summaryrefslogtreecommitdiffstats
path: root/src/libs/installer
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/installer')
-rw-r--r--src/libs/installer/adminauthorization_win.cpp6
-rw-r--r--src/libs/installer/adminauthorization_x11.cpp66
-rw-r--r--src/libs/installer/binarycontent.cpp10
-rw-r--r--src/libs/installer/binaryformat.cpp4
-rw-r--r--src/libs/installer/component.cpp149
-rw-r--r--src/libs/installer/component.h28
-rw-r--r--src/libs/installer/componentchecker.cpp12
-rw-r--r--src/libs/installer/componentmodel.cpp18
-rw-r--r--src/libs/installer/constants.h11
-rw-r--r--src/libs/installer/consumeoutputoperation.cpp31
-rw-r--r--src/libs/installer/consumeoutputoperation.h3
-rw-r--r--src/libs/installer/copydirectoryoperation.cpp48
-rw-r--r--src/libs/installer/copydirectoryoperation.h3
-rw-r--r--src/libs/installer/copyfiletask.cpp13
-rw-r--r--src/libs/installer/createdesktopentryoperation.cpp29
-rw-r--r--src/libs/installer/createdesktopentryoperation.h3
-rw-r--r--src/libs/installer/createlinkoperation.cpp24
-rw-r--r--src/libs/installer/createlinkoperation.h3
-rw-r--r--src/libs/installer/createlocalrepositoryoperation.cpp70
-rw-r--r--src/libs/installer/createlocalrepositoryoperation.h3
-rw-r--r--src/libs/installer/createshortcutoperation.cpp125
-rw-r--r--src/libs/installer/createshortcutoperation.h12
-rw-r--r--src/libs/installer/downloadarchivesjob.cpp36
-rw-r--r--src/libs/installer/downloadarchivesjob.h4
-rw-r--r--src/libs/installer/downloadfiletask.cpp76
-rw-r--r--src/libs/installer/downloadfiletask.h2
-rw-r--r--src/libs/installer/downloadfiletask_p.h4
-rw-r--r--src/libs/installer/elevatedexecuteoperation.cpp34
-rw-r--r--src/libs/installer/elevatedexecuteoperation.h13
-rw-r--r--src/libs/installer/environmentvariablesoperation.cpp32
-rw-r--r--src/libs/installer/environmentvariablesoperation.h3
-rw-r--r--src/libs/installer/errors.h12
-rw-r--r--src/libs/installer/extractarchiveoperation.cpp74
-rw-r--r--src/libs/installer/extractarchiveoperation.h3
-rw-r--r--src/libs/installer/extractarchiveoperation_p.h144
-rw-r--r--src/libs/installer/fakestopprocessforupdateoperation.cpp17
-rw-r--r--src/libs/installer/fakestopprocessforupdateoperation.h3
-rw-r--r--src/libs/installer/fileio.cpp12
-rw-r--r--src/libs/installer/fileutils.cpp67
-rw-r--r--src/libs/installer/fileutils.h2
-rw-r--r--src/libs/installer/globals.cpp5
-rw-r--r--src/libs/installer/globals.h1
-rw-r--r--src/libs/installer/globalsettingsoperation.cpp20
-rw-r--r--src/libs/installer/globalsettingsoperation.h3
-rw-r--r--src/libs/installer/init.cpp64
-rw-r--r--src/libs/installer/installer.pro12
-rw-r--r--src/libs/installer/installercalculator.cpp78
-rw-r--r--src/libs/installer/installercalculator.h4
-rw-r--r--src/libs/installer/installiconsoperation.cpp48
-rw-r--r--src/libs/installer/installiconsoperation.h3
-rw-r--r--src/libs/installer/keepaliveobject.cpp4
-rw-r--r--src/libs/installer/lib7z_create.h (renamed from src/libs/installer/localsocket.h)73
-rw-r--r--src/libs/installer/lib7z_extract.h85
-rw-r--r--src/libs/installer/lib7z_facade.cpp1860
-rw-r--r--src/libs/installer/lib7z_facade.h261
-rw-r--r--src/libs/installer/lib7z_guid.h97
-rw-r--r--src/libs/installer/lib7z_list.h62
-rw-r--r--src/libs/installer/licenseoperation.cpp23
-rw-r--r--src/libs/installer/licenseoperation.h3
-rw-r--r--src/libs/installer/linereplaceoperation.cpp24
-rw-r--r--src/libs/installer/linereplaceoperation.h3
-rw-r--r--src/libs/installer/link.cpp26
-rw-r--r--src/libs/installer/messageboxhandler.cpp4
-rw-r--r--src/libs/installer/metadatajob.cpp275
-rw-r--r--src/libs/installer/metadatajob.h13
-rw-r--r--src/libs/installer/metadatajob_p.h15
-rw-r--r--src/libs/installer/minimumprogressoperation.cpp9
-rw-r--r--src/libs/installer/minimumprogressoperation.h3
-rw-r--r--src/libs/installer/packagemanagercore.cpp350
-rw-r--r--src/libs/installer/packagemanagercore.h20
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp446
-rw-r--r--src/libs/installer/packagemanagercore_p.h51
-rw-r--r--src/libs/installer/packagemanagercoredata.cpp108
-rw-r--r--src/libs/installer/packagemanagercoredata.h3
-rw-r--r--src/libs/installer/packagemanagergui.cpp507
-rw-r--r--src/libs/installer/packagemanagergui.h12
-rw-r--r--src/libs/installer/packagemanagerpagefactory.cpp5
-rw-r--r--src/libs/installer/packagemanagerpagefactory.h13
-rw-r--r--src/libs/installer/packagemanagerproxyfactory.cpp2
-rw-r--r--src/libs/installer/packagemanagerproxyfactory.h2
-rw-r--r--src/libs/installer/packagesource.cpp91
-rw-r--r--src/libs/installer/packagesource.h63
-rw-r--r--src/libs/installer/performinstallationform.cpp11
-rw-r--r--src/libs/installer/productkeycheck.cpp5
-rw-r--r--src/libs/installer/productkeycheck.h1
-rw-r--r--src/libs/installer/progresscoordinator.cpp2
-rw-r--r--src/libs/installer/proxycredentialsdialog.h4
-rw-r--r--src/libs/installer/qinstallerglobal.h9
-rw-r--r--src/libs/installer/qprocesswrapper.cpp24
-rw-r--r--src/libs/installer/qprocesswrapper.h1
-rw-r--r--src/libs/installer/qtpatch.cpp14
-rw-r--r--src/libs/installer/registerfiletypeoperation.cpp72
-rw-r--r--src/libs/installer/registerfiletypeoperation.h9
-rw-r--r--src/libs/installer/remoteclient.cpp19
-rw-r--r--src/libs/installer/remoteclient.h3
-rw-r--r--src/libs/installer/remoteclient_p.h25
-rw-r--r--src/libs/installer/remoteobject.cpp6
-rw-r--r--src/libs/installer/remoteobject.h2
-rw-r--r--src/libs/installer/remoteserver.cpp8
-rw-r--r--src/libs/installer/remoteserver_p.h6
-rw-r--r--src/libs/installer/remoteserverconnection.cpp7
-rw-r--r--src/libs/installer/remoteserverconnection_p.h24
-rw-r--r--src/libs/installer/replaceoperation.cpp24
-rw-r--r--src/libs/installer/replaceoperation.h3
-rw-r--r--src/libs/installer/repository.cpp37
-rw-r--r--src/libs/installer/repository.h7
-rw-r--r--src/libs/installer/resources/install.pngbin0 -> 268 bytes
-rw-r--r--src/libs/installer/resources/installer.qrc4
-rw-r--r--src/libs/installer/resources/keepinstalled.pngbin0 -> 239 bytes
-rw-r--r--src/libs/installer/resources/keepuninstalled.pngbin0 -> 203 bytes
-rw-r--r--src/libs/installer/resources/uninstall.pngbin0 -> 240 bytes
-rw-r--r--src/libs/installer/scriptengine.cpp26
-rw-r--r--src/libs/installer/scriptengine_p.h6
-rw-r--r--src/libs/installer/selfrestartoperation.cpp24
-rw-r--r--src/libs/installer/selfrestartoperation.h3
-rw-r--r--src/libs/installer/settings.cpp82
-rw-r--r--src/libs/installer/settings.h5
-rw-r--r--src/libs/installer/settingsoperation.cpp19
-rw-r--r--src/libs/installer/settingsoperation.h3
-rw-r--r--src/libs/installer/simplemovefileoperation.cpp36
-rw-r--r--src/libs/installer/simplemovefileoperation.h3
-rw-r--r--src/libs/installer/sysinfo_win.cpp2
-rw-r--r--src/libs/installer/testrepository.cpp166
-rw-r--r--src/libs/installer/testrepository.h52
-rw-r--r--src/libs/installer/unziptask.cpp50
-rw-r--r--src/libs/installer/utils.cpp56
-rw-r--r--src/libs/installer/utils.h16
127 files changed, 3768 insertions, 3068 deletions
diff --git a/src/libs/installer/adminauthorization_win.cpp b/src/libs/installer/adminauthorization_win.cpp
index 721c36de1..3ad193b5e 100644
--- a/src/libs/installer/adminauthorization_win.cpp
+++ b/src/libs/installer/adminauthorization_win.cpp
@@ -106,14 +106,14 @@ bool AdminAuthorization::execute(QWidget *, const QString &program, const QStrin
shellExecuteInfo.lpParameters = (wchar_t *)args.utf16();
shellExecuteInfo.fMask = SEE_MASK_NOASYNC;
- qDebug() << QString::fromLatin1("Starting elevated process %1 with arguments: %2.").arg(file, args);
+ qDebug() << "Starting elevated process" << file << "with arguments" << args;
if (ShellExecuteExW(&shellExecuteInfo)) {
qDebug() << "Finished starting elevated process.";
return true;
} else {
- qWarning() << QString::fromLatin1("Error while starting elevated process: %1, "
- "Error: %2").arg(program, QInstaller::windowsErrorString(GetLastError()));
+ qWarning() << "Error while starting elevated process" << program
+ << ":" << QInstaller::windowsErrorString(GetLastError());
}
return false;
}
diff --git a/src/libs/installer/adminauthorization_x11.cpp b/src/libs/installer/adminauthorization_x11.cpp
index 1146519d2..7068bb2c6 100644
--- a/src/libs/installer/adminauthorization_x11.cpp
+++ b/src/libs/installer/adminauthorization_x11.cpp
@@ -55,6 +55,7 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <errno.h>
#include <iostream>
@@ -130,10 +131,14 @@ bool AdminAuthorization::execute(QWidget *parent, const QString &program, const
if (pipe(pipedData) != 0)
return false;
- int flags = ::fcntl(pipedData[0], F_GETFD);
+ int flags = ::fcntl(pipedData[0], F_GETFL);
if (flags != -1)
::fcntl(pipedData[0], F_SETFL, flags | O_NONBLOCK);
+ flags = ::fcntl(masterFD, F_GETFL);
+ if (flags != -1)
+ ::fcntl(masterFD, F_SETFL, flags | O_NONBLOCK);
+
pid_t child = fork();
if (child < -1) {
@@ -151,25 +156,36 @@ bool AdminAuthorization::execute(QWidget *parent, const QString &program, const
::close(pipedData[1]);
QRegExp re(QLatin1String("[Pp]assword.*:"));
+ QByteArray data;
QByteArray errData;
- flags = ::fcntl(masterFD, F_GETFD);
int bytes = 0;
int errBytes = 0;
char buf[1024];
char errBuf[1024];
+ int status;
+ bool statusValid = false;
while (bytes >= 0) {
- int state;
- if (::waitpid(child, &state, WNOHANG) == -1)
+ const pid_t waitResult = ::waitpid(child, &status, WNOHANG);
+ if (waitResult == -1) {
break;
+ }
+ if (waitResult == child) {
+ statusValid = true;
+ break;
+ }
bytes = ::read(masterFD, buf, 1023);
+ if (bytes == -1 && errno == EAGAIN)
+ bytes = 0;
+ else if (bytes > 0)
+ data.append(buf, bytes);
errBytes = ::read(pipedData[0], errBuf, 1023);
if (errBytes > 0)
{
- errData.append(buf, errBytes);
+ errData.append(errBuf, errBytes);
errBytes=0;
}
if (bytes > 0) {
- const QString line = QString::fromLatin1(buf, bytes);
+ const QString line = QString::fromLatin1(data);
if (re.indexIn(line) != -1) {
const QString password = getPassword(parent);
if (password.isEmpty()) {
@@ -189,20 +205,28 @@ bool AdminAuthorization::execute(QWidget *parent, const QString &program, const
if (bytes == 0)
::usleep(100000);
}
- if (!errData.isEmpty()) {
- printError(parent, QString::fromLocal8Bit(errData.constData()));
- return false;
+
+ while (true) {
+ errBytes = ::read(pipedData[0], errBuf, 1023);
+ if (errBytes == -1 && errno == EAGAIN) {
+ ::usleep(100000);
+ continue;
+ }
+
+ if (errBytes <= 0)
+ break;
+
+ errData.append(errBuf, errBytes);
}
- int status;
- child = ::wait(&status);
- const int exited = WIFEXITED(status);
- const int exitStatus = WEXITSTATUS(status);
- ::close(pipedData[1]);
- if (exited)
- return exitStatus == 0;
+ const bool success = statusValid && WIFEXITED(status) && WEXITSTATUS(status) == 0;
- return false;
+ if (!success && !errData.isEmpty()) {
+ printError(parent, QString::fromLocal8Bit(errData.constData()));
+ }
+
+ ::close(pipedData[0]);
+ return success;
}
// child process
@@ -229,7 +253,7 @@ bool AdminAuthorization::execute(QWidget *parent, const QString &program, const
for (int i = 3; i < static_cast<int>(rlp.rlim_cur); ++i)
::close(i);
- char **argp = (char **) ::malloc(arguments.count() + 4 * sizeof(char *));
+ char **argp = (char **) ::malloc((arguments.count() + 4) * sizeof(char *));
QList<QByteArray> args;
args.push_back(SU_COMMAND);
args.push_back("-b");
@@ -245,8 +269,10 @@ bool AdminAuthorization::execute(QWidget *parent, const QString &program, const
::unsetenv("LANG");
::unsetenv("LC_ALL");
- ::execv(SU_COMMAND, argp);
- _exit(0);
+ int exitStatus = 0;
+ if (::execv(SU_COMMAND, argp) == -1)
+ exitStatus = -errno;
+ _exit(exitStatus);
return false;
}
}
diff --git a/src/libs/installer/binarycontent.cpp b/src/libs/installer/binarycontent.cpp
index d32be6238..6112704b0 100644
--- a/src/libs/installer/binarycontent.cpp
+++ b/src/libs/installer/binarycontent.cpp
@@ -113,7 +113,7 @@ BinaryLayout BinaryContent::binaryLayout(QFile *file, quint64 magicCookie)
const qint64 posOfMetaDataCount = layout.endOfBinaryContent - (4 * sizeof(qint64));
if (!file->seek(posOfMetaDataCount)) {
throw QInstaller::Error(QCoreApplication::translate("BinaryLayout",
- "Could not seek to %1 to read the embedded meta data count.").arg(posOfMetaDataCount));
+ "Cannot seek to %1 to read the embedded meta data count.").arg(posOfMetaDataCount));
}
// read the meta resources count
@@ -124,7 +124,7 @@ BinaryLayout BinaryContent::binaryLayout(QFile *file, quint64 magicCookie)
+ (8 * sizeof(qint64))); // meta count, offset/length collection index, marker, cookie...
if (!file->seek(posOfResourceCollectionsSegment)) {
throw Error(QCoreApplication::translate("BinaryLayout",
- "Could not seek to %1 to read the resource collection segment.")
+ "Cannot seek to %1 to read the resource collection segment.")
.arg(posOfResourceCollectionsSegment));
}
@@ -199,7 +199,7 @@ void BinaryContent::readBinaryContent(QFile *file, QList<OperationBlob> *operati
const qint64 posOfOperationsBlock = layout.operationsSegment.start();
if (!file->seek(posOfOperationsBlock)) {
throw Error(QCoreApplication::translate("BinaryContent",
- "Could not seek to %1 to read the operation data.").arg(posOfOperationsBlock));
+ "Cannot seek to %1 to read the operation data.").arg(posOfOperationsBlock));
}
// read the operations count
qint64 operationsCount = QInstaller::retrieveInt64(file);
@@ -216,7 +216,7 @@ void BinaryContent::readBinaryContent(QFile *file, QList<OperationBlob> *operati
if (manager) { // read the collection index and data
const qint64 posOfResourceCollectionBlock = layout.resourceCollectionsSegment.start();
if (!file->seek(posOfResourceCollectionBlock)) {
- throw Error(QCoreApplication::translate("BinaryContent", "Could not seek to %1 to "
+ throw Error(QCoreApplication::translate("BinaryContent", "Cannot seek to %1 to "
"read the resource collection block.").arg(posOfResourceCollectionBlock));
}
manager->read(file, layout.endOfExectuable);
@@ -255,7 +255,7 @@ void BinaryContent::writeBinaryContent(QFile *out, const QList<OperationBlob> &o
const bool isOpen = resource->isOpen();
if ((!isOpen) && (!resource->open())) {
throw Error(QCoreApplication::translate("BinaryContent",
- "Could not open meta resource. Error: %1").arg(resource->errorString()));
+ "Cannot open meta resource %1.").arg(resource->errorString()));
}
resource->seek(0);
diff --git a/src/libs/installer/binaryformat.cpp b/src/libs/installer/binaryformat.cpp
index d9ca133c0..42c94ab1d 100644
--- a/src/libs/installer/binaryformat.cpp
+++ b/src/libs/installer/binaryformat.cpp
@@ -164,7 +164,7 @@ bool Resource::open()
}
if (!QIODevice::open(QIODevice::ReadOnly)) {
- setErrorString(tr("Could not open Resource '%1' read-only.").arg(QString::fromUtf8(m_name)));
+ setErrorString(tr("Cannot open resource %1 for reading.").arg(QString::fromUtf8(m_name)));
return false;
}
return true;
@@ -392,7 +392,7 @@ Range<qint64> ResourceCollectionManager::write(QFileDevice *out, qint64 offset)
foreach (const QSharedPointer<Resource> &resource, collection.resources()) {
if (!resource->open()) {
- throw QInstaller::Error(tr("Could not open resource %1: %2")
+ throw QInstaller::Error(tr("Cannot open resource %1: %2")
.arg(QString::fromUtf8(resource->name()), resource->errorString()));
}
resource->copyData(out);
diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp
index 38e8cd844..da0230ade 100644
--- a/src/libs/installer/component.cpp
+++ b/src/libs/installer/component.cpp
@@ -38,8 +38,7 @@
#include "settings.h"
#include "utils.h"
-#include <kdupdaterupdatesourcesinfo.h>
-#include <kdupdaterupdateoperationfactory.h>
+#include "updateoperationfactory.h"
#include <productkeycheck.h>
@@ -51,18 +50,22 @@
#include <QtUiTools/QUiLoader>
+#include <private/qv8engine_p.h>
+#include <private/qv4scopedvalue_p.h>
+#include <private/qv4object_p.h>
+
#include <algorithm>
using namespace QInstaller;
static const QLatin1String scScriptTag("Script");
-static const QLatin1String scAutoDependOn("AutoDependOn");
static const QLatin1String scVirtual("Virtual");
static const QLatin1String scInstalled("Installed");
static const QLatin1String scUpdateText("UpdateText");
static const QLatin1String scUninstalled("Uninstalled");
static const QLatin1String scCurrentState("CurrentState");
static const QLatin1String scForcedInstallation("ForcedInstallation");
+static const QLatin1String scCheckable("Checkable");
/*!
\inmodule QtInstallerFramework
@@ -208,7 +211,7 @@ Component::Component(PackageManagerCore *core)
{
setPrivate(d);
- connect(this, SIGNAL(valueChanged(QString, QString)), this, SLOT(updateModelData(QString, QString)));
+ connect(this, &Component::valueChanged, this, &Component::updateModelData);
qRegisterMetaType<QList<QInstaller::Component*> >("QList<QInstaller::Component*>");
}
@@ -237,10 +240,9 @@ Component::~Component()
/*!
Sets variables according to the values set in the package.xml file of a local \a package.
*/
-void Component::loadDataFromPackage(const LocalPackage &package)
+void Component::loadDataFromPackage(const KDUpdater::LocalPackage &package)
{
setValue(scName, package.name);
- // pixmap ???
setValue(scDisplayName, package.title);
setValue(scDescription, package.description);
setValue(scVersion, package.version);
@@ -249,14 +251,8 @@ void Component::loadDataFromPackage(const LocalPackage &package)
setValue(QLatin1String("LastUpdateDate"), package.lastUpdateDate.toString());
setValue(QLatin1String("InstallDate"), package.installDate.toString());
setValue(scUncompressedSize, QString::number(package.uncompressedSize));
-
- QString dependstr;
- foreach (const QString &val, package.dependencies)
- dependstr += val + QLatin1String(",");
-
- if (package.dependencies.count() > 0)
- dependstr.chop(1);
- setValue(scDependencies, dependstr);
+ setValue(scDependencies, package.dependencies.join(QLatin1String(",")));
+ setValue(scAutoDependOn, package.autoDependencies.join(QLatin1String(",")));
setValue(scForcedInstallation, package.forcedInstallation ? scTrue : scFalse);
if (package.forcedInstallation & !PackageManagerCore::noForceInstallation()) {
@@ -265,6 +261,7 @@ void Component::loadDataFromPackage(const LocalPackage &package)
}
setValue(scVirtual, package.virtualComp ? scTrue : scFalse);
setValue(scCurrentState, scInstalled);
+ setValue(scCheckable, package.checkable ? scTrue : scFalse);
}
/*!
@@ -282,7 +279,7 @@ void Component::loadDataFromPackage(const Package &package)
setValue(scAutoDependOn, package.data(scAutoDependOn).toString());
setValue(scCompressedSize, package.data(scCompressedSize).toString());
setValue(scUncompressedSize, package.data(scUncompressedSize).toString());
- setValue(scRemoteVersion, package.data(scRemoteVersion).toString());
+ setValue(scVersion, package.data(scVersion).toString());
setValue(scInheritVersion, package.data(scInheritVersion).toString());
setValue(scDependencies, package.data(scDependencies).toString());
setValue(scDownloadableArchives, package.data(scDownloadableArchives).toString());
@@ -297,6 +294,7 @@ void Component::loadDataFromPackage(const Package &package)
setValue(scScriptTag, package.data(scScriptTag).toString());
setValue(scReplaces, package.data(scReplaces).toString());
setValue(scReleaseDate, package.data(scReleaseDate).toString());
+ setValue(scCheckable, package.data(scCheckable).toString());
QString forced = package.data(scForcedInstallation, scFalse).toString().toLower();
if (PackageManagerCore::noForceInstallation())
@@ -307,7 +305,7 @@ void Component::loadDataFromPackage(const Package &package)
setCheckState(Qt::Checked);
}
- setLocalTempPath(QInstaller::pathFromUrl(package.sourceInfoUrl()));
+ setLocalTempPath(QInstaller::pathFromUrl(package.packageSource().url));
const QStringList uis = package.data(QLatin1String("UserInterfaces")).toString()
.split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
if (!uis.isEmpty())
@@ -388,6 +386,8 @@ void Component::setValue(const QString &key, const QString &value)
if (key == scName)
d->m_componentName = normalizedValue;
+ if (key == scCheckable)
+ this->setCheckable(normalizedValue.toLower() == scTrue);
d->m_vars[key] = normalizedValue;
emit valueChanged(key, normalizedValue);
@@ -570,8 +570,8 @@ void Component::loadUserInterfaces(const QDir &directory, const QStringList &uis
while (it.hasNext()) {
QFile file(it.next());
if (!file.open(QIODevice::ReadOnly)) {
- throw Error(tr("Could not open the requested UI file '%1'. Error: %2").arg(it.fileName(),
- file.errorString()));
+ throw Error(tr("Cannot open the requested UI file \"%1\": %2").arg(
+ it.fileName(), file.errorString()));
}
static QUiLoader loader;
@@ -579,8 +579,8 @@ void Component::loadUserInterfaces(const QDir &directory, const QStringList &uis
loader.setLanguageChangeEnabled(true);
QWidget *const widget = loader.load(&file, 0);
if (!widget) {
- throw Error(tr("Could not load the requested UI file '%1'. Error: %2").arg(it.fileName(),
- loader.errorString()));
+ throw Error(tr("Cannot load the requested UI file \"%1\": %2").arg(
+ it.fileName(), loader.errorString()));
}
d->scriptEngine()->newQObject(widget);
d->m_userInterfaces.insert(widget->objectName(), widget);
@@ -624,7 +624,7 @@ void Component::loadLicenses(const QString &directory, const QHash<QString, QVar
QFile file(fileInfo.filePath());
if (!file.open(QIODevice::ReadOnly)) {
- throw Error(tr("Could not open the requested license file '%1'. Error: %2").arg(
+ throw Error(tr("Cannot open the requested license file \"%1\": %2").arg(
file.fileName(), file.errorString()));
}
QTextStream stream(&file);
@@ -698,11 +698,11 @@ void Component::createOperationsForPath(const QString &path)
if (fi.isFile()) {
static const QString copy = QString::fromLatin1("Copy");
- addOperation(copy, fi.filePath(), target);
+ addOperation(copy, QStringList() << fi.filePath() << target);
} else if (fi.isDir()) {
qApp->processEvents();
static const QString mkdir = QString::fromLatin1("Mkdir");
- addOperation(mkdir, target);
+ addOperation(mkdir, QStringList(target));
QDirIterator it(fi.filePath());
while (it.hasNext())
@@ -742,7 +742,7 @@ void Component::createOperationsForArchive(const QString &archive)
if (isZip) {
// archives get completely extracted per default (if the script isn't doing other stuff)
- addOperation(QLatin1String("Extract"), archive, QLatin1String("@TargetDir@"));
+ addOperation(QLatin1String("Extract"), QStringList() << archive << QLatin1String("@TargetDir@"));
} else {
createOperationsForPath(archive);
}
@@ -823,7 +823,7 @@ void Component::addDownloadableArchive(const QString &path)
Q_ASSERT(isFromOnlineRepository());
qDebug() << "addDownloadable" << path;
- d->m_downloadableArchives.append(d->m_vars.value(scRemoteVersion) + path);
+ d->m_downloadableArchives.append(d->m_vars.value(scVersion) + path);
}
/*!
@@ -902,15 +902,14 @@ OperationList Component::operations() const
if (!d->m_minimumProgressOperation) {
d->m_minimumProgressOperation = KDUpdater::UpdateOperationFactory::instance()
- .create(QLatin1String("MinimumProgress"));
+ .create(QLatin1String("MinimumProgress"), d->m_core);
d->m_minimumProgressOperation->setValue(QLatin1String("component"), name());
d->m_operations.append(d->m_minimumProgressOperation);
}
if (!d->m_licenses.isEmpty()) {
d->m_licenseOperation = KDUpdater::UpdateOperationFactory::instance()
- .create(QLatin1String("License"));
- d->m_licenseOperation->setValue(QLatin1String("installer"), QVariant::fromValue(d->m_core));
+ .create(QLatin1String("License"), d->m_core);
d->m_licenseOperation->setValue(QLatin1String("component"), name());
QVariantMap licenses;
@@ -984,11 +983,12 @@ Operation *Component::createOperation(const QString &operationName, const QStrin
Operation *Component::createOperation(const QString &operationName, const QStringList &parameters)
{
- Operation *operation = KDUpdater::UpdateOperationFactory::instance().create(operationName);
+ Operation *operation = KDUpdater::UpdateOperationFactory::instance().create(operationName,
+ d->m_core);
if (operation == 0) {
const QMessageBox::StandardButton button =
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
- QLatin1String("OperationDoesNotExistError"), tr("Error"), tr("Error: Operation %1 does not exist")
+ QLatin1String("OperationDoesNotExistError"), tr("Error"), tr("Error: Operation %1 does not exist.")
.arg(operationName), QMessageBox::Abort | QMessageBox::Ignore);
if (button == QMessageBox::Abort)
d->m_operationsCreatedSuccessfully = false;
@@ -997,33 +997,50 @@ Operation *Component::createOperation(const QString &operationName, const QStrin
if (operation->name() == QLatin1String("Delete"))
operation->setValue(QLatin1String("performUndo"), false);
- operation->setValue(QLatin1String("installer"), qVariantFromValue(d->m_core));
operation->setArguments(d->m_core->replaceVariables(parameters));
operation->setValue(QLatin1String("component"), name());
return operation;
}
-/*!
- Convenience method for calling the operation \a operation with up to ten parameters:
- \a parameter1, \a parameter2, \a parameter3, \a parameter4, \a parameter5, \a parameter6,
- \a parameter7, \a parameter8, \a parameter9, and \a parameter10.
-
- Returns \c true if the operation succeeds, otherwise returns \c false.
+namespace {
- \sa {component::addOperation}{component.addOperation}
-*/
-bool Component::addOperation(const QString &operation, const QString &parameter1, const QString &parameter2,
- const QString &parameter3, const QString &parameter4, const QString &parameter5, const QString &parameter6,
- const QString &parameter7, const QString &parameter8, const QString &parameter9, const QString &parameter10)
+inline bool convert(QQmlV4Function *func, QStringList *toArgs)
{
+ if (func->length() < 2)
+ return false;
- if (Operation *op = createOperation(operation, parameter1, parameter2, parameter3, parameter4, parameter5,
- parameter6, parameter7, parameter8, parameter9, parameter10)) {
- addOperation(op);
- return true;
+ QV4::Scope scope(func->v4engine());
+ QV4::ScopedValue val(scope);
+ val = (*func)[0];
+
+ *toArgs << val->toQString();
+ for (int i = 1; i < func->length(); i++) {
+ val = (*func)[i];
+ if (val->isObject() && val->as<QV4::Object>()->isArrayObject()) {
+ QV4::ScopedValue valtmp(scope);
+ QV4::Object *array = val->as<QV4::Object>();
+ uint length = array->getLength();
+ for (uint ii = 0; ii < length; ++ii) {
+ valtmp = array->getIndexed(ii);
+ *toArgs << valtmp->toQStringNoThrow();
+ }
+ } else {
+ *toArgs << val->toQString();
+ }
}
+ return true;
+}
+}
+/*!
+ \internal
+*/
+bool Component::addOperation(QQmlV4Function *func)
+{
+ QStringList args;
+ if (convert(func, &args))
+ return addOperation(args[0], args.mid(1));
return false;
}
@@ -1032,7 +1049,7 @@ bool Component::addOperation(const QString &operation, const QString &parameter1
The variables that the parameters contain, such as \c @TargetDir@, are replaced with their
values.
- Returns \c true if the operation succeeds, otherwise returns \c false.
+ \sa {component::addOperation}{component.addOperation}
*/
bool Component::addOperation(const QString &operation, const QStringList &parameters)
{
@@ -1045,25 +1062,13 @@ bool Component::addOperation(const QString &operation, const QStringList &parame
}
/*!
- Convenience method for calling the elevated operation \a operation with up to ten parameters:
- \a parameter1, \a parameter2, \a parameter3, \a parameter4, \a parameter5, \a parameter6,
- \a parameter7, \a parameter8, \a parameter9, and \a parameter10.
-
- \sa {component::addElevatedOperation}{component.addElevatedOperation}
-
- Returns \c true if the operation succeeds, otherwise returns \c false.
+ \internal
*/
-bool Component::addElevatedOperation(const QString &operation, const QString &parameter1,
- const QString &parameter2, const QString &parameter3, const QString &parameter4, const QString &parameter5,
- const QString &parameter6, const QString &parameter7, const QString &parameter8, const QString &parameter9,
- const QString &parameter10)
+bool Component::addElevatedOperation(QQmlV4Function *func)
{
- if (Operation *op = createOperation(operation, parameter1, parameter2, parameter3, parameter4, parameter5,
- parameter6, parameter7, parameter8, parameter9, parameter10)) {
- addElevatedOperation(op);
- return true;
- }
-
+ QStringList args;
+ if (convert(func, &args))
+ return addElevatedOperation(args[0], args.mid(1));
return false;
}
@@ -1072,8 +1077,7 @@ bool Component::addElevatedOperation(const QString &operation, const QString &pa
The variables that the parameters contain, such as \c @TargetDir@, are replaced with their
values. The operation is executed with elevated rights.
- Returns \c true if the operation succeeds, otherwise returns \c false.
-
+ \sa {component::addElevatedOperation}{component.addElevatedOperation}
*/
bool Component::addElevatedOperation(const QString &operation, const QStringList &parameters)
{
@@ -1086,9 +1090,8 @@ bool Component::addElevatedOperation(const QString &operation, const QStringList
}
/*!
- Returns whether operations should be automatically created when the
- installation starts and createOperations() is called. If you set this to
- \c false, it is completely up
+ Specifies whether operations should be automatically created when the installation starts. This
+ would be done by calling createOperations(). If you set this to \c false, it is completely up
to the component's script to create all operations.
\sa {component::autoCreateOperations}{component.autoCreateOperations}
@@ -1239,9 +1242,13 @@ bool Component::isDefault() const
return d->m_vars.value(scDefault).compare(scTrue, Qt::CaseInsensitive) == 0;
}
-bool Component::isInstalled() const
+bool Component::isInstalled(const QString version) const
{
- return scInstalled == d->m_vars.value(scCurrentState);
+ if (version.isEmpty()) {
+ return scInstalled == d->m_vars.value(scCurrentState);
+ } else {
+ return d->m_vars.value(scInstalledVersion) == version;
+ }
}
/*!
diff --git a/src/libs/installer/component.h b/src/libs/installer/component.h
index 4f4623aba..01622548f 100644
--- a/src/libs/installer/component.h
+++ b/src/libs/installer/component.h
@@ -39,11 +39,7 @@
#include <QtCore/QUrl>
QT_FORWARD_DECLARE_CLASS(QDebug)
-
-namespace KDUpdater {
- class Update;
- struct PackageInfo;
-}
+QT_FORWARD_DECLARE_CLASS(QQmlV4Function)
namespace QInstaller {
@@ -96,7 +92,7 @@ public:
};
void loadDataFromPackage(const Package &package);
- void loadDataFromPackage(const LocalPackage &package);
+ void loadDataFromPackage(const KDUpdater::LocalPackage &package);
QHash<QString, QString> variables() const;
Q_INVOKABLE void setValue(const QString &key, const QString &value);
@@ -133,22 +129,12 @@ public:
OperationList operations() const;
void addOperation(Operation *operation);
- Q_INVOKABLE bool addOperation(const QString &operation, const QString &parameter1 = QString(),
- const QString &parameter2 = QString(), const QString &parameter3 = QString(),
- const QString &parameter4 = QString(), const QString &parameter5 = QString(),
- const QString &parameter6 = QString(), const QString &parameter7 = QString(),
- const QString &parameter8 = QString(), const QString &parameter9 = QString(),
- const QString &parameter10 = QString());
- Q_INVOKABLE bool addOperation(const QString &operation, const QStringList &parameters);
+ Q_INVOKABLE bool addOperation(QQmlV4Function *args);
+ bool addOperation(const QString &operation, const QStringList &parameters);
void addElevatedOperation(Operation *operation);
- Q_INVOKABLE bool addElevatedOperation(const QString &operation,
- const QString &parameter1 = QString(), const QString &parameter2 = QString(),
- const QString &parameter3 = QString(), const QString &parameter4 = QString(),
- const QString &parameter5 = QString(), const QString &parameter6 = QString(),
- const QString &parameter7 = QString(), const QString &parameter8 = QString(),
- const QString &parameter9 = QString(), const QString &parameter10 = QString());
- Q_INVOKABLE bool addElevatedOperation(const QString &operation, const QStringList &parameters);
+ Q_INVOKABLE bool addElevatedOperation(QQmlV4Function *args);
+ bool addElevatedOperation(const QString &operation, const QStringList &parameters);
QStringList downloadableArchives() const;
Q_INVOKABLE void addDownloadableArchive(const QString &path);
@@ -180,7 +166,7 @@ public:
Q_INVOKABLE bool isAutoDependOn(const QSet<QString> &componentsToInstall) const;
Q_INVOKABLE void setInstalled();
- Q_INVOKABLE bool isInstalled() const;
+ Q_INVOKABLE bool isInstalled(const QString version = QString()) const;
Q_INVOKABLE bool installationRequested() const;
bool isSelectedForInstallation() const;
diff --git a/src/libs/installer/componentchecker.cpp b/src/libs/installer/componentchecker.cpp
index d905786f3..e21bc6696 100644
--- a/src/libs/installer/componentchecker.cpp
+++ b/src/libs/installer/componentchecker.cpp
@@ -45,6 +45,12 @@ QStringList ComponentChecker::checkComponent(Component *component)
if (!core)
return checkResult;
+ if (component->childCount() && !component->archives().isEmpty()) {
+ checkResult << QString::fromLatin1("Component %1 contains data to be installed "
+ "while having child components. This may not work properly.")
+ .arg(component->name());
+ }
+
const bool defaultPropertyScriptValue = component->variables().value(scDefault).compare(scScript, Qt::CaseInsensitive) == 0;
const bool defaultPropertyValue = component->variables().value(scDefault).compare(scTrue, Qt::CaseInsensitive) == 0;
const QStringList autoDependencies = component->autoDependencies();
@@ -122,13 +128,13 @@ QStringList ComponentChecker::checkComponent(Component *component)
Moreover, the "Next" button will be disabled.
*/
checkResult << QString::fromLatin1("Component %1 auto depends on other components "
- "while having children components. This will not work properly.")
+ "while having child components. This will not work properly.")
.arg(component->name());
}
if (!component->dependencies().isEmpty()) {
checkResult << QString::fromLatin1("Component %1 depends on other components "
- "while having children components. This will not work properly.")
+ "while having child components. This will not work properly.")
.arg(component->name());
}
@@ -148,7 +154,7 @@ QStringList ComponentChecker::checkComponent(Component *component)
Moreover, the "Next" button will be disabled.
*/
checkResult << QString::fromLatin1("Other components depend on component %1 "
- "which has children components. This will not work properly.")
+ "which has child components. This will not work properly.")
.arg(component->name());
}
}
diff --git a/src/libs/installer/componentmodel.cpp b/src/libs/installer/componentmodel.cpp
index ba4c2d238..e0cc3fcd8 100644
--- a/src/libs/installer/componentmodel.cpp
+++ b/src/libs/installer/componentmodel.cpp
@@ -77,6 +77,10 @@ class IconCache
{
public:
IconCache() {
+ m_icons.insert(ComponentModelHelper::Install, QIcon(QLatin1String(":/install.png")));
+ m_icons.insert(ComponentModelHelper::Uninstall, QIcon(QLatin1String(":/uninstall.png")));
+ m_icons.insert(ComponentModelHelper::KeepInstalled, QIcon(QLatin1String(":/keepinstalled.png")));
+ m_icons.insert(ComponentModelHelper::KeepUninstalled, QIcon(QLatin1String(":/keepuninstalled.png")));
}
QIcon icon(ComponentModelHelper::InstallAction action) const {
@@ -97,7 +101,7 @@ ComponentModel::ComponentModel(int columns, PackageManagerCore *core)
, m_modelState(DefaultChecked)
{
m_headerData.insert(0, columns, QVariant());
- connect(this, SIGNAL(modelReset()), this, SLOT(slotModelReset()));
+ connect(this, &QAbstractItemModel::modelReset, this, &ComponentModel::slotModelReset);
}
/*!
@@ -403,7 +407,7 @@ void ComponentModel::setRootComponents(QList<QInstaller::Component*> rootCompone
// show virtual components only in case we run as updater or if the core engine is set to show them
const bool showVirtuals = m_core->isUpdater() || m_core->virtualComponentsVisible();
foreach (Component *const component, rootComponents) {
- connect(component, SIGNAL(virtualStateChanged()), this, SLOT(onVirtualStateChanged()));
+ connect(component, &Component::virtualStateChanged, this, &ComponentModel::onVirtualStateChanged);
if ((!showVirtuals) && component->isVirtual())
continue;
m_rootComponentList.append(component);
@@ -463,7 +467,7 @@ void ComponentModel::slotModelReset()
foreach (Component *const component, components) {
if (component->checkState() == Qt::Checked)
checked.insert(component);
- connect(component, SIGNAL(virtualStateChanged()), this, SLOT(onVirtualStateChanged()));
+ connect(component, &Component::virtualStateChanged, this, &ComponentModel::onVirtualStateChanged);
}
updateCheckedState(checked, Qt::Checked);
@@ -571,7 +575,13 @@ QSet<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &compone
// we can start in descending order to check node and tri-state nodes properly
for (int i = sortedNodes.count(); i > 0; i--) {
Component * const node = sortedNodes.at(i - 1);
- if (!node->isCheckable() || !node->isEnabled() || !node->autoDependencies().isEmpty())
+
+ bool checkable = true;
+ if (node->value(scCheckable, scTrue).toLower() == scFalse) {
+ checkable = false;
+ }
+
+ if ((!node->isCheckable() && checkable) || !node->isEnabled() || !node->autoDependencies().isEmpty())
continue;
Qt::CheckState newState = state;
diff --git a/src/libs/installer/constants.h b/src/libs/installer/constants.h
index 6022b074b..f1eac9926 100644
--- a/src/libs/installer/constants.h
+++ b/src/libs/installer/constants.h
@@ -41,7 +41,6 @@ static const QLatin1String scScript("script");
static const QLatin1String scName("Name");
static const QLatin1String scVersion("Version");
static const QLatin1String scDefault("Default");
-static const QLatin1String scRemoteVersion("Version");
static const QLatin1String scDisplayVersion("DisplayVersion");
static const QLatin1String scRemoteDisplayVersion("RemoteDisplayVersion");
static const QLatin1String scInheritVersion("inheritVersionFrom");
@@ -53,6 +52,7 @@ static const QLatin1String scReleaseDate("ReleaseDate");
static const QLatin1String scDescription("Description");
static const QLatin1String scDisplayName("DisplayName");
static const QLatin1String scDependencies("Dependencies");
+static const QLatin1String scAutoDependOn("AutoDependOn");
static const QLatin1String scNewComponent("NewComponent");
static const QLatin1String scRepositories("Repositories");
static const QLatin1String scCompressedSize("CompressedSize");
@@ -64,6 +64,7 @@ static const QLatin1String scRequiresAdminRights("RequiresAdminRights");
// constants used throughout the components class
static const QLatin1String scVirtual("Virtual");
static const QLatin1String scSortingPriority("SortingPriority");
+static const QLatin1String scCheckable("Checkable");
// constants used throughout the settings and package manager core class
static const QLatin1String scTitle("Title");
@@ -75,13 +76,21 @@ static const QLatin1String scRemoveTargetDir("RemoveTargetDir");
static const QLatin1String scRunProgramDescription("RunProgramDescription");
static const QLatin1String scTargetConfigurationFile("TargetConfigurationFile");
static const QLatin1String scAllowNonAsciiCharacters("AllowNonAsciiCharacters");
+static const QLatin1String scDisableAuthorizationFallback("DisableAuthorizationFallback");
static const QLatin1String scRepositorySettingsPageVisible("RepositorySettingsPageVisible");
static const QLatin1String scAllowSpaceInPath("AllowSpaceInPath");
static const QLatin1String scWizardStyle("WizardStyle");
+static const QLatin1String scStyleSheet("StyleSheet");
static const QLatin1String scTitleColor("TitleColor");
static const QLatin1String scWizardDefaultWidth("WizardDefaultWidth");
static const QLatin1String scWizardDefaultHeight("WizardDefaultHeight");
+static const QLatin1String scUrlQueryString("UrlQueryString");
static const QLatin1String scProductUUID("ProductUUID");
+static const QLatin1String scAllUsers("AllUsers");
+static const QLatin1String scSupportsModify("SupportsModify");
+
+const char scRelocatable[] = "@RELOCATABLE_PATH@";
+
}
#endif // CONSTANTS_H
diff --git a/src/libs/installer/consumeoutputoperation.cpp b/src/libs/installer/consumeoutputoperation.cpp
index 8bd9d59f1..43c78193c 100644
--- a/src/libs/installer/consumeoutputoperation.cpp
+++ b/src/libs/installer/consumeoutputoperation.cpp
@@ -37,7 +37,8 @@
using namespace QInstaller;
-ConsumeOutputOperation::ConsumeOutputOperation()
+ConsumeOutputOperation::ConsumeOutputOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("ConsumeOutput"));
}
@@ -53,15 +54,12 @@ bool ConsumeOutputOperation::performOperation()
// 2. executable path
// 3. argument for the executable
// 4. more arguments possible ...
- if (arguments().count() < 3) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.").arg(name()).arg(
- arguments().count()).arg(tr("at least 2"), QLatin1String("(<to be saved installer key name>, "
- "<executable>, [argument1], [argument2], ...)")));
+
+ if (!checkArgumentCount(2, INT_MAX, tr("<to be saved installer key name> "
+ "<executable> [argument1] [argument2] [...]")))
return false;
- }
- PackageManagerCore *const core = value(QLatin1String("installer")).value<PackageManagerCore*>();
+ PackageManagerCore *const core = packageManager();
if (!core) {
setError(UserDefinedError);
setErrorString(tr("Needed installer object in %1 operation is empty.").arg(name()));
@@ -71,8 +69,8 @@ bool ConsumeOutputOperation::performOperation()
const QString installerKeyName = arguments().at(0);
if (installerKeyName.isEmpty()) {
setError(UserDefinedError);
- setErrorString(tr("Can not save the output of %1 to an empty installer key value.").arg(
- arguments().at(1)));
+ setErrorString(tr("Cannot save the output of \"%1\" to an empty installer key value.").arg(
+ QDir::toNativeSeparators(arguments().at(1))));
return false;
}
@@ -85,7 +83,7 @@ bool ConsumeOutputOperation::performOperation()
if (!executable.exists() || !executable.isExecutable()) {
setError(UserDefinedError);
- setErrorString(tr("File '%1' does not exist or is not an executable binary.").arg(
+ setErrorString(tr("File \"%1\" does not exist or is not an executable binary.").arg(
QDir::toNativeSeparators(executable.absoluteFilePath())));
return false;
}
@@ -106,7 +104,7 @@ bool ConsumeOutputOperation::performOperation()
<< "standard output: " << process.readAllStandardOutput()
<< "error output: " << process.readAllStandardError();
setError(UserDefinedError);
- setErrorString(tr("Running '%1' resulted in a crash.").arg(
+ setErrorString(tr("Running \"%1\" resulted in a crash.").arg(
QDir::toNativeSeparators(executable.absoluteFilePath())));
return false;
}
@@ -124,8 +122,7 @@ bool ConsumeOutputOperation::performOperation()
}
if (executableOutput.isEmpty()) {
- qWarning() << QString::fromLatin1("Cannot get any query output from executable: '%1'").arg(
- executable.absoluteFilePath());
+ qWarning() << "Cannot get any query output from executable" << executable.absoluteFilePath();
}
core->setValue(installerKeyName, QString::fromLocal8Bit(executableOutput));
return true;
@@ -140,9 +137,3 @@ bool ConsumeOutputOperation::testOperation()
{
return true;
}
-
-Operation *ConsumeOutputOperation::clone() const
-{
- return new ConsumeOutputOperation();
-}
-
diff --git a/src/libs/installer/consumeoutputoperation.h b/src/libs/installer/consumeoutputoperation.h
index ff7629e6e..a1f8a09ff 100644
--- a/src/libs/installer/consumeoutputoperation.h
+++ b/src/libs/installer/consumeoutputoperation.h
@@ -37,13 +37,12 @@ class INSTALLER_EXPORT ConsumeOutputOperation : public Operation
{
Q_DECLARE_TR_FUNCTIONS(QInstaller::ConsumeOutputOperation)
public:
- ConsumeOutputOperation();
+ explicit ConsumeOutputOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
private:
};
diff --git a/src/libs/installer/copydirectoryoperation.cpp b/src/libs/installer/copydirectoryoperation.cpp
index 20358ca66..cdd6da6ab 100644
--- a/src/libs/installer/copydirectoryoperation.cpp
+++ b/src/libs/installer/copydirectoryoperation.cpp
@@ -46,7 +46,8 @@ public:
};
-CopyDirectoryOperation::CopyDirectoryOperation()
+CopyDirectoryOperation::CopyDirectoryOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("CopyDirectory"));
}
@@ -57,13 +58,10 @@ void CopyDirectoryOperation::backup()
bool CopyDirectoryOperation::performOperation()
{
- const QStringList args = arguments();
- if (args.count() < 2 || args.count() > 3) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("2 or 3"), tr(" (<source> <target> [forceOverwrite])")));
+ if (!checkArgumentCount(2, 3, tr("<source> <target> [\"forceOverwrite\"]")))
return false;
- }
+
+ const QStringList args = arguments();
const QString sourcePath = args.at(0);
const QString targetPath = args.at(1);
bool overwrite = false;
@@ -74,19 +72,22 @@ bool CopyDirectoryOperation::performOperation()
overwrite = true;
} else {
setError(InvalidArguments);
- setErrorString(tr("Invalid argument in %0: Third argument needs to be forceOverwrite, "
- "if specified").arg(name()));
+ setErrorString(tr("Invalid argument in %1: Third argument needs to be forceOverwrite, "
+ "if specified.").arg(name()));
return false;
}
}
const QFileInfo sourceInfo(sourcePath);
const QFileInfo targetInfo(targetPath);
- if (!sourceInfo.exists() || !sourceInfo.isDir() || !targetInfo.exists() || !targetInfo.isDir()) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: Directories are invalid: %1 %2").arg(name())
- .arg(sourcePath).arg(targetPath));
- return false;
+
+ foreach (const QFileInfo &dir, QList<QFileInfo>() << sourceInfo << targetInfo) {
+ if (!dir.exists() || !dir.isDir()) {
+ setError(InvalidArguments);
+ setErrorString(tr("Invalid argument in %1: Directory \"%2\" is invalid.").arg(name())
+ .arg(QDir::toNativeSeparators(sourcePath)));
+ return false;
+ }
}
const QDir sourceDir = sourceInfo.absoluteDir();
@@ -117,22 +118,24 @@ bool CopyDirectoryOperation::performOperation()
} else if (itemInfo.isDir()) {
if (!targetDir.mkpath(targetDir.absoluteFilePath(relativePath))) {
setError(InvalidArguments);
- setErrorString(tr("Could not create %0").arg(targetDir.absoluteFilePath(relativePath)));
+ setErrorString(tr("Cannot create directory \"%1\".").arg(
+ QDir::toNativeSeparators(targetDir.absoluteFilePath(relativePath))));
return false;
}
} else {
const QString absolutePath = targetDir.absoluteFilePath(relativePath);
if (overwrite && QFile::exists(absolutePath) && !deleteFileNowOrLater(absolutePath)) {
setError(UserDefinedError);
- setErrorString(tr("Failed to overwrite %1").arg(absolutePath));
+ setErrorString(tr("Failed to overwrite \"%1\".").arg(QDir::toNativeSeparators(absolutePath)));
return false;
}
QFile file(sourceDir.absoluteFilePath(itemName));
if (!file.copy(absolutePath)) {
setError(UserDefinedError);
- setErrorString(tr("Could not copy %0 to %1, error was: %3").arg(sourceDir.absoluteFilePath(itemName),
- targetDir.absoluteFilePath(relativePath),
- file.errorString()));
+ setErrorString(tr("Cannot copy file \"%1\" to \"%2\": %3").arg(
+ QDir::toNativeSeparators(sourceDir.absoluteFilePath(itemName)),
+ QDir::toNativeSeparators(targetDir.absoluteFilePath(relativePath)),
+ file.errorString()));
return false;
}
autoPush.m_files.prepend(targetDir.absoluteFilePath(relativePath));
@@ -151,7 +154,7 @@ bool CopyDirectoryOperation::undoOperation()
foreach (const QString &file, files) {
if (!QFile::remove(file)) {
setError(InvalidArguments);
- setErrorString(tr("Could not remove %0").arg(file));
+ setErrorString(tr("Cannot remove file \"%1\".").arg(QDir::toNativeSeparators(file)));
return false;
}
dir.rmpath(QFileInfo(file).absolutePath());
@@ -166,8 +169,3 @@ bool CopyDirectoryOperation::testOperation()
{
return true;
}
-
-Operation *CopyDirectoryOperation::clone() const
-{
- return new CopyDirectoryOperation();
-}
diff --git a/src/libs/installer/copydirectoryoperation.h b/src/libs/installer/copydirectoryoperation.h
index 57169e936..f934f8b91 100644
--- a/src/libs/installer/copydirectoryoperation.h
+++ b/src/libs/installer/copydirectoryoperation.h
@@ -40,13 +40,12 @@ class INSTALLER_EXPORT CopyDirectoryOperation : public QObject, public Operation
Q_OBJECT
public:
- CopyDirectoryOperation();
+ explicit CopyDirectoryOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
Q_SIGNALS:
void outputTextChanged(const QString &progress);
diff --git a/src/libs/installer/copyfiletask.cpp b/src/libs/installer/copyfiletask.cpp
index 84287678a..b3cd61aa2 100644
--- a/src/libs/installer/copyfiletask.cpp
+++ b/src/libs/installer/copyfiletask.cpp
@@ -28,6 +28,7 @@
#include "copyfiletask.h"
#include "observer.h"
+#include <QDir>
#include <QFileInfo>
#include <QTemporaryFile>
@@ -63,8 +64,8 @@ void CopyFileTask::doTask(QFutureInterface<FileTaskResult> &fi)
QFile source(item.source());
if (!source.open(QIODevice::ReadOnly)) {
- fi.reportException(TaskException(tr("Could not open source '%1' for read. Error: %2.")
- .arg(source.fileName(), source.errorString())));
+ fi.reportException(TaskException(tr("Cannot open file \"%1\" for reading: %2")
+ .arg(QDir::toNativeSeparators(source.fileName()), source.errorString())));
fi.reportFinished(); return; // error
}
observer.setBytesToTransfer(source.size());
@@ -79,8 +80,8 @@ void CopyFileTask::doTask(QFutureInterface<FileTaskResult> &fi)
file.reset(new QFile(target));
}
if (!file->open(QIODevice::WriteOnly | QIODevice::Truncate)) {
- fi.reportException(TaskException(tr("Could not open target '%1' for write. Error: %2.")
- .arg(file->fileName(), file->errorString())));
+ fi.reportException(TaskException(tr("Cannot open file \"%1\" for writing: %2")
+ .arg(QDir::toNativeSeparators(file->fileName()), file->errorString())));
fi.reportFinished(); return; // error
}
@@ -96,8 +97,8 @@ void CopyFileTask::doTask(QFutureInterface<FileTaskResult> &fi)
while (written < read) {
const qint64 toWrite = file->write(buffer.constData() + written, read - written);
if (toWrite < 0) {
- fi.reportException(TaskException(tr("Writing to target '%1' failed. Error: %2.")
- .arg(file->fileName(), file->errorString())));
+ fi.reportException(TaskException(tr("Writing to file \"%1\" failed: %2")
+ .arg(QDir::toNativeSeparators(file->fileName()), file->errorString())));
}
written += toWrite;
}
diff --git a/src/libs/installer/createdesktopentryoperation.cpp b/src/libs/installer/createdesktopentryoperation.cpp
index a3bf045de..ed55cdbf2 100644
--- a/src/libs/installer/createdesktopentryoperation.cpp
+++ b/src/libs/installer/createdesktopentryoperation.cpp
@@ -91,7 +91,8 @@ QString CreateDesktopEntryOperation::absoluteFileName()
return QDir(directory).absoluteFilePath(filename);
}
-CreateDesktopEntryOperation::CreateDesktopEntryOperation()
+CreateDesktopEntryOperation::CreateDesktopEntryOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("CreateDesktopEntry"));
}
@@ -116,32 +117,27 @@ void CreateDesktopEntryOperation::backup()
}
if (!file.copy(value(QLatin1String("backupOfExistingDesktopEntry")).toString()))
- setErrorString(tr("Could not backup file %1: %2").arg(filename, file.errorString()));
+ setErrorString(tr("Cannot backup file \"%1\": %2").arg(QDir::toNativeSeparators(filename), file.errorString()));
}
bool CreateDesktopEntryOperation::performOperation()
{
- const QStringList args = arguments();
- if (args.count() != 2) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("exactly 2"), QLatin1String("")));
+ if (!checkArgumentCount(2))
return false;
- }
const QString filename = absoluteFileName();
- const QString &values = args[1];
+ const QString &values = arguments().at(1);
QFile file(filename);
if (file.exists() && !file.remove()) {
setError(UserDefinedError);
- setErrorString(tr("Failed to overwrite %1").arg(filename));
+ setErrorString(tr("Failed to overwrite file \"%1\".").arg(QDir::toNativeSeparators(filename)));
return false;
}
if(!file.open(QIODevice::WriteOnly)) {
setError(UserDefinedError);
- setErrorString(tr("Could not write Desktop Entry at %1").arg(filename));
+ setErrorString(tr("Cannot write desktop entry to \"%1\".").arg(QDir::toNativeSeparators(filename)));
return false;
}
@@ -167,7 +163,7 @@ bool CreateDesktopEntryOperation::undoOperation()
// first remove the link
QFile file(filename);
if (file.exists() && !file.remove()) {
- qWarning() << "Could not delete file" << filename << file.errorString();
+ qWarning() << "Cannot delete file" << filename << ":" << file.errorString();
return true;
}
@@ -177,13 +173,13 @@ bool CreateDesktopEntryOperation::undoOperation()
QFile backupFile(value(QLatin1String("backupOfExistingDesktopEntry")).toString());
if (!backupFile.exists()) {
// do not treat this as a real error: The backup file might have been just nuked by the user.
- qWarning() << "Could not restore original desktop entry at" << filename
+ qWarning() << "Cannot restore original desktop entry at" << filename
<< ": Backup file" << backupFile.fileName() << "does not exist anymore.";
return true;
}
if (!backupFile.rename(filename))
- qWarning() << "Could not restore the file" << filename << ":" << backupFile.errorString();
+ qWarning() << "Cannot restore the file" << filename << ":" << backupFile.errorString();
return true;
}
@@ -192,8 +188,3 @@ bool CreateDesktopEntryOperation::testOperation()
{
return true;
}
-
-Operation *CreateDesktopEntryOperation::clone() const
-{
- return new CreateDesktopEntryOperation();
-}
diff --git a/src/libs/installer/createdesktopentryoperation.h b/src/libs/installer/createdesktopentryoperation.h
index 6a7ab5c25..793d1db16 100644
--- a/src/libs/installer/createdesktopentryoperation.h
+++ b/src/libs/installer/createdesktopentryoperation.h
@@ -37,14 +37,13 @@ class INSTALLER_EXPORT CreateDesktopEntryOperation : public Operation
{
Q_DECLARE_TR_FUNCTIONS(QInstaller::CreateDesktopEntryOperation)
public:
- CreateDesktopEntryOperation();
+ explicit CreateDesktopEntryOperation(PackageManagerCore *core);
~CreateDesktopEntryOperation();
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation* clone() const;
QString absoluteFileName();
};
diff --git a/src/libs/installer/createlinkoperation.cpp b/src/libs/installer/createlinkoperation.cpp
index 1ca609237..851290ba8 100644
--- a/src/libs/installer/createlinkoperation.cpp
+++ b/src/libs/installer/createlinkoperation.cpp
@@ -29,11 +29,13 @@
#include "link.h"
+#include <QDir>
#include <QFileInfo>
using namespace QInstaller;
-CreateLinkOperation::CreateLinkOperation()
+CreateLinkOperation::CreateLinkOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("CreateLink"));
}
@@ -44,22 +46,18 @@ void CreateLinkOperation::backup()
bool CreateLinkOperation::performOperation()
{
- QStringList args = arguments();
-
- if (args.count() != 2) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("exactly 2"), QLatin1String("")));
+ if (!checkArgumentCount(2))
return false;
- }
+ const QStringList args = arguments();
const QString& linkPath = args.at(0);
const QString& targetPath = args.at(1);
Link link = Link::create(linkPath, targetPath);
if (!link.exists()) {
setError(UserDefinedError);
- setErrorString(tr("Could not create link from %1 to %2.").arg(linkPath, targetPath));
+ setErrorString(tr("Cannot create link from \"%1\" to \"%2\".").arg(
+ QDir::toNativeSeparators(linkPath), QDir::toNativeSeparators(targetPath)));
return false;
}
@@ -79,7 +77,8 @@ bool CreateLinkOperation::undoOperation()
}
if (!link.remove()) {
setError(UserDefinedError);
- setErrorString(tr("Could not remove link from %1 to %2.").arg(linkPath, targetPath));
+ setErrorString(tr("Cannot remove link from \"%1\" to \"%2\".").arg(
+ QDir::toNativeSeparators(linkPath), QDir::toNativeSeparators(targetPath)));
return false;
}
@@ -90,8 +89,3 @@ bool CreateLinkOperation::testOperation()
{
return true;
}
-
-Operation *CreateLinkOperation::clone() const
-{
- return new CreateLinkOperation();
-}
diff --git a/src/libs/installer/createlinkoperation.h b/src/libs/installer/createlinkoperation.h
index 8b27014bd..2e4ece9aa 100644
--- a/src/libs/installer/createlinkoperation.h
+++ b/src/libs/installer/createlinkoperation.h
@@ -37,13 +37,12 @@ class INSTALLER_EXPORT CreateLinkOperation : public Operation
{
Q_DECLARE_TR_FUNCTIONS(QInstaller::CreateLinkOperation)
public:
- CreateLinkOperation();
+ explicit CreateLinkOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
};
}
diff --git a/src/libs/installer/createlocalrepositoryoperation.cpp b/src/libs/installer/createlocalrepositoryoperation.cpp
index 6a78e68e3..8f6ab2eaa 100644
--- a/src/libs/installer/createlocalrepositoryoperation.cpp
+++ b/src/libs/installer/createlocalrepositoryoperation.cpp
@@ -34,11 +34,12 @@
#include "fileio.h"
#include "fileutils.h"
#include "copydirectoryoperation.h"
+#include "lib7z_create.h"
#include "lib7z_facade.h"
#include "packagemanagercore.h"
#include "productkeycheck.h"
-#include "kdupdaterupdateoperations.h"
+#include "updateoperations.h"
#include <QtCore/QDir>
#include <QtCore/QDirIterator>
@@ -82,8 +83,8 @@ static void fixPermissions(const QString &repoPath)
if (!QFile::setPermissions(it.filePath(), QFile::ReadOwner | QFile::WriteOwner
| QFile::ReadUser | QFile::WriteUser | QFile::ReadGroup | QFile::ReadOther)) {
- throw Error(CreateLocalRepositoryOperation::tr("Could not set file permissions %1!")
- .arg(it.filePath()));
+ throw Error(CreateLocalRepositoryOperation::tr("Cannot set permissions for file \"%1\".")
+ .arg(QDir::toNativeSeparators(it.filePath())));
}
}
}
@@ -103,8 +104,8 @@ static void removeFiles(const QString &path, AutoHelper *const helper)
if (fi.isSymLink() || fi.isFile()) {
QFile f(fi.filePath());
if (!f.remove()) {
- throw Error(CreateLocalRepositoryOperation::tr("Could not remove file %1: %2")
- .arg(f.fileName(), f.errorString()));
+ throw Error(CreateLocalRepositoryOperation::tr("Cannot remove file \"%1\": %2")
+ .arg(QDir::toNativeSeparators(f.fileName()), f.errorString()));
}
helper->m_files.removeAll(f.fileName());
}
@@ -121,8 +122,9 @@ static QString createArchive(const QString repoPath, const QString &sourceDir, c
Lib7z::createArchive(&archive, QStringList() << sourceDir);
removeFiles(sourceDir, helper); // cleanup the files we compressed
if (!archive.rename(sourceDir + fileName)) {
- throw Error(CreateLocalRepositoryOperation::tr("Could not move file %1 to %2. Error: %3")
- .arg(archive.fileName(), sourceDir + fileName, archive.errorString()));
+ throw Error(CreateLocalRepositoryOperation::tr("Cannot move file \"%1\" to \"%2\": %3")
+ .arg(QDir::toNativeSeparators(archive.fileName()),
+ QDir::toNativeSeparators(sourceDir + fileName), archive.errorString()));
}
return archive.fileName();
}
@@ -132,7 +134,8 @@ static QString createArchive(const QString repoPath, const QString &sourceDir, c
// -- CreateLocalRepositoryOperation
-CreateLocalRepositoryOperation::CreateLocalRepositoryOperation()
+CreateLocalRepositoryOperation::CreateLocalRepositoryOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("CreateLocalRepository"));
}
@@ -146,24 +149,20 @@ bool CreateLocalRepositoryOperation::performOperation()
AutoHelper helper(this);
emit progressChanged(0.0);
- const QStringList args = arguments();
-
- if (args.count() != 2) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("exactly 2"), QLatin1String("")));
+ if (!checkArgumentCount(2))
return false;
- }
try {
+ const QStringList args = arguments();
+
const QString binaryPath = QFileInfo(args.at(0)).absoluteFilePath();
// Note the "/" at the end, important to make copy directory operation behave well
const QString repoPath = QFileInfo(args.at(1)).absoluteFilePath() + QLatin1Char('/');
// check if this is an offline version, otherwise there will be no binary data
- PackageManagerCore *const core = value(QLatin1String("installer")).value<PackageManagerCore*>();
+ PackageManagerCore *const core = packageManager();
if (core && !core->isOfflineOnly()) {
- throw QInstaller::Error(tr("Installer needs to be an offline version: %1.")
+ throw QInstaller::Error(tr("Installer at \"%1\" needs to be an offline one.")
.arg(QDir::toNativeSeparators(binaryPath)));
}
@@ -185,9 +184,10 @@ bool CreateLocalRepositoryOperation::performOperation()
setValue(QLatin1String("createddir"), mkDirOp.value(QLatin1String("createddir")));
// copy the whole meta data into local repository
- CopyDirectoryOperation copyDirOp;
+ CopyDirectoryOperation copyDirOp(core);
copyDirOp.setArguments(QStringList() << QLatin1String(":/metadata/") << repoPath);
- connect(&copyDirOp, SIGNAL(outputTextChanged(QString)), this, SIGNAL(outputTextChanged(QString)));
+ connect(&copyDirOp, &CopyDirectoryOperation::outputTextChanged,
+ this, &CreateLocalRepositoryOperation::outputTextChanged);
const bool success = copyDirOp.performOperation();
helper.m_files = copyDirOp.value(QLatin1String("files")).toStringList();
@@ -206,13 +206,15 @@ bool CreateLocalRepositoryOperation::performOperation()
// open the updates xml file we previously copied
QFile updatesXml(repoPath + QLatin1String("Updates.xml"));
if (!updatesXml.exists() || !updatesXml.open(QIODevice::ReadOnly))
- throw QInstaller::Error(tr("Could not open file: %1").arg(updatesXml.fileName()));
+ throw QInstaller::Error(tr("Cannot open file \"%1\" for reading.").arg(
+ QDir::toNativeSeparators(updatesXml.fileName())));
// read the content of the updates xml
QString error;
QDomDocument doc;
if (!doc.setContent(&updatesXml, &error))
- throw QInstaller::Error(tr("Could not read: %1. Error: %2").arg(updatesXml.fileName(), error));
+ throw QInstaller::Error(tr("Cannot read file \"%1\": %2").arg(
+ QDir::toNativeSeparators(updatesXml.fileName()), error));
// build for each available package a name - version mapping
QHash<QString, QString> nameVersionHash;
@@ -242,8 +244,9 @@ bool CreateLocalRepositoryOperation::performOperation()
QFile file(binaryPath);
if (!file.open(QIODevice::ReadOnly)) {
- throw QInstaller::Error(tr("Could not open file: %1. Error: %2").arg(file.fileName(),
- file.errorString()));
+ throw QInstaller::Error(tr("Cannot open file \"%1\" for reading: %2").arg(
+ QDir::toNativeSeparators(file.fileName()),
+ file.errorString()));
}
// start to read the binary layout
@@ -260,8 +263,8 @@ bool CreateLocalRepositoryOperation::performOperation()
for (int i = 0; i < names.count(); ++i) {
const QString name = names.at(i);
if (!repo.mkpath(name)) {
- throw QInstaller::Error(tr("Could not create target dir: %1.")
- .arg(repo.filePath(name)));
+ throw QInstaller::Error(tr("Cannot create target directory: \"%1\".")
+ .arg(QDir::toNativeSeparators(repo.filePath(name))));
}
// zip the meta files that come with the offline installer
helper.m_files.prepend(Static::createArchive(repoPath,
@@ -329,10 +332,10 @@ bool CreateLocalRepositoryOperation::undoOperation()
QDir dir;
const QStringList files = value(QLatin1String("files")).toStringList();
foreach (const QString &file, files) {
- emit outputTextChanged(tr("Removing file: %0").arg(file));
+ emit outputTextChanged(tr("Removing file \"%1\".").arg(QDir::toNativeSeparators(file)));
if (!QFile::remove(file)) {
setError(InvalidArguments);
- setErrorString(tr("Could not remove %0.").arg(file));
+ setErrorString(tr("Cannot remove file \"%1\".").arg(QDir::toNativeSeparators(file)));
return false;
}
dir.rmpath(QFileInfo(file).absolutePath());
@@ -351,12 +354,12 @@ bool CreateLocalRepositoryOperation::undoOperation()
#if defined(Q_OS_WIN) && !defined(Q_CC_MINGW)
char msg[128];
if (strerror_s(msg, sizeof msg, errno) != 0) {
- setError(UserDefinedError, tr("Cannot remove directory %1: %2").arg(createdDir.path(),
- QString::fromLocal8Bit(msg)));
+ setError(UserDefinedError, tr("Cannot remove directory \"%1\": %2").arg(
+ QDir::toNativeSeparators(createdDir.path()), QString::fromLocal8Bit(msg)));
}
#else
- setError(UserDefinedError, tr("Cannot remove directory %1: %2").arg(createdDir.path(),
- QString::fromLocal8Bit(strerror(errno))));
+ setError(UserDefinedError, tr("Cannot remove directory \"%1\": %2").arg(
+ QDir::toNativeSeparators(createdDir.path()), QString::fromLocal8Bit(strerror(errno))));
#endif
}
setValue(QLatin1String("files"), QStringList());
@@ -369,11 +372,6 @@ bool CreateLocalRepositoryOperation::testOperation()
return true;
}
-Operation *CreateLocalRepositoryOperation::clone() const
-{
- return new CreateLocalRepositoryOperation();
-}
-
void CreateLocalRepositoryOperation::emitFullProgress()
{
emit progressChanged(1.0);
diff --git a/src/libs/installer/createlocalrepositoryoperation.h b/src/libs/installer/createlocalrepositoryoperation.h
index c89fd2ca6..275d7a409 100644
--- a/src/libs/installer/createlocalrepositoryoperation.h
+++ b/src/libs/installer/createlocalrepositoryoperation.h
@@ -41,13 +41,12 @@ class INSTALLER_EXPORT CreateLocalRepositoryOperation : public QObject, public O
friend struct AutoHelper;
public:
- CreateLocalRepositoryOperation();
+ explicit CreateLocalRepositoryOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
signals:
void progressChanged(double progress);
diff --git a/src/libs/installer/createshortcutoperation.cpp b/src/libs/installer/createshortcutoperation.cpp
index 754ba317e..2c2e96eff 100644
--- a/src/libs/installer/createshortcutoperation.cpp
+++ b/src/libs/installer/createshortcutoperation.cpp
@@ -41,6 +41,7 @@ using namespace QInstaller;
#ifdef Q_OS_WIN
#include <qt_windows.h>
#include <shlobj.h>
+#include <Intshcut.h>
#ifndef PIDLIST_ABSOLUTE
typedef ITEMIDLIST *PIDLIST_ABSOLUTE;
@@ -93,39 +94,62 @@ static QString takeArgument(const QString argument, QStringList *arguments)
static bool createLink(const QString &fileName, const QString &linkName, QString workingDir,
const QString &arguments = QString(), const QString &iconPath = QString(),
- const QString &iconId = QString())
+ const QString &iconId = QString(), const QString &description = QString())
{
#ifdef Q_OS_WIN
- bool success = QFile::link(fileName, linkName);
+ // CoInitialize cleanup object
+ DeCoInitializer _;
- if (!success)
- return success;
+ IUnknown *iunkn = NULL;
- if (workingDir.isEmpty())
- workingDir = QFileInfo(fileName).absolutePath();
- workingDir = QDir::toNativeSeparators(workingDir);
+ if (fileName.toLower().startsWith(QLatin1String("http:"))
+ || fileName.toLower().startsWith(QLatin1String("ftp:"))) {
+ IUniformResourceLocator *iurl = NULL;
+ if (FAILED(CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
+ IID_IUniformResourceLocator, (LPVOID*)&iurl))) {
+ return false;
+ }
- // CoInitialize cleanup object
- DeCoInitializer _;
+ if (FAILED(iurl->SetURL((wchar_t *)fileName.utf16(), IURL_SETURL_FL_GUESS_PROTOCOL))) {
+ iurl->Release();
+ return false;
+ }
+ iunkn = iurl;
+ } else {
+ bool success = QFile::link(fileName, linkName);
+
+ if (!success) {
+ return success;
+ }
+
+ if (workingDir.isEmpty())
+ workingDir = QFileInfo(fileName).absolutePath();
+ workingDir = QDir::toNativeSeparators(workingDir);
- IShellLink *psl = NULL;
- if (FAILED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl)))
- return success;
+ IShellLink *psl = NULL;
+ if (FAILED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+ IID_IShellLink, (LPVOID*)&psl))) {
+ return success;
+ }
- // TODO: implement this server side, since there's not Qt equivalent to set working dir and arguments
- psl->SetPath((wchar_t *)QDir::toNativeSeparators(fileName).utf16());
- psl->SetWorkingDirectory((wchar_t *)workingDir.utf16());
- if (!arguments.isNull())
- psl->SetArguments((wchar_t*)arguments.utf16());
- if (!iconPath.isNull())
- psl->SetIconLocation((wchar_t*)(iconPath.utf16()), iconId.toInt());
+ // TODO: implement this server side, since there's not Qt equivalent to set working dir and arguments
+ psl->SetPath((wchar_t *)QDir::toNativeSeparators(fileName).utf16());
+ psl->SetWorkingDirectory((wchar_t *)workingDir.utf16());
+ if (!arguments.isNull())
+ psl->SetArguments((wchar_t*)arguments.utf16());
+ if (!iconPath.isNull())
+ psl->SetIconLocation((wchar_t*)(iconPath.utf16()), iconId.toInt());
+ if (!description.isNull())
+ psl->SetDescription((wchar_t*)(description.utf16()));
+ iunkn = psl;
+ }
IPersistFile *ppf = NULL;
- if (SUCCEEDED(psl->QueryInterface(IID_IPersistFile, (void **)&ppf))) {
+ if (SUCCEEDED(iunkn->QueryInterface(IID_IPersistFile, (void **)&ppf))) {
ppf->Save((wchar_t*)QDir::toNativeSeparators(linkName).utf16(), true);
ppf->Release();
}
- psl->Release();
+ iunkn->Release();
PIDLIST_ABSOLUTE pidl; // Force start menu cache update
if (SUCCEEDED(SHGetFolderLocation(0, CSIDL_STARTMENU, 0, 0, &pidl))) {
@@ -137,7 +161,7 @@ static bool createLink(const QString &fileName, const QString &linkName, QString
CoTaskMemFree(pidl);
}
- return success;
+ return true;
#else
Q_UNUSED(arguments)
Q_UNUSED(workingDir)
@@ -152,13 +176,17 @@ static bool createLink(const QString &fileName, const QString &linkName, QString
// -- CreateShortcutOperation
-CreateShortcutOperation::CreateShortcutOperation()
+CreateShortcutOperation::CreateShortcutOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
+ , m_optionalArgumentsRead(false)
{
setName(QLatin1String("CreateShortcut"));
}
void CreateShortcutOperation::backup()
{
+ ensureOptionalArgumentsRead();
+
QDir linkPath(QFileInfo(arguments().at(1)).absolutePath());
QStringList directoriesToCreate;
@@ -171,25 +199,38 @@ void CreateShortcutOperation::backup()
setValue(QLatin1String("createddirs"), directoriesToCreate);
}
-bool CreateShortcutOperation::performOperation()
+void CreateShortcutOperation::ensureOptionalArgumentsRead()
{
+ if (m_optionalArgumentsRead)
+ return;
+
+ m_optionalArgumentsRead = true;
+
QStringList args = arguments();
- const QString iconId = takeArgument(QString::fromLatin1("iconId="), &args);
- const QString iconPath = takeArgument(QString::fromLatin1("iconPath="), &args);
- const QString workingDir = takeArgument(QString::fromLatin1("workingDirectory="), &args);
+ m_iconId = takeArgument(QString::fromLatin1("iconId="), &args);
+ m_iconPath = takeArgument(QString::fromLatin1("iconPath="), &args);
+ m_workingDir = takeArgument(QString::fromLatin1("workingDirectory="), &args);
+ m_description = takeArgument(QString::fromLatin1("description="), &args);
+
+ setArguments(args);
+}
+
+bool CreateShortcutOperation::performOperation()
+{
+ ensureOptionalArgumentsRead();
- if (args.count() != 2 && args.count() != 3) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("2 or 3"),
- tr(" (optional: 'workingDirectory=...', 'iconPath=...', 'iconId=...')")));
+ if (!checkArgumentCount(2, 3, tr("<target> <link location> [target arguments] "
+ "[\"workingDirectory=...\"] [\"iconPath=...\"] [\"iconId=...\"] "
+ "[\"description=...\"]"))) {
return false;
}
+ QStringList args = arguments();
+
const QString linkTarget = args.at(0);
const QString linkLocation = args.at(1);
- const QString targetArguments = args.value(2); //used value because it could be not existing
+ const QString targetArguments = args.value(2); // value() used since it's optional
const QString linkPath = QFileInfo(linkLocation).absolutePath().trimmed();
const bool created = QDir(linkPath).exists() || QDir::root().mkpath(linkPath);
@@ -199,11 +240,11 @@ bool CreateShortcutOperation::performOperation()
#if defined(Q_OS_WIN) && !defined(Q_CC_MINGW)
char msg[128];
if (strerror_s(msg, sizeof msg, errno) != 0) {
- setErrorString(tr("Could not create folder %1: %2.").arg(QDir::toNativeSeparators(linkPath),
+ setErrorString(tr("Cannot create directory \"%1\": %2").arg(QDir::toNativeSeparators(linkPath),
QString::fromLocal8Bit(msg)));
}
#else
- setErrorString(tr("Could not create folder %1: %2.").arg(QDir::toNativeSeparators(linkPath),
+ setErrorString(tr("Cannot create directory \"%1\": %2").arg(QDir::toNativeSeparators(linkPath),
QString::fromLocal8Bit(strerror(errno))));
#endif
return false;
@@ -213,15 +254,16 @@ bool CreateShortcutOperation::performOperation()
QString errorString;
if (QFile::exists(linkLocation) && !deleteFileNowOrLater(linkLocation, &errorString)) {
setError(UserDefinedError);
- setErrorString(tr("Failed to overwrite %1: %2").arg(QDir::toNativeSeparators(linkLocation),
+ setErrorString(tr("Failed to overwrite \"%1\": %2").arg(QDir::toNativeSeparators(linkLocation),
errorString));
return false;
}
- const bool linked = createLink(linkTarget, linkLocation, workingDir, targetArguments, iconPath, iconId);
+ const bool linked = createLink(linkTarget, linkLocation, m_workingDir, targetArguments, m_iconPath, m_iconId,
+ m_description);
if (!linked) {
setError(UserDefinedError);
- setErrorString(tr("Could not create link %1: %2").arg(QDir::toNativeSeparators(linkLocation),
+ setErrorString(tr("Cannot create link \"%1\": %2").arg(QDir::toNativeSeparators(linkLocation),
qt_error_string()));
return false;
}
@@ -230,6 +272,8 @@ bool CreateShortcutOperation::performOperation()
bool CreateShortcutOperation::undoOperation()
{
+ ensureOptionalArgumentsRead();
+
const QString &linkLocation = arguments().at(1);
if (!deleteFileNowOrLater(linkLocation) )
qDebug() << "Cannot delete:" << linkLocation;
@@ -271,8 +315,3 @@ bool CreateShortcutOperation::testOperation()
{
return true;
}
-
-Operation *CreateShortcutOperation::clone() const
-{
- return new CreateShortcutOperation();
-}
diff --git a/src/libs/installer/createshortcutoperation.h b/src/libs/installer/createshortcutoperation.h
index 6cd5dc064..dc2ac6ddb 100644
--- a/src/libs/installer/createshortcutoperation.h
+++ b/src/libs/installer/createshortcutoperation.h
@@ -37,13 +37,21 @@ class INSTALLER_EXPORT CreateShortcutOperation : public Operation
{
Q_DECLARE_TR_FUNCTIONS(QInstaller::CreateShortcutOperation)
public:
- CreateShortcutOperation();
+ explicit CreateShortcutOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
+
+private:
+ void ensureOptionalArgumentsRead();
+
+ bool m_optionalArgumentsRead;
+ QString m_iconId;
+ QString m_iconPath;
+ QString m_workingDir;
+ QString m_description;
};
}
diff --git a/src/libs/installer/downloadarchivesjob.cpp b/src/libs/installer/downloadarchivesjob.cpp
index 4f153219e..8fd8a40a9 100644
--- a/src/libs/installer/downloadarchivesjob.cpp
+++ b/src/libs/installer/downloadarchivesjob.cpp
@@ -33,8 +33,8 @@
#include "packagemanagercore.h"
#include "utils.h"
-#include "kdupdaterfiledownloader.h"
-#include "kdupdaterfiledownloaderfactory.h"
+#include "filedownloader.h"
+#include "filedownloaderfactory.h"
#include <QtCore/QFile>
#include <QtCore/QTimerEvent>
@@ -47,7 +47,7 @@ using namespace KDUpdater;
Creates a new DownloadArchivesJob with \a parent.
*/
DownloadArchivesJob::DownloadArchivesJob(PackageManagerCore *core)
- : KDJob(core)
+ : Job(core)
, m_core(core)
, m_downloader(0)
, m_archivesDownloaded(0)
@@ -120,8 +120,8 @@ void DownloadArchivesJob::fetchNextArchiveHash()
return;
}
- connect(m_downloader, SIGNAL(downloadCompleted()), this, SLOT(finishedHashDownload()),
- Qt::QueuedConnection);
+ connect(m_downloader, &FileDownloader::downloadCompleted,
+ this, &DownloadArchivesJob::finishedHashDownload, Qt::QueuedConnection);
m_downloader->download();
} else {
QMetaObject::invokeMethod(this, "fetchNextArchive", Qt::QueuedConnection);
@@ -159,7 +159,7 @@ void DownloadArchivesJob::fetchNextArchive()
if (m_downloader != 0)
m_downloader->deleteLater();
- m_downloader = setupDownloader(QString(), m_core->value(QLatin1String("UrlQueryString")));
+ m_downloader = setupDownloader(QString(), m_core->value(scUrlQueryString));
if (!m_downloader) {
m_archivesToDownload.removeFirst();
QMetaObject::invokeMethod(this, "fetchNextArchiveHash", Qt::QueuedConnection);
@@ -168,7 +168,8 @@ void DownloadArchivesJob::fetchNextArchive()
emit progressChanged(double(m_archivesDownloaded) / m_archivesToDownloadCount);
connect(m_downloader, SIGNAL(downloadProgress(double)), this, SLOT(emitDownloadProgress(double)));
- connect(m_downloader, SIGNAL(downloadCompleted()), this, SLOT(registerFile()), Qt::QueuedConnection);
+ connect(m_downloader, &FileDownloader::downloadCompleted,
+ this, &DownloadArchivesJob::registerFile, Qt::QueuedConnection);
m_downloader->download();
}
@@ -215,7 +216,7 @@ void DownloadArchivesJob::registerFile()
QMessageBox::Retry | QMessageBox::Cancel, QMessageBox::Cancel);
if (res == QMessageBox::Cancel) {
- finishWithError(tr("Could not verify Hash"));
+ finishWithError(tr("Cannot verify Hash"));
return;
}
} else {
@@ -235,7 +236,7 @@ void DownloadArchivesJob::registerFile()
void DownloadArchivesJob::downloadCanceled()
{
- emitFinishedWithError(KDJob::Canceled, m_downloader->errorString());
+ emitFinishedWithError(Job::Canceled, m_downloader->errorString());
}
void DownloadArchivesJob::downloadFailed(const QString &error)
@@ -245,7 +246,7 @@ void DownloadArchivesJob::downloadFailed(const QString &error)
const QMessageBox::StandardButton b =
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
- QLatin1String("archiveDownloadError"), tr("Download Error"), tr("Could not download archive: %1 : %2")
+ QLatin1String("archiveDownloadError"), tr("Download Error"), tr("Cannot download archive %1: %2")
.arg(m_archivesToDownload.first().second, error), QMessageBox::Retry | QMessageBox::Cancel);
if (b == QMessageBox::Retry)
@@ -257,7 +258,7 @@ void DownloadArchivesJob::downloadFailed(const QString &error)
void DownloadArchivesJob::finishWithError(const QString &error)
{
const FileDownloader *const dl = qobject_cast<const FileDownloader*> (sender());
- const QString msg = tr("Could not fetch archives: %1\nError while loading %2");
+ const QString msg = tr("Cannot fetch archives: %1\nError while loading %2");
if (dl != 0)
emitFinishedWithError(QInstaller::DownloadError, msg.arg(error, dl->url().toString()));
else
@@ -286,24 +287,23 @@ KDUpdater::FileDownloader *DownloadArchivesJob::setupDownloader(const QString &s
auth.setPassword(component->value(QLatin1String("password")));
downloader->setAuthenticator(auth);
- connect(downloader, SIGNAL(downloadCanceled()), this, SLOT(downloadCanceled()));
- connect(downloader, SIGNAL(downloadAborted(QString)), this, SLOT(downloadFailed(QString)),
+ connect(downloader, &FileDownloader::downloadCanceled, this, &DownloadArchivesJob::downloadCanceled);
+ connect(downloader, &FileDownloader::downloadAborted, this, &DownloadArchivesJob::downloadFailed,
Qt::QueuedConnection);
- connect(downloader, SIGNAL(downloadStatus(QString)), this, SIGNAL(downloadStatusChanged(QString)));
+ connect(downloader, &FileDownloader::downloadStatus, this, &DownloadArchivesJob::downloadStatusChanged);
if (FileDownloaderFactory::isSupportedScheme(scheme)) {
downloader->setDownloadedFileName(component->localTempPath() + QLatin1Char('/')
+ component->name() + QLatin1Char('/') + fi.fileName() + suffix);
}
- emit outputTextChanged(tr("Downloading archive '%1' for component: %2")
+ emit outputTextChanged(tr("Downloading archive \"%1\" for component %2.")
.arg(fi.fileName() + suffix, component->displayName()));
} else {
- emit outputTextChanged(tr("Scheme not supported: %1 (%2)").arg(scheme, url.toString()));
+ emit outputTextChanged(tr("Scheme %1 not supported (URL: %2).").arg(scheme, url.toString()));
}
} else {
- emit outputTextChanged(tr("Could not find component for: %1.").arg(QFileInfo(fi.path())
- .fileName()));
+ emit outputTextChanged(tr("Cannot find component for %1.").arg(QFileInfo(fi.path()).fileName()));
}
return downloader;
}
diff --git a/src/libs/installer/downloadarchivesjob.h b/src/libs/installer/downloadarchivesjob.h
index 35c62b3a2..8f2392064 100644
--- a/src/libs/installer/downloadarchivesjob.h
+++ b/src/libs/installer/downloadarchivesjob.h
@@ -29,7 +29,7 @@
#ifndef DOWNLOADARCHIVESJOB_H
#define DOWNLOADARCHIVESJOB_H
-#include <kdjob.h>
+#include "job.h"
#include <QtCore/QPair>
@@ -46,7 +46,7 @@ namespace QInstaller {
class MessageBoxHandler;
class PackageManagerCore;
-class DownloadArchivesJob : public KDJob
+class DownloadArchivesJob : public Job
{
Q_OBJECT
diff --git a/src/libs/installer/downloadfiletask.cpp b/src/libs/installer/downloadfiletask.cpp
index b9b560383..2c99e04e1 100644
--- a/src/libs/installer/downloadfiletask.cpp
+++ b/src/libs/installer/downloadfiletask.cpp
@@ -31,12 +31,12 @@
#include "downloadfiletask_p.h"
#include <QCoreApplication>
+#include <QDir>
#include <QEventLoop>
#include <QFileInfo>
#include <QNetworkProxyFactory>
#include <QSslError>
#include <QTemporaryFile>
-#include <QTimer>
namespace QInstaller {
@@ -49,7 +49,8 @@ AuthenticationRequiredException::AuthenticationRequiredException(Type type, cons
Downloader::Downloader()
: m_finished(0)
{
- connect(&m_nam, SIGNAL(finished(QNetworkReply*)), SLOT(onFinished(QNetworkReply*)));
+ connect(&m_timer, &QTimer::timeout, this, &Downloader::onTimeout);
+ connect(&m_nam, &QNetworkAccessManager::finished, this, &Downloader::onFinished);
}
Downloader::~Downloader()
@@ -72,15 +73,17 @@ void Downloader::download(QFutureInterface<FileTaskResult> &fi, const QList<File
fi.setExpectedResultCount(items.count());
m_nam.setProxyFactory(networkProxyFactory);
- connect(&m_nam, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this,
- SLOT(onAuthenticationRequired(QNetworkReply*,QAuthenticator*)));
- connect(&m_nam, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), this,
- SLOT(onProxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
- QTimer::singleShot(0, this, SLOT(doDownload()));
+ connect(&m_nam, &QNetworkAccessManager::authenticationRequired, this,
+ &Downloader::onAuthenticationRequired);
+ connect(&m_nam, &QNetworkAccessManager::proxyAuthenticationRequired, this,
+ &Downloader::onProxyAuthenticationRequired);
+ QTimer::singleShot(0, this, &Downloader::doDownload);
}
void Downloader::doDownload()
{
+ m_timer.start(1000); // Use a timer to check for canceled downloads.
+
foreach (const FileTaskItem &item, m_items) {
if (!startDownload(item))
break;
@@ -120,15 +123,17 @@ void Downloader::onReadyRead()
}
if (file->exists() && (!QFileInfo(file->fileName()).isFile())) {
- m_futureInterface->reportException(TaskException(tr("Target file '%1' already exists "
+ m_futureInterface->reportException(TaskException(tr("Target file \"%1\" already exists "
"but is not a file.").arg(file->fileName())));
return;
}
if (!file->open(QIODevice::WriteOnly | QIODevice::Truncate)) {
//: %2 is a sentence describing the error
- m_futureInterface->reportException(TaskException(tr("Could not open target '%1' for "
- "write. Error: %2.").arg(file->fileName(), file->errorString())));
+ m_futureInterface->reportException(
+ TaskException(tr("Cannot open file \"%1\" for writing: %2").arg(
+ QDir::toNativeSeparators(file->fileName()),
+ file->errorString())));
return;
}
data.file = std::move(file);
@@ -137,8 +142,9 @@ void Downloader::onReadyRead()
if (!data.file->isOpen()) {
//: %2 is a sentence describing the error.
m_futureInterface->reportException(
- TaskException(tr("Target '%1' not open for write. Error: %2.").arg(
- data.file->fileName(), data.file->errorString())));
+ TaskException(tr("File \"%1\" not open for writing: %2").arg(
+ QDir::toNativeSeparators(data.file->fileName()),
+ data.file->errorString())));
return;
}
@@ -156,8 +162,9 @@ void Downloader::onReadyRead()
if (toWrite < 0) {
//: %2 is a sentence describing the error.
m_futureInterface->reportException(
- TaskException(tr("Writing to target '%1' failed. Error: %2.").arg(
- data.file->fileName(), data.file->errorString())));
+ TaskException(tr("Writing to file \"%1\" failed: %2").arg(
+ QDir::toNativeSeparators(data.file->fileName()),
+ data.file->errorString())));
return;
}
written += toWrite;
@@ -203,7 +210,7 @@ void Downloader::onFinished(QNetworkReply *reply)
reply->deleteLater();
return;
} else {
- m_futureInterface->reportException(TaskException(tr("Redirect loop detected '%1'.")
+ m_futureInterface->reportException(TaskException(tr("Redirect loop detected for \"%1\".")
.arg(url.toString())));
return;
}
@@ -220,7 +227,7 @@ void Downloader::onFinished(QNetworkReply *reply)
const QByteArray expectedCheckSum = data.taskItem.value(TaskRole::Checksum).toByteArray();
if (!expectedCheckSum.isEmpty()) {
if (expectedCheckSum != data.observer->checkSum().toHex()) {
- m_futureInterface->reportException(TaskException(tr("Checksum mismatch detected '%1'.")
+ m_futureInterface->reportException(TaskException(tr("Checksum mismatch detected for \"%1\".")
.arg(reply->url().toString())));
}
}
@@ -262,7 +269,7 @@ void Downloader::onError(QNetworkReply::NetworkError error)
} else {
//: %1 is a sentence describing the error
m_futureInterface->reportException(
- TaskException(tr("Unknown network error while downloading: %1.").arg(error)));
+ TaskException(tr("Unknown network error while downloading \"%1\".").arg(error)));
}
}
@@ -272,7 +279,7 @@ void Downloader::onSslErrors(const QList<QSslError> &sslErrors)
Q_UNUSED(sslErrors);
#else
foreach (const QSslError &error, sslErrors)
- qDebug() << QString::fromLatin1("SSL error: %s").arg(error.errorString());
+ qDebug() << "SSL error:" << error.errorString();
#endif
}
@@ -319,6 +326,28 @@ void Downloader::onProxyAuthenticationRequired(const QNetworkProxy &proxy, QAuth
}
+/*!
+ \internal
+
+ Canceling from the outside will not get noticed if we are waiting on a connection that
+ does not create any events. QNam will drop after 45 seconds, though the user might have
+ canceled the download before. In that case we block until the QNam timeout is reached,
+ worst case resulting in deadlock while the application is shutting down at the same time.
+*/
+void Downloader::onTimeout()
+{
+ if (testCanceled()) {
+ // Inject exception, we can't use QFuturInterface::reportException() as the exception
+ // store is "frozen" once cancel was called. On the other hand, client code could use
+ // QFutureWatcherBase::isCanceled() or QFuture::isCanceled() to check for canceled futures.
+ m_futureInterface->exceptionStore()
+ .setException(TaskException(tr("Network transfers canceled.")));
+ m_futureInterface->reportFinished();
+ emit finished();
+ }
+}
+
+
// -- private
bool Downloader::testCanceled()
@@ -337,7 +366,7 @@ QNetworkReply *Downloader::startDownload(const FileTaskItem &item)
QUrl const source = item.source();
if (!source.isValid()) {
//: %2 is a sentence describing the error
- m_futureInterface->reportException(TaskException(tr("Invalid source '%1'. Error: %2.")
+ m_futureInterface->reportException(TaskException(tr("Invalid source URL \"%1\": %2")
.arg(source.toString(), source.errorString())));
return 0;
}
@@ -346,14 +375,13 @@ QNetworkReply *Downloader::startDownload(const FileTaskItem &item)
std::unique_ptr<Data> data(new Data(item));
m_downloads[reply] = std::move(data);
- connect(reply, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
+ connect(reply, &QIODevice::readyRead, this, &Downloader::onReadyRead);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this,
SLOT(onError(QNetworkReply::NetworkError)));
#ifndef QT_NO_SSL
- connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(onSslErrors(QList<QSslError>)));
+ connect(reply, &QNetworkReply::sslErrors, this, &Downloader::onSslErrors);
#endif
- connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(onDownloadProgress(qint64,
- qint64)));
+ connect(reply, &QNetworkReply::downloadProgress, this, &Downloader::onDownloadProgress);
return reply;
}
@@ -400,7 +428,7 @@ void DownloadFileTask::doTask(QFutureInterface<FileTaskResult> &fi)
{
QEventLoop el;
Downloader downloader;
- connect(&downloader, SIGNAL(finished()), &el, SLOT(quit()));
+ connect(&downloader, &Downloader::finished, &el, &QEventLoop::quit);
QList<FileTaskItem> items = taskItems();
if (!m_authenticator.isNull()) {
diff --git a/src/libs/installer/downloadfiletask.h b/src/libs/installer/downloadfiletask.h
index a682321f1..21908549d 100644
--- a/src/libs/installer/downloadfiletask.h
+++ b/src/libs/installer/downloadfiletask.h
@@ -30,7 +30,7 @@
#define DOWNLOADFILETASK_H
#include "abstractfiletask.h"
-#include "kdupdaterfiledownloaderfactory.h"
+#include "filedownloaderfactory.h"
#include <QAuthenticator>
Q_DECLARE_METATYPE(QAuthenticator)
diff --git a/src/libs/installer/downloadfiletask_p.h b/src/libs/installer/downloadfiletask_p.h
index 0e44e2aa3..3dfce27b4 100644
--- a/src/libs/installer/downloadfiletask_p.h
+++ b/src/libs/installer/downloadfiletask_p.h
@@ -36,6 +36,7 @@
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
+#include <QTimer>
#include <memory>
#include <unordered_map>
@@ -90,7 +91,7 @@ private slots:
void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
void onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator);
void onProxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator);
-
+ void onTimeout();
private:
bool testCanceled();
@@ -99,6 +100,7 @@ private:
private:
QFutureInterface<FileTaskResult> *m_futureInterface;
+ QTimer m_timer;
int m_finished;
QNetworkAccessManager m_nam;
QList<FileTaskItem> m_items;
diff --git a/src/libs/installer/elevatedexecuteoperation.cpp b/src/libs/installer/elevatedexecuteoperation.cpp
index 1241fc567..2cc988a4d 100644
--- a/src/libs/installer/elevatedexecuteoperation.cpp
+++ b/src/libs/installer/elevatedexecuteoperation.cpp
@@ -59,8 +59,9 @@ public:
bool showStandardError;
};
-ElevatedExecuteOperation::ElevatedExecuteOperation()
- : d(new Private(this))
+ElevatedExecuteOperation::ElevatedExecuteOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
+ , d(new Private(this))
{
// this operation has to "overwrite" the Execute operation from KDUpdater
setName(QLatin1String("Execute"));
@@ -75,12 +76,9 @@ bool ElevatedExecuteOperation::performOperation()
{
// This operation receives only one argument. It is the complete
// command line of the external program to execute.
- if (arguments().isEmpty()) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("at least 1"), QLatin1String("")));
+ if (!checkArgumentCount(1, INT_MAX))
return false;
- }
+
QStringList args;
foreach (const QString &argument, arguments()) {
if (argument!=QLatin1String("UNDOEXECUTE"))
@@ -140,7 +138,7 @@ bool ElevatedExecuteOperation::Private::run(const QStringList &arguments)
const bool success = QProcessWrapper::startDetached(args.front(), args.mid(1));
if (!success) {
q->setError(UserDefinedError);
- q->setErrorString(tr("Execution failed: Could not start detached: \"%1\"").arg(callstr));
+ q->setErrorString(tr("Cannot start detached: \"%1\"").arg(callstr));
}
return success;
}
@@ -159,12 +157,12 @@ bool ElevatedExecuteOperation::Private::run(const QStringList &arguments)
if (showStandardError)
process->setProcessChannelMode(QProcessWrapper::MergedChannels);
- connect(q, SIGNAL(cancelProcess()), process, SLOT(cancel()));
+ connect(q, &ElevatedExecuteOperation::cancelProcess, process, &QProcessWrapper::cancel);
//we still like the none blocking possibility to perform this operation without threads
QEventLoop loop;
if (QThread::currentThread() == qApp->thread()) {
- QObject::connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), &loop, SLOT(quit()));
+ QObject::connect(process, &QProcessWrapper::finished, &loop, &QEventLoop::quit);
}
//readProcessOutput should only called from this current Thread -> Qt::DirectConnection
QObject::connect(process, SIGNAL(readyRead()), q, SLOT(readProcessOutput()), Qt::DirectConnection);
@@ -183,7 +181,7 @@ bool ElevatedExecuteOperation::Private::run(const QStringList &arguments)
if (!success) {
q->setError(UserDefinedError);
//TODO: pass errorString() through the wrapper */
- q->setErrorString(tr("Execution failed: Could not start: \"%1\"(%2)").arg(callstr,
+ q->setErrorString(tr("Cannot start: \"%1\": %2").arg(callstr,
process->errorString()));
returnValue = false;
}
@@ -199,14 +197,14 @@ bool ElevatedExecuteOperation::Private::run(const QStringList &arguments)
if (process->exitStatus() == QProcessWrapper::CrashExit) {
q->setError(UserDefinedError);
- q->setErrorString(tr("Execution failed(Crash): \"%1\"").arg(callstr));
+ q->setErrorString(tr("Program crashed: \"%1\"").arg(callstr));
returnValue = false;
}
if (!allowedExitCodes.contains(process->exitCode())) {
q->setError(UserDefinedError);
if (customErrorMessage.isEmpty()) {
- q->setErrorString(tr("Execution failed(Unexpected exit code: %1): \"%2\"")
+ q->setErrorString(tr("Execution failed (Unexpected exit code: %1): \"%2\"")
.arg(QString::number(process->exitCode()), callstr));
} else {
q->setErrorString(customErrorMessage);
@@ -215,13 +213,14 @@ bool ElevatedExecuteOperation::Private::run(const QStringList &arguments)
QByteArray standardErrorOutput = process->readAllStandardError();
// in error case it would be useful to see something in verbose output
if (!standardErrorOutput.isEmpty())
- qWarning() << standardErrorOutput;
+ qWarning().noquote() << standardErrorOutput;
returnValue = false;
}
Q_ASSERT(process);
- process->deleteLater();
+ Q_ASSERT(process->state() == QProcessWrapper::NotRunning);
+ delete process;
process = 0;
return returnValue;
@@ -276,11 +275,6 @@ bool ElevatedExecuteOperation::testOperation()
return true;
}
-Operation *ElevatedExecuteOperation::clone() const
-{
- return new ElevatedExecuteOperation;
-}
-
void ElevatedExecuteOperation::backup()
{
}
diff --git a/src/libs/installer/elevatedexecuteoperation.h b/src/libs/installer/elevatedexecuteoperation.h
index fc9b42c66..5585e77a8 100644
--- a/src/libs/installer/elevatedexecuteoperation.h
+++ b/src/libs/installer/elevatedexecuteoperation.h
@@ -38,14 +38,13 @@ class INSTALLER_EXPORT ElevatedExecuteOperation : public QObject, public Operati
Q_OBJECT
public:
- ElevatedExecuteOperation();
+ explicit ElevatedExecuteOperation(PackageManagerCore *core);
~ElevatedExecuteOperation();
-
- virtual void backup();
- virtual bool performOperation();
- virtual bool undoOperation();
- virtual bool testOperation();
- virtual Operation *clone() const;
+
+ void backup() Q_DECL_OVERRIDE;
+ bool performOperation() Q_DECL_OVERRIDE;
+ bool undoOperation() Q_DECL_OVERRIDE;
+ bool testOperation() Q_DECL_OVERRIDE;
Q_SIGNALS:
void cancelProcess();
diff --git a/src/libs/installer/environmentvariablesoperation.cpp b/src/libs/installer/environmentvariablesoperation.cpp
index 00444f870..b80951d2b 100644
--- a/src/libs/installer/environmentvariablesoperation.cpp
+++ b/src/libs/installer/environmentvariablesoperation.cpp
@@ -40,7 +40,8 @@
using namespace QInstaller;
using namespace KDUpdater;
-EnvironmentVariableOperation::EnvironmentVariableOperation()
+EnvironmentVariableOperation::EnvironmentVariableOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("EnvironmentVariable"));
}
@@ -74,7 +75,7 @@ UpdateOperation::Error writeSetting(const QString &regPath,
oldValue->clear();
SettingsType registry(regPath, QSettingsWrapper::NativeFormat);
if (!registry.isWritable()) {
- *errorString = UpdateOperation::tr("Registry path %1 is not writable").arg(regPath);
+ *errorString = UpdateOperation::tr("Registry path %1 is not writable.").arg(regPath);
return UpdateOperation::UserDefinedError;
}
@@ -86,7 +87,7 @@ UpdateOperation::Error writeSetting(const QString &regPath,
registry.sync();
if (registry.status() != QSettingsWrapper::NoError) {
- *errorString = UpdateOperation::tr("Could not write to registry path %1").arg(regPath);
+ *errorString = UpdateOperation::tr("Cannot write to registry path %1.").arg(regPath);
return UpdateOperation::UserDefinedError;
}
@@ -115,21 +116,16 @@ UpdateOperation::Error undoSetting(const QString &regPath,
bool EnvironmentVariableOperation::performOperation()
{
- QStringList args = arguments();
- if (args.count() < 2 || args.count() > 4) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("2 to 4"), QLatin1String("")));
+ if (!checkArgumentCount(2, 4))
return false;
- }
- const QString name = arguments().at(0);
- const QString value = arguments().at(1);
- bool isPersistent = false;
+ const QStringList args = arguments();
+ const QString name = args.at(0);
+ const QString value = args.at(1);
#ifdef Q_OS_WIN
- isPersistent = arguments().count() >= 3 ? arguments().at(2) == QLatin1String("true") : true;
- const bool isSystemWide = arguments().count() >= 4 ? arguments().at(3) == QLatin1String("true") : false;
+ const bool isPersistent = arguments().count() > 2 ? arguments().at(2) == QLatin1String("true") : true;
+ const bool isSystemWide = arguments().count() > 3 ? arguments().at(3) == QLatin1String("true") : false;
QString oldvalue;
if (isPersistent) {
const QString regPath = isSystemWide ? QLatin1String("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet"
@@ -152,9 +148,8 @@ bool EnvironmentVariableOperation::performOperation()
setValue(QLatin1String("oldvalue"), oldvalue);
return true;
}
-#endif
Q_ASSERT(!isPersistent);
- Q_UNUSED(isPersistent)
+#endif
setValue(QLatin1String("oldvalue"), Environment::instance().value(name));
Environment::instance().setTemporaryValue(name, value);
@@ -209,8 +204,3 @@ bool EnvironmentVariableOperation::testOperation()
{
return true;
}
-
-Operation *EnvironmentVariableOperation::clone() const
-{
- return new EnvironmentVariableOperation();
-}
diff --git a/src/libs/installer/environmentvariablesoperation.h b/src/libs/installer/environmentvariablesoperation.h
index bda0dd2cd..3c5252bc6 100644
--- a/src/libs/installer/environmentvariablesoperation.h
+++ b/src/libs/installer/environmentvariablesoperation.h
@@ -37,13 +37,12 @@ class INSTALLER_EXPORT EnvironmentVariableOperation : public Operation
{
Q_DECLARE_TR_FUNCTIONS(QInstaller::EnvironmentVariableOperation)
public:
- EnvironmentVariableOperation();
+ explicit EnvironmentVariableOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
};
}
diff --git a/src/libs/installer/errors.h b/src/libs/installer/errors.h
index 7c66d09c2..117eb5119 100644
--- a/src/libs/installer/errors.h
+++ b/src/libs/installer/errors.h
@@ -39,13 +39,15 @@ namespace QInstaller {
class Error : public std::exception
{
public:
- Error() {}
+ Error()
+ {}
+
explicit Error(const QString &message)
: m_message(message)
- {
- qDebug() << "create Error-Exception:" << message;
- }
- virtual ~Error() throw() {}
+ {}
+
+ virtual ~Error() throw()
+ {}
QString message() const { return m_message; }
diff --git a/src/libs/installer/extractarchiveoperation.cpp b/src/libs/installer/extractarchiveoperation.cpp
index 230d0f883..c41f029e3 100644
--- a/src/libs/installer/extractarchiveoperation.cpp
+++ b/src/libs/installer/extractarchiveoperation.cpp
@@ -26,17 +26,15 @@
**
**************************************************************************/
-#include "extractarchiveoperation.h"
#include "extractarchiveoperation_p.h"
-#include <QtCore/QEventLoop>
-#include <QtCore/QThread>
-#include <QtCore/QThreadPool>
+#include <QEventLoop>
+#include <QThreadPool>
-using namespace QInstaller;
+namespace QInstaller {
-
-ExtractArchiveOperation::ExtractArchiveOperation()
+ExtractArchiveOperation::ExtractArchiveOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("Extract"));
}
@@ -48,55 +46,46 @@ void ExtractArchiveOperation::backup()
bool ExtractArchiveOperation::performOperation()
{
- const QStringList args = arguments();
- if (args.count() != 2) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("exactly 2"), QLatin1String("")));
+ if (!checkArgumentCount(2))
return false;
- }
- const QString archivePath = args.first();
+ const QStringList args = arguments();
+ const QString archivePath = args.at(0);
const QString targetDir = args.at(1);
Receiver receiver;
Callback callback;
- connect(&callback, SIGNAL(currentFileChanged(QString)), this, SLOT(fileFinished(QString)));
- connect(&callback, SIGNAL(progressChanged(double)), this, SIGNAL(progressChanged(double)));
+ connect(&callback, &Callback::currentFileChanged, this, &ExtractArchiveOperation::fileFinished);
+ connect(&callback, &Callback::progressChanged, this, &ExtractArchiveOperation::progressChanged);
- if (PackageManagerCore *core = this->value(QLatin1String("installer")).value<PackageManagerCore*>()) {
- connect(core, SIGNAL(statusChanged(QInstaller::PackageManagerCore::Status)), &callback,
- SLOT(statusChanged(QInstaller::PackageManagerCore::Status)));
+ if (PackageManagerCore *core = packageManager()) {
+ connect(core, &PackageManagerCore::statusChanged, &callback, &Callback::statusChanged);
}
- //Runnable is derived from QRunable which will be deleted by the ThreadPool -> no parent is needed
Runnable *runnable = new Runnable(archivePath, targetDir, &callback);
- connect(runnable, SIGNAL(finished(bool,QString)), &receiver, SLOT(runnableFinished(bool,QString)),
+ connect(runnable, &Runnable::finished, &receiver, &Receiver::runnableFinished,
Qt::QueuedConnection);
QEventLoop loop;
- connect(&receiver, SIGNAL(finished()), &loop, SLOT(quit()));
+ connect(&receiver, &Receiver::finished, &loop, &QEventLoop::quit);
if (QThreadPool::globalInstance()->tryStart(runnable)) {
loop.exec();
} else {
- // in case there is no availabe thread we should call it directly this is more a hack
+ // HACK: In case there is no availabe thread we should call it directly.
runnable->run();
receiver.runnableFinished(true, QString());
}
- typedef QPair<QString, QString> StringPair;
- QVector<StringPair> backupFiles = callback.backupFiles;
-
- //TODO use backups for rollback, too? doesn't work for uninstallation though
+ // TODO: Use backups for rollback, too? Doesn't work for uninstallation though.
- //delete all backups we can delete right now, remember the rest
- foreach (const StringPair &i, backupFiles)
+ // delete all backups we can delete right now, remember the rest
+ foreach (const Backup &i, callback.backupFiles())
deleteFileNowOrLater(i.second);
- if (!receiver.success) {
+ if (!receiver.success()) {
setError(UserDefinedError);
- setErrorString(receiver.errorString);
+ setErrorString(receiver.errorString());
return false;
}
return true;
@@ -105,17 +94,16 @@ bool ExtractArchiveOperation::performOperation()
bool ExtractArchiveOperation::undoOperation()
{
Q_ASSERT(arguments().count() == 2);
- //const QString archivePath = arguments().first();
- //const QString targetDir = arguments().last();
-
const QStringList files = value(QLatin1String("files")).toStringList();
WorkerThread *const thread = new WorkerThread(this, files);
- connect(thread, SIGNAL(currentFileChanged(QString)), this, SIGNAL(outputTextChanged(QString)));
- connect(thread, SIGNAL(progressChanged(double)), this, SIGNAL(progressChanged(double)));
+ connect(thread, &WorkerThread::currentFileChanged, this,
+ &ExtractArchiveOperation::outputTextChanged);
+ connect(thread, &WorkerThread::progressChanged, this,
+ &ExtractArchiveOperation::progressChanged);
QEventLoop loop;
- connect(thread, SIGNAL(finished()), &loop, SLOT(quit()), Qt::QueuedConnection);
+ connect(thread, &QThread::finished, &loop, &QEventLoop::quit, Qt::QueuedConnection);
thread->start();
loop.exec();
thread->deleteLater();
@@ -127,18 +115,16 @@ bool ExtractArchiveOperation::testOperation()
return true;
}
-Operation *ExtractArchiveOperation::clone() const
-{
- return new ExtractArchiveOperation();
-}
-
/*!
- This slot is direct connected to the caller so please don't call it from another thread in the same time.
+ This slot is direct connected to the caller so please don't call it from another thread in the
+ same time.
*/
void ExtractArchiveOperation::fileFinished(const QString &filename)
{
QStringList files = value(QLatin1String("files")).toStringList();
files.prepend(filename);
setValue(QLatin1String("files"), files);
- emit outputTextChanged(filename);
+ emit outputTextChanged(QDir::toNativeSeparators(filename));
}
+
+} // namespace QInstaller
diff --git a/src/libs/installer/extractarchiveoperation.h b/src/libs/installer/extractarchiveoperation.h
index ab22f4000..45c67a9cb 100644
--- a/src/libs/installer/extractarchiveoperation.h
+++ b/src/libs/installer/extractarchiveoperation.h
@@ -41,13 +41,12 @@ class INSTALLER_EXPORT ExtractArchiveOperation : public QObject, public Operatio
friend class WorkerThread;
public:
- ExtractArchiveOperation();
+ explicit ExtractArchiveOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
Q_SIGNALS:
void outputTextChanged(const QString &progress);
diff --git a/src/libs/installer/extractarchiveoperation_p.h b/src/libs/installer/extractarchiveoperation_p.h
index 03d45a6e3..f333da366 100644
--- a/src/libs/installer/extractarchiveoperation_p.h
+++ b/src/libs/installer/extractarchiveoperation_p.h
@@ -31,24 +31,23 @@
#include "extractarchiveoperation.h"
#include "fileutils.h"
+#include "lib7z_extract.h"
#include "lib7z_facade.h"
#include "packagemanagercore.h"
-#include <QtCore/QDir>
-#include <QtCore/QFile>
-#include <QtCore/QPair>
-#include <QtCore/QThread>
-#include <QtCore/QVector>
+#include <QRunnable>
+#include <QThread>
namespace QInstaller {
class WorkerThread : public QThread
{
Q_OBJECT
+ Q_DISABLE_COPY(WorkerThread)
+
public:
- WorkerThread(ExtractArchiveOperation *op, const QStringList &files, QObject *parent = 0)
- : QThread(parent)
- , m_files(files)
+ WorkerThread(ExtractArchiveOperation *op, const QStringList &files)
+ : m_files(files)
, m_op(op)
{
setObjectName(QLatin1String("ExtractArchive"));
@@ -56,26 +55,25 @@ public:
void run()
{
- ExtractArchiveOperation *const op = m_op;//dynamic_cast< ExtractArchiveOperation* >(parent());
- Q_ASSERT(op != 0);
+ Q_ASSERT(m_op != 0);
int removedCounter = 0;
foreach (const QString &file, m_files) {
removedCounter++;
+
const QFileInfo fi(file);
- emit currentFileChanged(file);
+ emit currentFileChanged(QDir::toNativeSeparators(file));
emit progressChanged(double(removedCounter) / m_files.count());
if (fi.isFile() || fi.isSymLink()) {
- op->deleteFileNowOrLater(fi.absoluteFilePath());
+ m_op->deleteFileNowOrLater(fi.absoluteFilePath());
} else if (fi.isDir()) {
- const QDir d = fi.dir();
removeSystemGeneratedFiles(file);
- d.rmdir(file); // directory may not exist
+ fi.dir().rmdir(file); // directory may not exist
}
}
}
-Q_SIGNALS:
+signals:
void currentFileChanged(const QString &filename);
void progressChanged(double);
@@ -84,44 +82,42 @@ private:
ExtractArchiveOperation *m_op;
};
+typedef QPair<QString, QString> Backup;
+typedef QVector<Backup> BackupFiles;
class ExtractArchiveOperation::Callback : public QObject, public Lib7z::ExtractCallback
{
Q_OBJECT
+ Q_DISABLE_COPY(Callback)
public:
- HRESULT state;
- bool createBackups;
- QVector<QPair<QString, QString> > backupFiles;
-
- Callback() : state(S_OK), createBackups(true) {}
+ Callback() = default;
-Q_SIGNALS:
- void currentFileChanged(const QString &filename);
- void progressChanged(double progress);
+ BackupFiles backupFiles() const {
+ return m_backupFiles;
+ }
-public Q_SLOTS:
+public slots:
void statusChanged(QInstaller::PackageManagerCore::Status status)
{
switch(status) {
case PackageManagerCore::Canceled:
- state = E_ABORT;
+ m_state = E_ABORT;
break;
case PackageManagerCore::Failure:
- state = E_FAIL;
+ m_state = E_FAIL;
break;
- default: // fall through
- // PackageManagerCore::Unfinished, PackageManagerCore::Success, PackageManagerCore::Running
- // PackageManagerCore::ForceUpdate
-
- // already set
- //state = S_OK;
+ default: // ignore all other status values
break;
}
}
-protected:
- void setCurrentFile(const QString &filename)
+signals:
+ void currentFileChanged(const QString &filename);
+ void progressChanged(double progress);
+
+private:
+ void setCurrentFile(const QString &filename) Q_DECL_OVERRIDE
{
emit currentFileChanged(QDir::toNativeSeparators(filename));
}
@@ -136,94 +132,106 @@ protected:
return res;
}
- bool prepareForFile(const QString &filename)
+ bool prepareForFile(const QString &filename) Q_DECL_OVERRIDE
{
- if (!createBackups)
- return true;
if (!QFile::exists(filename))
return true;
const QString backup = generateBackupName(filename);
QFile f(filename);
const bool renamed = f.rename(backup);
if (f.exists() && !renamed) {
- qCritical("Could not rename %s to %s: %s", qPrintable(filename), qPrintable(backup),
+ qCritical("Cannot rename %s to %s: %s", qPrintable(filename), qPrintable(backup),
qPrintable(f.errorString()));
return false;
}
- backupFiles.push_back(qMakePair(filename, backup));
+ m_backupFiles.append(qMakePair(filename, backup));
return true;
}
- HRESULT setCompleted(quint64 completed, quint64 total)
+ HRESULT setCompleted(quint64 completed, quint64 total) Q_DECL_OVERRIDE
{
emit progressChanged(double(completed) / total);
- return state;
+ return m_state;
}
+
+private:
+ HRESULT m_state = S_OK;
+ BackupFiles m_backupFiles;
};
class ExtractArchiveOperation::Runnable : public QObject, public QRunnable
{
Q_OBJECT
+ Q_DISABLE_COPY(Runnable)
public:
- Runnable(const QString &archivePath_, const QString &targetDir_, ExtractArchiveOperation::Callback *callback_)
- : QObject()
- , QRunnable()
- , archivePath(archivePath_)
- , targetDir(targetDir_)
- , callback(callback_) {}
+ Runnable(const QString &archivePath, const QString &targetDir,
+ ExtractArchiveOperation::Callback *callback)
+ : m_archivePath(archivePath)
+ , m_targetDir(targetDir)
+ , m_callback(callback)
+ {}
void run()
{
- QFile archive(archivePath);
+ QFile archive(m_archivePath);
if (!archive.open(QIODevice::ReadOnly)) {
-
- emit finished(false, tr("Could not open %1 for reading: %2.").arg(archivePath, archive.errorString()));
+ emit finished(false, tr("Cannot open archive \"%1\" for reading: %2").arg(m_archivePath,
+ archive.errorString()));
return;
}
try {
- Lib7z::extractArchive(&archive, targetDir, callback);
+ Lib7z::extractArchive(&archive, m_targetDir, m_callback);
emit finished(true, QString());
} catch (const Lib7z::SevenZipException& e) {
- emit finished(false, tr("Error while extracting '%1': %2").arg(archivePath, e.message()));
+ emit finished(false, tr("Error while extracting archive \"%1\": %2").arg(m_archivePath,
+ e.message()));
} catch (...) {
- emit finished(false, tr("Unknown exception caught while extracting %1.").arg(archivePath));
+ emit finished(false, tr("Unknown exception caught while extracting \"%1\".")
+ .arg(m_archivePath));
}
}
-Q_SIGNALS:
+signals:
void finished(bool success, const QString &errorString);
private:
- const QString archivePath;
- const QString targetDir;
- ExtractArchiveOperation::Callback *const callback;
+ QString m_archivePath;
+ QString m_targetDir;
+ ExtractArchiveOperation::Callback *m_callback;
};
-
class ExtractArchiveOperation::Receiver : public QObject
{
Q_OBJECT
+ Q_DISABLE_COPY(Receiver)
+
public:
- explicit Receiver(QObject *parent = 0)
- : QObject(parent)
- , success(false) {}
+ Receiver() = default;
-public Q_SLOTS:
+ bool success() const {
+ return m_success;
+ }
+
+ QString errorString() const {
+ return m_errorString;
+ }
+
+public slots:
void runnableFinished(bool ok, const QString &msg)
{
- success = ok;
- errorString = msg;
+ m_success = ok;
+ m_errorString = msg;
emit finished();
}
-Q_SIGNALS:
+signals:
void finished();
-public:
- bool success;
- QString errorString;
+private:
+ bool m_success = false;
+ QString m_errorString;
};
}
diff --git a/src/libs/installer/fakestopprocessforupdateoperation.cpp b/src/libs/installer/fakestopprocessforupdateoperation.cpp
index a1dc60057..69870fcab 100644
--- a/src/libs/installer/fakestopprocessforupdateoperation.cpp
+++ b/src/libs/installer/fakestopprocessforupdateoperation.cpp
@@ -34,7 +34,8 @@
using namespace KDUpdater;
using namespace QInstaller;
-FakeStopProcessForUpdateOperation::FakeStopProcessForUpdateOperation()
+FakeStopProcessForUpdateOperation::FakeStopProcessForUpdateOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("FakeStopProcessForUpdate"));
}
@@ -51,15 +52,12 @@ bool FakeStopProcessForUpdateOperation::performOperation()
bool FakeStopProcessForUpdateOperation::undoOperation()
{
setError(KDUpdater::UpdateOperation::NoError);
- if (arguments().size() != 1) {
- setError(KDUpdater::UpdateOperation::InvalidArguments, tr("Number of arguments does not "
- "match: one is required"));
+ if (!checkArgumentCount(1))
return false;
- }
- PackageManagerCore *const core = value(QLatin1String("installer")).value<PackageManagerCore*>();
+ PackageManagerCore *const core = packageManager();
if (!core) {
- setError(KDUpdater::UpdateOperation::UserDefinedError, tr("Could not get package manager "
+ setError(KDUpdater::UpdateOperation::UserDefinedError, tr("Cannot get package manager "
"core."));
return false;
}
@@ -88,8 +86,3 @@ bool FakeStopProcessForUpdateOperation::testOperation()
{
return true;
}
-
-Operation *FakeStopProcessForUpdateOperation::clone() const
-{
- return new FakeStopProcessForUpdateOperation();
-}
diff --git a/src/libs/installer/fakestopprocessforupdateoperation.h b/src/libs/installer/fakestopprocessforupdateoperation.h
index ba5de745c..6fd5da44b 100644
--- a/src/libs/installer/fakestopprocessforupdateoperation.h
+++ b/src/libs/installer/fakestopprocessforupdateoperation.h
@@ -38,13 +38,12 @@ class INSTALLER_EXPORT FakeStopProcessForUpdateOperation : public QObject, publi
Q_OBJECT
public:
- FakeStopProcessForUpdateOperation();
+ explicit FakeStopProcessForUpdateOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
};
}
diff --git a/src/libs/installer/fileio.cpp b/src/libs/installer/fileio.cpp
index 60ebd1011..dac2e4c50 100644
--- a/src/libs/installer/fileio.cpp
+++ b/src/libs/installer/fileio.cpp
@@ -33,6 +33,7 @@
#include <QCoreApplication>
#include <QByteArray>
+#include <QDir>
#include <QFileDevice>
#include <QString>
@@ -102,7 +103,8 @@ void QInstaller::openForRead(QFileDevice *dev)
Q_ASSERT(dev);
if (!dev->open(QIODevice::ReadOnly)) {
throw Error(QCoreApplication::translate("QInstaller",
- "Cannot open file %1 for reading: %2").arg(dev->fileName(), dev->errorString()));
+ "Cannot open file \"%1\" for reading: %2").arg(
+ QDir::toNativeSeparators(dev->fileName()), dev->errorString()));
}
}
@@ -111,7 +113,8 @@ void QInstaller::openForWrite(QFileDevice *dev)
Q_ASSERT(dev);
if (!dev->open(QIODevice::WriteOnly)) {
throw Error(QCoreApplication::translate("QInstaller",
- "Cannot open file %1 for writing: %2").arg(dev->fileName(), dev->errorString()));
+ "Cannot open file \"%1\" for writing: %2").arg(
+ QDir::toNativeSeparators(dev->fileName()), dev->errorString()));
}
}
@@ -120,7 +123,8 @@ void QInstaller::openForAppend(QFileDevice *dev)
Q_ASSERT(dev);
if (!dev->open(QIODevice::WriteOnly | QIODevice::Append)) {
throw Error(QCoreApplication::translate("QInstaller",
- "Cannot open file %1 for writing: %2").arg(dev->fileName(), dev->errorString()));
+ "Cannot open file \"%1\" for writing: %2").arg(
+ QDir::toNativeSeparators(dev->fileName()), dev->errorString()));
}
}
@@ -154,7 +158,7 @@ qint64 QInstaller::blockingCopy(QFileDevice *in, QFileDevice *out, qint64 size)
size -= actual;
actual = qMin(blockSize, size);
} catch (const Error &error) {
- throw Error(QCoreApplication::translate("QInstaller", "Copy failed. Error: %1")
+ throw Error(QCoreApplication::translate("QInstaller", "Copy failed: %1")
.arg(error.message()));
}
}
diff --git a/src/libs/installer/fileutils.cpp b/src/libs/installer/fileutils.cpp
index 60b912b6e..58744b3c2 100644
--- a/src/libs/installer/fileutils.cpp
+++ b/src/libs/installer/fileutils.cpp
@@ -176,10 +176,11 @@ void QInstaller::removeFiles(const QString &path, bool ignoreErrors)
QFile f(fi.filePath());
if (!f.remove()) {
const QString errorMessage = QCoreApplication::translate("QInstaller",
- "Could not remove file %1: %2").arg(f.fileName(), f.errorString());
+ "Cannot remove file \"%1\": %2").arg(
+ QDir::toNativeSeparators(f.fileName()), f.errorString());
if (!ignoreErrors)
throw Error(errorMessage);
- qWarning() << errorMessage;
+ qWarning().noquote() << errorMessage;
}
}
}
@@ -217,10 +218,11 @@ void QInstaller::removeDirectory(const QString &path, bool ignoreErrors)
errno = 0;
if (d.exists(path) && !d.rmdir(dir)) {
const QString errorMessage = QCoreApplication::translate("QInstaller",
- "Could not remove folder %1: %2").arg(dir, errnoToQString(errno));
+ "Cannot remove directory \"%1\": %2").arg(QDir::toNativeSeparators(dir),
+ errnoToQString(errno));
if (!ignoreErrors)
throw Error(errorMessage);
- qWarning() << errorMessage;
+ qWarning().noquote() << errorMessage;
}
}
}
@@ -264,7 +266,7 @@ void QInstaller::removeDirectoryThreaded(const QString &path, bool ignoreErrors)
{
RemoveDirectoryThread thread(path, ignoreErrors);
QEventLoop loop;
- QObject::connect(&thread, SIGNAL(finished()), &loop, SLOT(quit()));
+ QObject::connect(&thread, &RemoveDirectoryThread::finished, &loop, &QEventLoop::quit);
thread.start();
loop.exec();
if (!thread.error().isEmpty())
@@ -287,8 +289,8 @@ void QInstaller::copyDirectoryContents(const QString &sourceDir, const QString &
Q_ASSERT(QFileInfo(sourceDir).isDir());
Q_ASSERT(!QFileInfo(targetDir).exists() || QFileInfo(targetDir).isDir());
if (!QDir().mkpath(targetDir)) {
- throw Error(QCoreApplication::translate("QInstaller", "Could not create folder %1")
- .arg(targetDir));
+ throw Error(QCoreApplication::translate("QInstaller", "Cannot create directory \"%1\".")
+ .arg(QDir::toNativeSeparators(targetDir)));
}
QDirIterator it(sourceDir, QDir::NoDotAndDotDot | QDir::AllEntries);
while (it.hasNext()) {
@@ -301,8 +303,10 @@ void QInstaller::copyDirectoryContents(const QString &sourceDir, const QString &
const QString target = QDir(targetDir).absoluteFilePath(i.fileName());
if (!f.copy(target)) {
throw Error(QCoreApplication::translate("QInstaller",
- "Could not copy file from %1 to %2: %3").arg(f.fileName(), target,
- f.errorString()));
+ "Cannot copy file from \"%1\" to \"%2\": %3").arg(
+ QDir::toNativeSeparators(f.fileName()),
+ QDir::toNativeSeparators(target),
+ f.errorString()));
}
}
}
@@ -313,8 +317,8 @@ void QInstaller::moveDirectoryContents(const QString &sourceDir, const QString &
Q_ASSERT(QFileInfo(sourceDir).isDir());
Q_ASSERT(!QFileInfo(targetDir).exists() || QFileInfo(targetDir).isDir());
if (!QDir().mkpath(targetDir)) {
- throw Error(QCoreApplication::translate("QInstaller", "Could not create folder %1")
- .arg(targetDir));
+ throw Error(QCoreApplication::translate("QInstaller", "Cannot create directory \"%1\".")
+ .arg(QDir::toNativeSeparators(targetDir)));
}
QDirIterator it(sourceDir, QDir::NoDotAndDotDot | QDir::AllEntries);
while (it.hasNext()) {
@@ -330,8 +334,10 @@ void QInstaller::moveDirectoryContents(const QString &sourceDir, const QString &
const QString target = QDir(targetDir).absoluteFilePath(i.fileName());
if (!f.rename(target)) {
throw Error(QCoreApplication::translate("QInstaller",
- "Could not move file from %1 to %2: %3").arg(f.fileName(), target,
- f.errorString()));
+ "Cannot move file from \"%1\" to \"%2\": %3").arg(
+ QDir::toNativeSeparators(f.fileName()),
+ QDir::toNativeSeparators(target),
+ f.errorString()));
}
}
}
@@ -341,8 +347,8 @@ void QInstaller::mkdir(const QString &path)
{
errno = 0;
if (!QDir().mkdir(QFileInfo(path).absoluteFilePath())) {
- throw Error(QCoreApplication::translate("QInstaller", "Could not create folder %1: %2")
- .arg(path, errnoToQString(errno)));
+ throw Error(QCoreApplication::translate("QInstaller", "Cannot create directory \"%1\": %2")
+ .arg(QDir::toNativeSeparators(path), errnoToQString(errno)));
}
}
@@ -350,8 +356,8 @@ void QInstaller::mkpath(const QString &path)
{
errno = 0;
if (!QDir().mkpath(QFileInfo(path).absoluteFilePath())) {
- throw Error(QCoreApplication::translate("QInstaller", "Could not create folder %1: %2")
- .arg(path, errnoToQString(errno)));
+ throw Error(QCoreApplication::translate("QInstaller", "Cannot create directory \"%1\": %2")
+ .arg(QDir::toNativeSeparators(path), errnoToQString(errno)));
}
}
@@ -361,7 +367,7 @@ QString QInstaller::generateTemporaryFileName(const QString &templ)
QTemporaryFile f;
if (!f.open()) {
throw Error(QCoreApplication::translate("QInstaller",
- "Could not open temporary file: %1").arg(f.errorString()));
+ "Cannot open temporary file: %1").arg(f.errorString()));
}
return f.fileName();
}
@@ -380,7 +386,7 @@ QString QInstaller::generateTemporaryFileName(const QString &templ)
QFile f(tmp.arg(templ, suffix).arg(count));
if (!f.open(QIODevice::WriteOnly)) {
throw Error(QCoreApplication::translate("QInstaller",
- "Could not open temporary file for template %1: %2").arg(templ, f.errorString()));
+ "Cannot open temporary file for template %1: %2").arg(templ, f.errorString()));
}
f.remove();
return f.fileName();
@@ -481,14 +487,13 @@ void QInstaller::setApplicationIcon(const QString &application, const QString &i
{
QFile iconFile(icon);
if (!iconFile.open(QIODevice::ReadOnly)) {
- qWarning() << QString::fromLatin1("Could not use '%1' as application icon: %2.")
- .arg(icon, iconFile.errorString());
+ qWarning() << "Cannot use" << icon << "as an application icon:" << iconFile.errorString();
return;
}
if (QImageReader::imageFormat(icon) != "ico") {
- qWarning() << QString::fromLatin1("Could not use '%1' as application icon, unsupported format %2.")
- .arg(icon, QLatin1String(QImageReader::imageFormat(icon)));
+ qWarning() << "Cannot use" << icon << "as an application icon, unsupported format"
+ << QImageReader::imageFormat(icon).constData();
return;
}
@@ -574,3 +579,19 @@ bool QInstaller::isInBundle(const QString &path, QString *bundlePath)
#endif
return false;
}
+
+/*!
+ Replaces the path \a before with the path \a after at the beginning of \a path and returns
+ the replaced path. If \a before cannot be found in \a path, the original value is returned.
+*/
+QString QInstaller::replacePath(const QString &path, const QString &before, const QString &after)
+{
+ if (path.isEmpty() || before.isEmpty())
+ return path;
+
+ QString pathToPatch = QDir::cleanPath(path);
+ const QString pathToReplace = QDir::cleanPath(before);
+ if (pathToPatch.startsWith(pathToReplace))
+ return QDir::cleanPath(after) + pathToPatch.mid(pathToReplace.size());
+ return path;
+}
diff --git a/src/libs/installer/fileutils.h b/src/libs/installer/fileutils.h
index 74436bef7..ae08f5ff3 100644
--- a/src/libs/installer/fileutils.h
+++ b/src/libs/installer/fileutils.h
@@ -94,6 +94,8 @@ private:
quint64 INSTALLER_EXPORT fileSize(const QFileInfo &info);
bool INSTALLER_EXPORT isInBundle(const QString &path, QString *bundlePath = 0);
+ QString replacePath(const QString &path, const QString &pathBefore, const QString &pathAfter);
+
#ifdef Q_OS_WIN
QString INSTALLER_EXPORT getLongPathName(const QString &name);
QString INSTALLER_EXPORT getShortPathName(const QString &name);
diff --git a/src/libs/installer/globals.cpp b/src/libs/installer/globals.cpp
index df97c11b0..5f3009905 100644
--- a/src/libs/installer/globals.cpp
+++ b/src/libs/installer/globals.cpp
@@ -30,6 +30,7 @@
const char IFW_COMPONENT_CHECKER[] = "ifw.componentChecker";
const char IFW_RESOURCES[] = "ifw.resources";
const char IFW_TRANSLATIONS[] = "ifw.translations";
+const char IFW_NETWORK[] = "ifw.network";
namespace QInstaller
{
@@ -37,13 +38,15 @@ namespace QInstaller
Q_LOGGING_CATEGORY(lcComponentChecker, IFW_COMPONENT_CHECKER)
Q_LOGGING_CATEGORY(lcResources, IFW_RESOURCES)
Q_LOGGING_CATEGORY(lcTranslations, IFW_TRANSLATIONS)
+Q_LOGGING_CATEGORY(lcNetwork, IFW_NETWORK)
QStringList loggingCategories()
{
static QStringList categories = QStringList()
<< QLatin1String(IFW_COMPONENT_CHECKER)
<< QLatin1String(IFW_RESOURCES)
- << QLatin1String(IFW_TRANSLATIONS);
+ << QLatin1String(IFW_TRANSLATIONS)
+ << QLatin1String(IFW_NETWORK);
return categories;
}
diff --git a/src/libs/installer/globals.h b/src/libs/installer/globals.h
index fd45b61f2..a5bd47ac8 100644
--- a/src/libs/installer/globals.h
+++ b/src/libs/installer/globals.h
@@ -38,6 +38,7 @@ namespace QInstaller {
INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcComponentChecker)
INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcResources)
INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcTranslations)
+INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcNetwork)
QStringList INSTALLER_EXPORT loggingCategories();
diff --git a/src/libs/installer/globalsettingsoperation.cpp b/src/libs/installer/globalsettingsoperation.cpp
index 12b57413b..f8f7c112d 100644
--- a/src/libs/installer/globalsettingsoperation.cpp
+++ b/src/libs/installer/globalsettingsoperation.cpp
@@ -31,7 +31,8 @@
using namespace QInstaller;
-GlobalSettingsOperation::GlobalSettingsOperation()
+GlobalSettingsOperation::GlobalSettingsOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("GlobalConfig"));
}
@@ -49,7 +50,7 @@ bool GlobalSettingsOperation::performOperation()
if (!settings->isWritable()) {
setError(UserDefinedError);
- setErrorString(tr("Settings are not writable"));
+ setErrorString(tr("Settings are not writable."));
return false;
}
@@ -59,7 +60,7 @@ bool GlobalSettingsOperation::performOperation()
if (settings->status() != QSettingsWrapper::NoError) {
setError(UserDefinedError);
- setErrorString(tr("Failed to write settings"));
+ setErrorString(tr("Failed to write settings."));
return false;
}
@@ -92,24 +93,15 @@ bool GlobalSettingsOperation::testOperation()
return true;
}
-Operation *GlobalSettingsOperation::clone() const
-{
- return new GlobalSettingsOperation();
-}
-
QSettingsWrapper *GlobalSettingsOperation::setup(QString *key, QString *value, const QStringList &arguments)
{
- if (arguments.count() != 3 && arguments.count() != 4 && arguments.count() != 5) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments.count()).arg(tr("3, 4 or 5"), QLatin1String("")));
+ if (!checkArgumentCount(3, 5))
return 0;
- }
if (arguments.count() == 5) {
QSettingsWrapper::Scope scope = QSettingsWrapper::UserScope;
if (arguments.at(0) == QLatin1String("SystemScope"))
- scope = QSettingsWrapper::SystemScope;
+ scope = QSettingsWrapper::SystemScope;
const QString &company = arguments.at(1);
const QString &application = arguments.at(2);
*key = arguments.at(3);
diff --git a/src/libs/installer/globalsettingsoperation.h b/src/libs/installer/globalsettingsoperation.h
index be6e79c5d..fe5d14edb 100644
--- a/src/libs/installer/globalsettingsoperation.h
+++ b/src/libs/installer/globalsettingsoperation.h
@@ -38,13 +38,12 @@ class INSTALLER_EXPORT GlobalSettingsOperation : public Operation
{
Q_DECLARE_TR_FUNCTIONS(QInstaller::GlobalSettingsOperation)
public:
- GlobalSettingsOperation();
+ explicit GlobalSettingsOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
private:
QSettingsWrapper *setup(QString *key, QString *value, const QStringList &args);
diff --git a/src/libs/installer/init.cpp b/src/libs/installer/init.cpp
index cf3ed918d..285c7ebc9 100644
--- a/src/libs/installer/init.cpp
+++ b/src/libs/installer/init.cpp
@@ -48,75 +48,20 @@
#include "settingsoperation.h"
#include "consumeoutputoperation.h"
-
+#include "lib7z_facade.h"
#include "utils.h"
-#include "kdupdaterupdateoperationfactory.h"
-#include "kdupdaterfiledownloaderfactory.h"
-
-#include "7zCrc.h"
+#include "updateoperationfactory.h"
+#include "filedownloaderfactory.h"
#include <QtPlugin>
#include <QElapsedTimer>
#include <iostream>
-namespace NArchive {
- namespace NXz {
- void registerArcxz();
- }
- namespace NSplit {
- void registerArcSplit();
- }
- namespace NLzma {
- namespace NLzmaAr {
- void registerArcLzma();
- }
- namespace NLzma86Ar {
- void registerArcLzma86();
- }
- }
-}
-
-void registerArc7z();
-
-void registerCodecBCJ();
-void registerCodecBCJ2();
-
-void registerCodecCopy();
-void registerCodecLZMA();
-void registerCodecLZMA2();
-
-void registerCodecDelta();
-void registerCodecBranch();
-void registerCodecByteSwap();
-
using namespace KDUpdater;
using namespace QInstaller;
-static void initArchives()
-{
- CrcGenerateTable();
-
- registerArc7z();
-
- registerCodecBCJ();
- registerCodecBCJ2();
-
- registerCodecCopy();
- registerCodecLZMA();
- registerCodecLZMA2();
-
- registerCodecDelta();
- registerCodecBranch();
- registerCodecByteSwap();
-
- NArchive::NXz::registerArcxz();
- NArchive::NSplit::registerArcSplit();
- NArchive::NLzma::NLzmaAr::registerArcLzma();
- NArchive::NLzma::NLzma86Ar::registerArcLzma86();
-}
-
#if defined(QT_STATIC)
static void initResources()
{
@@ -193,7 +138,8 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt
void QInstaller::init()
{
- ::initArchives();
+ Lib7z::initSevenZ();
+
#if defined(QT_STATIC)
::initResources();
#endif
diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro
index 53daf978d..d641ff1fc 100644
--- a/src/libs/installer/installer.pro
+++ b/src/libs/installer/installer.pro
@@ -34,7 +34,8 @@ QT += \
xml \
concurrent \
widgets \
- core-private
+ core-private \
+ qml-private
win32:QT += winextras
HEADERS += packagemanagercore.h \
@@ -124,7 +125,11 @@ HEADERS += packagemanagercore.h \
serverauthenticationdialog.h \
keepaliveobject.h \
systeminfo.h \
- localsocket.h
+ packagesource.h \
+ lib7z_guid.h \
+ lib7z_create.h \
+ lib7z_extract.h \
+ lib7z_list.h
SOURCES += packagemanagercore.cpp \
packagemanagercore_p.cpp \
@@ -198,7 +203,8 @@ SOURCES += packagemanagercore.cpp \
proxycredentialsdialog.cpp \
serverauthenticationdialog.cpp \
keepaliveobject.cpp \
- systeminfo.cpp
+ systeminfo.cpp \
+ packagesource.cpp
FORMS += proxycredentialsdialog.ui \
serverauthenticationdialog.ui
diff --git a/src/libs/installer/installercalculator.cpp b/src/libs/installer/installercalculator.cpp
index 65713dc74..064dbafa5 100644
--- a/src/libs/installer/installercalculator.cpp
+++ b/src/libs/installer/installercalculator.cpp
@@ -71,7 +71,7 @@ QString InstallerCalculator::installReason(Component *component) const
"Components added as automatic dependencies:");
case Dependent:
return QCoreApplication::translate("InstallerCalculator", "Components added as "
- "dependency for '%1':").arg(installReasonReferencedComponent(component));
+ "dependency for \"%1\":").arg(installReasonReferencedComponent(component));
case Resolved:
return QCoreApplication::translate("InstallerCalculator",
"Components that have resolved dependencies:");
@@ -92,9 +92,9 @@ QString InstallerCalculator::componentsToInstallError() const
return m_componentsToInstallError;
}
-void InstallerCalculator::realAppendToInstallComponents(Component *component)
+void InstallerCalculator::realAppendToInstallComponents(Component *component, const QString &version)
{
- if (!component->isInstalled() || component->updateRequested()) {
+ if (!component->isInstalled(version) || component->updateRequested()) {
m_orderedComponentsToInstall.append(component);
m_toInstallComponentIds.insert(component->name());
}
@@ -102,8 +102,8 @@ void InstallerCalculator::realAppendToInstallComponents(Component *component)
QString InstallerCalculator::recursionError(Component *component)
{
- return QCoreApplication::translate("InstallerCalculator", "Recursion detected, component '%1' "
- "already added with reason: '%2'").arg(component->name(), installReason(component));
+ return QCoreApplication::translate("InstallerCalculator", "Recursion detected, component \"%1\" "
+ "already added with reason: \"%2\"").arg(component->name(), installReason(component));
}
bool InstallerCalculator::appendComponentsToInstall(const QList<Component *> &components)
@@ -115,7 +115,7 @@ bool InstallerCalculator::appendComponentsToInstall(const QList<Component *> &co
foreach (Component *component, components){
if (m_toInstallComponentIds.contains(component->name())) {
const QString errorMessage = recursionError(component);
- qWarning() << errorMessage;
+ qWarning().noquote() << errorMessage;
m_componentsToInstallError.append(errorMessage);
Q_ASSERT_X(!m_toInstallComponentIds.contains(component->name()), Q_FUNC_INFO,
qPrintable(errorMessage));
@@ -154,10 +154,10 @@ bool InstallerCalculator::appendComponentsToInstall(const QList<Component *> &co
return true;
}
-bool InstallerCalculator::appendComponentToInstall(Component *component)
+bool InstallerCalculator::appendComponentToInstall(Component *component, const QString &version)
{
QSet<QString> allDependencies = component->dependencies().toSet();
-
+ QString requiredDependencyVersion = version;
foreach (const QString &dependencyComponentName, allDependencies) {
// PackageManagerCore::componentByName returns 0 if dependencyComponentName contains a
// version which is not available
@@ -165,36 +165,56 @@ bool InstallerCalculator::appendComponentToInstall(Component *component)
PackageManagerCore::componentByName(dependencyComponentName, m_allComponents);
if (!dependencyComponent) {
const QString errorMessage = QCoreApplication::translate("InstallerCalculator",
- "Cannot find missing dependency '%1' for '%2'.").arg(dependencyComponentName,
+ "Cannot find missing dependency \"%1\" for \"%2\".").arg(dependencyComponentName,
component->name());
- qWarning() << errorMessage;
+ qWarning().noquote() << errorMessage;
m_componentsToInstallError.append(errorMessage);
return false;
}
+ //Check if component requires higher version than what might be already installed
+ bool isUpdateRequired = false;
+ if (dependencyComponentName.contains(QChar::fromLatin1('-')) &&
+ !dependencyComponent->value(scInstalledVersion).isEmpty()) {
+ QRegExp compEx(QLatin1String("([<=>]+)(.*)"));
+ const QString installedVersion = compEx.exactMatch(dependencyComponent->value(scInstalledVersion)) ?
+ compEx.cap(2) : dependencyComponent->value(scInstalledVersion);
+
+ QString requiredVersion = dependencyComponentName.section(QLatin1Char('-'), 1);
+ requiredVersion = compEx.exactMatch(requiredVersion) ? compEx.cap(2) : requiredVersion;
+
+ if (KDUpdater::compareVersion(requiredVersion, installedVersion) >= 1 ) {
+ isUpdateRequired = true;
+ requiredDependencyVersion = requiredVersion;
+ }
+ }
+ //Check dependencies only if
+ //- Dependency is not installed or update requested, nor newer version of dependency component required
+ //- And dependency component is not already added for install
+ //- And component is not already added for install, then dependencies are already resolved
+ if (((!dependencyComponent->isInstalled() || dependencyComponent->updateRequested())
+ || isUpdateRequired) && (!m_toInstallComponentIds.contains(dependencyComponent->name())
+ && !m_toInstallComponentIds.contains(component->name()))) {
+ if (m_visitedComponents.value(component).contains(dependencyComponent)) {
+ const QString errorMessage = recursionError(component);
+ qWarning().noquote() << errorMessage;
+ m_componentsToInstallError = errorMessage;
+ Q_ASSERT_X(!m_visitedComponents.value(component).contains(dependencyComponent),
+ Q_FUNC_INFO, qPrintable(errorMessage));
+ return false;
+ }
+ m_visitedComponents[component].insert(dependencyComponent);
+
+ // add needed dependency components to the next run
+ insertInstallReason(dependencyComponent, InstallerCalculator::Dependent,
+ component->name());
- if ((!dependencyComponent->isInstalled() || dependencyComponent->updateRequested())
- && !m_toInstallComponentIds.contains(dependencyComponent->name())) {
- if (m_visitedComponents.value(component).contains(dependencyComponent)) {
- const QString errorMessage = recursionError(component);
- qWarning() << errorMessage;
- m_componentsToInstallError = errorMessage;
- Q_ASSERT_X(!m_visitedComponents.value(component).contains(dependencyComponent),
- Q_FUNC_INFO, qPrintable(errorMessage));
- return false;
- }
- m_visitedComponents[component].insert(dependencyComponent);
-
- // add needed dependency components to the next run
- insertInstallReason(dependencyComponent, InstallerCalculator::Dependent,
- component->name());
-
- if (!appendComponentToInstall(dependencyComponent))
- return false;
+ if (!appendComponentToInstall(dependencyComponent, requiredDependencyVersion))
+ return false;
}
}
if (!m_toInstallComponentIds.contains(component->name())) {
- realAppendToInstallComponents(component);
+ realAppendToInstallComponents(component, requiredDependencyVersion);
insertInstallReason(component, InstallerCalculator::Resolved);
}
return true;
diff --git a/src/libs/installer/installercalculator.h b/src/libs/installer/installercalculator.h
index 08dd47f78..b2d05bdbe 100644
--- a/src/libs/installer/installercalculator.h
+++ b/src/libs/installer/installercalculator.h
@@ -64,8 +64,8 @@ private:
void insertInstallReason(Component *component,
InstallReasonType installReasonType,
const QString &referencedComponentName = QString());
- void realAppendToInstallComponents(Component *component);
- bool appendComponentToInstall(Component *components);
+ void realAppendToInstallComponents(Component *component, const QString &version = QString());
+ bool appendComponentToInstall(Component *components, const QString &version = QString());
QString recursionError(Component *component);
QList<Component*> m_allComponents;
diff --git a/src/libs/installer/installiconsoperation.cpp b/src/libs/installer/installiconsoperation.cpp
index fe6127941..ecd21be86 100644
--- a/src/libs/installer/installiconsoperation.cpp
+++ b/src/libs/installer/installiconsoperation.cpp
@@ -86,7 +86,8 @@ QString InstallIconsOperation::targetDirectory()
return directory;
}
-InstallIconsOperation::InstallIconsOperation()
+InstallIconsOperation::InstallIconsOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("InstallIcons"));
}
@@ -103,20 +104,16 @@ void InstallIconsOperation::backup()
bool InstallIconsOperation::performOperation()
{
- const QStringList args = arguments();
- if ((args.count() != 1) && (args.count() != 2)) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("1 or 2"), tr(" (Sourcepath, [Vendorprefix])")));
+ if (!checkArgumentCount(1, 2, tr("<source path> [vendor prefix]")))
return false;
- }
+ const QStringList args = arguments();
const QString source = args.at(0);
- const QString vendor = args.value(1);
+ const QString vendor = args.value(1); // value() used since it's optional
if (source.isEmpty()) {
setError(InvalidArguments);
- setErrorString(tr("Invalid Argument: source folder must not be empty."));
+ setErrorString(tr("Invalid Argument: source directory must not be empty."));
return false;
}
@@ -127,7 +124,7 @@ bool InstallIconsOperation::performOperation()
QStringList backupFiles;
QStringList createdDirectories;
- PackageManagerCore *const core = value(QLatin1String("installer")).value<PackageManagerCore*>();
+ PackageManagerCore *const core = packageManager();
// iterate a second time to get the actual work done
QDirIterator it(sourceDir.path(), QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot,
@@ -165,7 +162,8 @@ bool InstallIconsOperation::performOperation()
QFile bf(target);
if (!bf.copy(backup)) {
setError(UserDefinedError);
- setErrorString(tr("Could not backup file %1: %2").arg(target, bf.errorString()));
+ setErrorString(tr("Cannot backup file \"%1\": %2").arg(
+ QDir::toNativeSeparators(target), bf.errorString()));
undoOperation();
return false;
}
@@ -178,7 +176,8 @@ bool InstallIconsOperation::performOperation()
QString errStr;
if (!deleteFileNowOrLater(target, &errStr)) {
setError(UserDefinedError);
- setErrorString(tr("Failed to overwrite %1: %2").arg(target, errStr));
+ setErrorString(tr("Failed to overwrite \"%1\": %2").arg(
+ QDir::toNativeSeparators(target), errStr));
undoOperation();
return false;
}
@@ -189,7 +188,8 @@ bool InstallIconsOperation::performOperation()
QFile cf(source);
if (!cf.copy(target)) {
setError(UserDefinedError);
- setErrorString(tr("Failed to copy file %1: %2").arg(target, cf.errorString()));
+ setErrorString(tr("Failed to copy file \"%1\": %2").arg(
+ QDir::toNativeSeparators(target), cf.errorString()));
undoOperation();
return false;
}
@@ -199,7 +199,8 @@ bool InstallIconsOperation::performOperation()
setValue(QLatin1String("files"), files);
} else if (fi.isDir() && !QDir(target).exists()) {
if (!QDir().mkpath(target)) {
- setErrorString(tr("Could not create folder at %1: %2").arg(target, qt_error_string()));
+ setErrorString(tr("Cannot create directory \"%1\": %2").arg(
+ QDir::toNativeSeparators(target), qt_error_string()));
undoOperation();
return false;
}
@@ -231,7 +232,7 @@ bool InstallIconsOperation::undoOperation()
QFile installedTarget(target);
if (installedTarget.exists() && !(installedTarget.copy(source) && installedTarget.remove())) {
- warningMessages << QString::fromLatin1("Could not move file from '%1' to '%2', error: %3)").arg(
+ warningMessages << QString::fromLatin1("Cannot move file from \"%1\" to \"%2\": %3)").arg(
target, source, installedTarget.errorString());
}
}
@@ -247,13 +248,13 @@ bool InstallIconsOperation::undoOperation()
deleteFileNowOrLater(target);
// then copy the backup onto the target
if (!QFile::copy(backup, target)) {
- warningMessages << QString::fromLatin1("Could not restore the backup '%1' to '%2'").arg(
+ warningMessages << QString::fromLatin1("Cannot restore the backup \"%1\" to \"%2\".").arg(
backup, target);
}
// finally remove the backp
if (!deleteFileNowOrLater(backup))
- warningMessages << QString::fromLatin1("Could not remove the backup '%1'").arg(backup);
+ warningMessages << QString::fromLatin1("Cannot remove the backup \"%1\".").arg(backup);
}
@@ -263,14 +264,14 @@ bool InstallIconsOperation::undoOperation()
const QDir dir(*it);
removeSystemGeneratedFiles(dir.absolutePath());
if (dir.exists() && !QDir::root().rmdir(dir.path()))
- warningMessages << QString::fromLatin1("Could not remove directory '%1'").arg(dir.path());
+ warningMessages << QString::fromLatin1("Cannot remove directory \"%1\".").arg(dir.path());
}
if (!warningMessages.isEmpty()) {
- qWarning() << QString::fromLatin1("Undo of operation '%1' with arguments '%2' had some problems.").arg(
- name(), arguments().join(QLatin1String(", ")));
+ qWarning() << "Undo of operation" << name() << "with arguments"
+ << arguments().join(QLatin1String(", ")) << "had some problems.";
foreach (const QString &message, warningMessages) {
- qWarning() << message;
+ qWarning().noquote() << message;
}
}
@@ -281,8 +282,3 @@ bool InstallIconsOperation::testOperation()
{
return true;
}
-
-Operation *InstallIconsOperation::clone() const
-{
- return new InstallIconsOperation();
-}
diff --git a/src/libs/installer/installiconsoperation.h b/src/libs/installer/installiconsoperation.h
index d8170fef2..5f8dff514 100644
--- a/src/libs/installer/installiconsoperation.h
+++ b/src/libs/installer/installiconsoperation.h
@@ -39,14 +39,13 @@ class INSTALLER_EXPORT InstallIconsOperation : public QObject, public Operation
{
Q_OBJECT
public:
- InstallIconsOperation();
+ explicit InstallIconsOperation(PackageManagerCore *core);
~InstallIconsOperation();
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
Q_SIGNALS:
void outputTextChanged(const QString &progress);
diff --git a/src/libs/installer/keepaliveobject.cpp b/src/libs/installer/keepaliveobject.cpp
index 148987280..6f56d7823 100644
--- a/src/libs/installer/keepaliveobject.cpp
+++ b/src/libs/installer/keepaliveobject.cpp
@@ -28,8 +28,8 @@
#include "keepaliveobject.h"
#include "remoteclient.h"
-#include "localsocket.h"
+#include <QLocalSocket>
#include <QTimer>
namespace QInstaller {
@@ -43,7 +43,7 @@ KeepAliveObject::KeepAliveObject()
void KeepAliveObject::start()
{
m_timer = new QTimer(this);
- m_socket = new LocalSocket(this);
+ m_socket = new QLocalSocket(this);
connect(m_timer, &QTimer::timeout, [this]() {
if (m_socket->state() != QLocalSocket::UnconnectedState)
diff --git a/src/libs/installer/localsocket.h b/src/libs/installer/lib7z_create.h
index 146547258..ad308ffd1 100644
--- a/src/libs/installer/localsocket.h
+++ b/src/libs/installer/lib7z_create.h
@@ -1,7 +1,7 @@
-/**************************************************************************
+/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
@@ -24,45 +24,54 @@
**
** $QT_END_LICENSE$
**
-**************************************************************************/
+****************************************************************************/
-#ifndef LOCALSOCKET_H
-#define LOCALSOCKET_H
+#ifndef LIB7Z_CREATE_H
+#define LIB7Z_CREATE_H
-#include <QLocalSocket>
+#include "installer_global.h"
-#if defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK(5,5,0)
+#include <Common/MyCom.h>
+#include <7zip/UI/Common/Update.h>
-// This is a crude hack to work around QLocalSocket::waitForReadyRead returning instantly
-// if there are still bytes left in the buffer. This has been fixed in Qt 5.5.0 ...
-class LocalSocket : public QLocalSocket
+QT_BEGIN_NAMESPACE
+class QFileDevice;
+class QStringList;
+QT_END_NAMESPACE
+
+namespace Lib7z
{
-public:
- LocalSocket(QObject *parent = 0) : QLocalSocket(parent), inReadyRead(false)
- {
- }
+ enum struct QTmpFile {
+ No,
+ Yes
+ };
- qint64 bytesAvailable() const {
- if (inReadyRead)
- return 0;
- return QLocalSocket::bytesAvailable();
- }
+ enum struct Compression {
+ Non = 0,
+ Fastest = 1,
+ Fast = 3,
+ Normal = 5,
+ Maximum = 7,
+ Ultra = 9
+ };
- bool waitForReadyRead(int msecs = 30000) {
- inReadyRead = true;
- bool result = QLocalSocket::waitForReadyRead(msecs);
- inReadyRead = false;
- return result;
- }
+ class INSTALLER_EXPORT UpdateCallback : public IUpdateCallbackUI2, public CMyUnknownImp
+ {
+ Q_DISABLE_COPY(UpdateCallback)
-private:
- bool inReadyRead;
-};
+ public:
+ UpdateCallback() = default;
+ virtual ~UpdateCallback() {}
-#else
+ MY_UNKNOWN_IMP
+ INTERFACE_IUpdateCallbackUI2(;)
+ };
-typedef QLocalSocket LocalSocket;
+ void INSTALLER_EXPORT createArchive(QFileDevice *archive, const QStringList &sources,
+ Compression level = Compression::Normal, UpdateCallback *callback = 0);
+ void INSTALLER_EXPORT createArchive(const QString &archive, const QStringList &sources,
+ QTmpFile mode, Compression level = Compression::Normal, UpdateCallback *callback = 0);
-#endif
+} // namespace Lib7z
-#endif // LOCALSOCKET_H
+#endif // LIB7Z_CREATE_H
diff --git a/src/libs/installer/lib7z_extract.h b/src/libs/installer/lib7z_extract.h
new file mode 100644
index 000000000..f6182c727
--- /dev/null
+++ b/src/libs/installer/lib7z_extract.h
@@ -0,0 +1,85 @@
+/**************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+#ifndef LIB7Z_EXTRACT_H
+#define LIB7Z_EXTRACT_H
+
+#include "installer_global.h"
+
+#include <Common/MyCom.h>
+#include <7zip/Archive/IArchive.h>
+
+#include <QString>
+
+class CArc;
+
+QT_BEGIN_NAMESPACE
+class QFileDevice;
+QT_END_NAMESPACE
+
+namespace Lib7z
+{
+ class INSTALLER_EXPORT ExtractCallback : public IArchiveExtractCallback, public CMyUnknownImp
+ {
+ Q_DISABLE_COPY(ExtractCallback)
+
+ public:
+ ExtractCallback() = default;
+ virtual ~ExtractCallback() = default;
+
+ void setArchive(CArc *carc) { arc = carc; }
+ void setTarget(const QString &dir) { targetDir = dir; }
+
+ MY_UNKNOWN_IMP
+ INTERFACE_IArchiveExtractCallback(;)
+
+ protected:
+ virtual bool prepareForFile(const QString & /*filename*/) { return true; }
+ virtual void setCurrentFile(const QString &filename) { Q_UNUSED(filename) }
+ virtual HRESULT setCompleted(quint64 /*completed*/, quint64 /*total*/) { return S_OK; }
+
+ private:
+ CArc *arc = 0;
+
+ QString targetDir;
+ quint64 total = 0;
+ quint64 completed = 0;
+ quint32 currentIndex = 0;
+ };
+
+ void INSTALLER_EXPORT extractArchive(QFileDevice *archive, const QString &targetDirectory,
+ ExtractCallback *callback = 0);
+
+} // namespace Lib7z
+
+#endif // LIB7Z_EXTRACT_H
diff --git a/src/libs/installer/lib7z_facade.cpp b/src/libs/installer/lib7z_facade.cpp
index ebff609b4..f5561af2f 100644
--- a/src/libs/installer/lib7z_facade.cpp
+++ b/src/libs/installer/lib7z_facade.cpp
@@ -25,106 +25,199 @@
** $QT_END_LICENSE$
**
**************************************************************************/
+
#include "lib7z_facade.h"
#include "errors.h"
#include "fileio.h"
+#include "lib7z_create.h"
+#include "lib7z_extract.h"
+#include "lib7z_list.h"
+#include "lib7z_guid.h"
+
#ifndef Q_OS_WIN
# include "StdAfx.h"
#endif
-#include "Common/MyInitGuid.h"
+#include <7zCrc.h>
+
+#include <7zip/Archive/IArchive.h>
-#include "7zip/Archive/IArchive.h"
-#include "7zip/UI/Common/OpenArchive.h"
-#include "7zip/UI/Common/Update.h"
+#include <7zip/UI/Common/ArchiveCommandLine.h>
+#include <7zip/UI/Common/OpenArchive.h>
-#include "Windows/FileIO.h"
-#include "Windows/PropVariant.h"
-#include "Windows/PropVariantConversions.h"
+#include <Windows/FileDir.h>
+#include <Windows/FileIO.h>
+#include <Windows/PropVariant.h>
+#include <Windows/PropVariantConv.h>
+#include <QCoreApplication>
#include <QDir>
#include <QFileInfo>
#include <QIODevice>
-#include <QtCore/QMutexLocker>
#include <QPointer>
-#include <QTemporaryFile>
#include <QReadWriteLock>
+#include <QTemporaryFile>
-#ifdef _MSC_VER
-#pragma warning(disable:4297)
-#endif
+#include <mutex>
+#include <memory>
#ifdef Q_OS_WIN
+HINSTANCE g_hInstance = 0;
+
+# define S_IFMT 00170000
+# define S_IFLNK 0120000
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+# define FILE_ATTRIBUTE_UNIX_EXTENSION 0x8000 /* trick for Unix */
+# if !defined(Q_CC_MINGW)
+# include <time.h> // for localtime_s
+# endif
+#else
+extern "C" int global_use_utf16_conversion;
+
+#include <myWindows/config.h>
+#include <sys/stat.h>
+#endif
+
+namespace NArchive {
+ namespace N7z {
+ void registerArcDec7z();
+ }
+ namespace NXz {
+ void registerArcxz();
+ }
+ namespace NSplit {
+ void registerArcSplit();
+ }
+ namespace NLzma {
+ namespace NLzmaAr {
+ void registerArcLzma();
+ }
+ namespace NLzma86Ar {
+ void registerArcLzma86();
+ }
+ }
+}
+using namespace NWindows;
+
+void registerCodecBCJ();
+void registerCodecBCJ2();
+
+void registerCodecLZMA();
+void registerCodecLZMA2();
+
+void registerCodecCopy();
+void registerCodecDelta();
+void registerCodecBranch();
+void registerCodecByteSwap();
+
+namespace Lib7z {
+
-#include <time.h>
-#define FILE_ATTRIBUTE_UNIX_EXTENSION 0x8000 /* trick for Unix */
-#define S_IFMT 00170000
-#define S_IFLNK 0120000
-#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+// -- 7z init codecs, archives
-typedef BOOL (WINAPI *CREATEHARDLINK)(LPCSTR dst, LPCSTR str, LPSECURITY_ATTRIBUTES sa);
+std::once_flag gOnceFlag;
-bool CreateHardLinkWrapper(const QString &dest, const QString &file)
+void initSevenZ()
{
- static HMODULE module = 0;
- static CREATEHARDLINK proc = 0;
+ std::call_once(gOnceFlag, [] {
+ CrcGenerateTable();
- if (module == 0)
- module = LoadLibrary(L"kernel32.dll");
- if (module == 0)
- return false;
- if (proc == 0)
- proc = (CREATEHARDLINK) GetProcAddress(module, "CreateHardLinkA");
- if (proc == 0)
- return false;
- QString target = file;
- if (!QFileInfo(file).isAbsolute())
- {
- target = QFileInfo(dest).dir().absoluteFilePath(file);
- }
- const QString link = QDir::toNativeSeparators(dest);
- const QString existingFile = QDir::toNativeSeparators(target);
- return proc(link.toLocal8Bit(), existingFile.toLocal8Bit(), 0);
-}
+ registerCodecBCJ();
+ registerCodecBCJ2();
-#else
-#include <sys/stat.h>
+ registerCodecLZMA();
+ registerCodecLZMA2();
+
+ registerCodecCopy();
+ registerCodecDelta();
+ registerCodecBranch();
+ registerCodecByteSwap();
+
+ NArchive::N7z::registerArcDec7z();
+ NArchive::NXz::registerArcxz();
+ NArchive::NSplit::registerArcSplit();
+ NArchive::NLzma::NLzmaAr::registerArcLzma();
+ NArchive::NLzma::NLzma86Ar::registerArcLzma86();
+
+#ifndef Q_OS_WIN
+# ifdef ENV_HAVE_LOCALE
+ const QByteArray locale = qgetenv("LC_ALL").toUpper();
+ if (!locale.isEmpty() && (locale != "C") && (locale != "POSIX"))
+ global_use_utf16_conversion = 1;
+# elif defined(LOCALE_IS_UTF8)
+ global_use_utf16_conversion = 1;
+# else
+ global_use_utf16_conversion = 0;
+# endif
#endif
+ });
+}
-#include <memory>
-#include <cassert>
+// -- error handling
-using namespace Lib7z;
-using namespace NWindows;
+Q_GLOBAL_STATIC(QString, getLastErrorString)
+Q_GLOBAL_STATIC(QReadWriteLock, lastErrorReadWriteLock)
+QString lastError()
+{
+ QReadLocker locker(lastErrorReadWriteLock());
+ Q_UNUSED(locker)
+ return *getLastErrorString();
+}
-namespace Lib7z {
- Q_GLOBAL_STATIC(QReadWriteLock, lastErrorReadWriteLock)
- Q_GLOBAL_STATIC(QString, getLastErrorString)
+void setLastError(const QString &errorString)
+{
+ QWriteLocker locker(lastErrorReadWriteLock());
+ Q_UNUSED(locker)
+ *getLastErrorString() = errorString;
+}
- QString lastError()
- {
- QReadLocker locker(lastErrorReadWriteLock());
- Q_UNUSED(locker)
- return *getLastErrorString();
- }
+QString errorMessageFrom7zResult(const LONG &extractResult)
+{
+ if (!lastError().isEmpty())
+ return lastError();
- void setLastError(const QString &errorString)
- {
- QWriteLocker locker(lastErrorReadWriteLock());
- Q_UNUSED(locker)
- *getLastErrorString() = errorString;
+ QString errorMessage = QCoreApplication::translate("Lib7z", "internal code: %1");
+ switch (extractResult) {
+ case S_OK:
+ qFatal("S_OK value is not a valid error code.");
+ break;
+ case E_NOTIMPL:
+ errorMessage = errorMessage.arg(QLatin1String("E_NOTIMPL"));
+ break;
+ case E_NOINTERFACE:
+ errorMessage = errorMessage.arg(QLatin1String("E_NOINTERFACE"));
+ break;
+ case E_ABORT:
+ errorMessage = errorMessage.arg(QLatin1String("E_ABORT"));
+ break;
+ case E_FAIL:
+ errorMessage = errorMessage.arg(QLatin1String("E_FAIL"));
+ break;
+ case STG_E_INVALIDFUNCTION:
+ errorMessage = errorMessage.arg(QLatin1String("STG_E_INVALIDFUNCTION"));
+ break;
+ case E_OUTOFMEMORY:
+ errorMessage = QCoreApplication::translate("Lib7z", "not enough memory");
+ break;
+ case E_INVALIDARG:
+ errorMessage = errorMessage.arg(QLatin1String("E_INVALIDARG"));
+ break;
+ default:
+ errorMessage = QCoreApplication::translate("Lib7z", "Error: %1").arg(extractResult);
+ break;
}
+ return errorMessage;
}
-namespace {
-/**
-* RAII class to create a directory (tryCreate()) and delete it on destruction unless released.
+/*!
+ RAII class to create a directory (tryCreate()) and delete it on destruction unless released.
*/
-struct DirectoryGuard {
+struct DirectoryGuard
+{
explicit DirectoryGuard(const QString &path)
: m_path(path)
, m_created(false)
@@ -139,14 +232,15 @@ struct DirectoryGuard {
return;
QDir dir(m_path);
if (!dir.rmdir(m_path))
- qWarning() << "Could not delete directory " << m_path;
+ qWarning() << "Cannot delete directory " << m_path;
}
- /**
- * Tries to create the directorie structure.
- * Returns a list of every directory created.
+ /*!
+ Tries to create the directory structure.
+ Returns a list of every directory created.
*/
- QStringList tryCreate() {
+ QStringList tryCreate()
+ {
if (m_path.isEmpty())
return QStringList();
@@ -155,13 +249,12 @@ struct DirectoryGuard {
return QStringList();
if (fi.exists() && !fi.isDir()) {
throw SevenZipException(QCoreApplication::translate("DirectoryGuard",
- "Path exists but is not a folder: %1").arg(m_path));
+ "Path \"%1\" exists but is not a directory.").arg(QDir::toNativeSeparators(m_path)));
}
QStringList created;
QDir toCreate(m_path);
- while (!toCreate.exists())
- {
+ while (!toCreate.exists()) {
QString p = toCreate.absolutePath();
created.push_front(p);
p = p.section(QLatin1Char('/'), 0, -2);
@@ -172,12 +265,13 @@ struct DirectoryGuard {
m_created = dir.mkpath(m_path);
if (!m_created) {
throw SevenZipException(QCoreApplication::translate("DirectoryGuard",
- "Could not create folder: %1").arg(m_path));
+ "Cannot create directory \"%1\".").arg(QDir::toNativeSeparators(m_path)));
}
return created;
}
- void release() {
+ void release()
+ {
m_released = true;
}
@@ -185,7 +279,6 @@ struct DirectoryGuard {
bool m_created;
bool m_released;
};
-}
static UString QString2UString(const QString &str)
{
@@ -197,32 +290,12 @@ static QString UString2QString(const UString& str)
return QString::fromStdWString(static_cast<const wchar_t*>(str));
}
-static QString generateTempFileName()
-{
- QTemporaryFile tmp;
- if (!tmp.open()) {
- throw SevenZipException(QCoreApplication::translate("QInstaller",
- "Could not create temporary file"));
- }
- return QDir::toNativeSeparators(tmp.fileName());
-}
-
-/*
-static QStringList UStringVector2QStringList(const UStringVector& vec)
-{
-QStringList res;
-for (int i = 0; i < vec.Size(); ++i)
-res += UString2QString(vec[i]);
-return res;
-}
-*/
-
-static NCOM::CPropVariant readProperty(IInArchive* archive, int index, int propId)
+static NCOM::CPropVariant readProperty(IInArchive *archive, int index, int propId)
{
NCOM::CPropVariant prop;
if (archive->GetProperty(index, propId, &prop) != S_OK) {
- throw SevenZipException(QCoreApplication::translate("QInstaller",
- "Could not retrieve property %1 for item %2").arg(QString::number(propId),
+ throw SevenZipException(QCoreApplication::translate("Lib7z",
+ "Cannot retrieve property %1 for item %2.").arg(QString::number(propId),
QString::number(index)));
}
return prop;
@@ -233,193 +306,134 @@ static bool IsFileTimeZero(const FILETIME *lpFileTime)
return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0);
}
-static bool IsDST(const QDateTime& datetime = QDateTime())
-{
- const time_t seconds = static_cast< time_t >(datetime.isValid() ? datetime.toTime_t()
- : QDateTime::currentDateTime().toTime_t());
-#if defined(Q_OS_WIN) && !defined(Q_CC_MINGW)
- struct tm t;
- localtime_s(&t, &seconds);
-#else
- const struct tm &t = *localtime(&seconds);
-#endif
- return t.tm_isdst;
-}
-
-static bool getFileTimeFromProperty(IInArchive* archive, int index, int propId, FILETIME *fileTime)
+static bool getFileTimeFromProperty(IInArchive* archive, int index, int propId, FILETIME *ft)
{
const NCOM::CPropVariant prop = readProperty(archive, index, propId);
if (prop.vt != VT_FILETIME) {
- throw SevenZipException(QCoreApplication::translate("QInstaller",
- "Property %1 for item %2 not of type VT_FILETIME but %3").arg(QString::number(propId),
+ throw SevenZipException(QCoreApplication::translate("Lib7z",
+ "Property %1 for item %2 not of type VT_FILETIME but %3.").arg(QString::number(propId),
QString::number(index), QString::number(prop.vt)));
}
- *fileTime = prop.filetime;
-
- if (IsFileTimeZero(fileTime))
- return false;
- return true;
+ *ft = prop.filetime;
+ return !IsFileTimeZero(ft);
}
-static
-QDateTime getDateTimeProperty(IInArchive* archive, int index, int propId, const QDateTime& defaultValue)
+static bool getDateTimeProperty(IInArchive *arc, int index, int id, QDateTime *value)
{
- FILETIME fileTime;
- if (!getFileTimeFromProperty(archive, index, propId, &fileTime))
- return defaultValue;
+ FILETIME ft7z;
+ if (!getFileTimeFromProperty(arc, index, id, &ft7z))
+ return false;
- FILETIME localFileTime;
- if (!FileTimeToLocalFileTime(&fileTime, &localFileTime)) {
- throw SevenZipException(QCoreApplication::translate("QInstaller",
- "Could not convert file time to local time"));
- }
SYSTEMTIME st;
- if (!BOOLToBool(FileTimeToSystemTime(&localFileTime, &st))) {
- throw SevenZipException(QCoreApplication::translate("QInstaller",
- "Could not convert local file time to system time"));
+ if (!BOOLToBool(FileTimeToSystemTime(&ft7z, &st))) {
+ throw SevenZipException(QCoreApplication::translate("Lib7z",
+ "Cannot convert UTC file time to system time."));
}
- const QDate date(st.wYear, st.wMonth, st.wDay);
- const QTime time(st.wHour, st.wMinute, st.wSecond);
- QDateTime result(date, time);
-
- // fix daylight saving time
- const bool dst = IsDST();
- if (dst != IsDST(result))
- result = result.addSecs(dst ? -3600 : 3600);
-
- return result;
+ *value = QDateTime(QDate(st.wYear, st.wMonth, st.wDay), QTime(st.wHour, st.wMinute,
+ st.wSecond), Qt::UTC);
+ return value->isValid();
}
-static quint64 getUInt64Property(IInArchive* archive, int index, int propId, quint64 defaultValue=0)
+static quint64 getUInt64Property(IInArchive *archive, int index, int propId, quint64 defaultValue)
{
- const NCOM::CPropVariant prop = readProperty(archive, index, propId);
- if (prop.vt == VT_EMPTY)
- return defaultValue;
- return static_cast<quint64>(ConvertPropVariantToUInt64(prop));
+ UInt64 value;
+ if (ConvertPropVariantToUInt64(readProperty(archive, index, propId), value))
+ return value;
+ return defaultValue;
}
-static quint32 getUInt32Property(IInArchive* archive, int index, int propId, quint32 defaultValue=0)
+static quint32 getUInt32Property(IInArchive *archive, int index, int propId, quint32 defaultValue)
{
const NCOM::CPropVariant prop = readProperty(archive, index, propId);
if (prop.vt == VT_EMPTY)
return defaultValue;
- return static_cast< quint32 >(prop.ulVal);
+ return static_cast<quint32>(prop.ulVal);
}
-static QFile::Permissions getPermissions(IInArchive* archive, int index, bool* hasPermissions = 0)
+static QFile::Permissions getPermissions(IInArchive *archive, int index, bool *hasPermissions)
{
quint32 attributes = getUInt32Property(archive, index, kpidAttrib, 0);
QFile::Permissions permissions = 0;
if (attributes & FILE_ATTRIBUTE_UNIX_EXTENSION) {
if (hasPermissions != 0)
*hasPermissions = true;
- // filter the unix permissions
+ // filter the Unix permissions
attributes = (attributes >> 16) & 0777;
- permissions |= static_cast< QFile::Permissions >((attributes & 0700) << 2); // owner rights
- permissions |= static_cast< QFile::Permissions >((attributes & 0070) << 1); // group
- permissions |= static_cast< QFile::Permissions >((attributes & 0007) << 0); // and world rights
+ permissions |= static_cast<QFile::Permissions>((attributes & 0700) << 2); // owner rights
+ permissions |= static_cast<QFile::Permissions>((attributes & 0070) << 1); // group
+ permissions |= static_cast<QFile::Permissions>((attributes & 0007) << 0); // and world rights
} else if (hasPermissions != 0) {
*hasPermissions = false;
}
return permissions;
}
-namespace Lib7z {
+#define LIB7Z_ASSERTS(X, MODE) \
+ Q_ASSERT(X); \
+ Q_ASSERT(X->isOpen()); \
+ Q_ASSERT(X->is ## MODE()); \
+ Q_ASSERT(!X->isSequential());
+
class QIODeviceSequentialOutStream : public ISequentialOutStream, public CMyUnknownImp
{
-public:
- enum Behavior {
- KeepDeviceUntouched,
- CloseAndDeleteDevice
- };
+ Q_DISABLE_COPY(QIODeviceSequentialOutStream)
+public:
MY_UNKNOWN_IMP
- explicit QIODeviceSequentialOutStream(QIODevice* device, Behavior behavior);
- ~QIODeviceSequentialOutStream();
- QString errorString() const;
- /* reimp */ STDMETHOD(Write)(const void* data, UInt32 size, UInt32* processedSize);
-
-private:
- Behavior m_behavior;
- QString m_errorString;
- QPointer<QIODevice> m_device;
-};
-
-QIODeviceSequentialOutStream::QIODeviceSequentialOutStream(QIODevice* device, Behavior behavior)
- : ISequentialOutStream()
- , CMyUnknownImp()
- , m_behavior(behavior)
- , m_device(device)
-{
- Q_ASSERT(m_device);
-
- if (!device->isOpen() && !m_device->open(QIODevice::WriteOnly))
- m_errorString = m_device->errorString();
-}
-
-QIODeviceSequentialOutStream::~QIODeviceSequentialOutStream()
-{
- if (m_behavior == CloseAndDeleteDevice) {
- m_device->close();
- delete m_device;
- m_device = 0;
+ explicit QIODeviceSequentialOutStream(std::unique_ptr<QIODevice> device)
+ : ISequentialOutStream()
+ , m_device(std::move(device))
+ {
+ LIB7Z_ASSERTS(m_device, Writable)
}
-}
-QString QIODeviceSequentialOutStream::errorString() const
-{
- return m_errorString;
-}
+ QString errorString() const {
+ return m_errorString;
+ }
-HRESULT QIODeviceSequentialOutStream::Write(const void* data, UInt32 size, UInt32* processedSize)
-{
- if (!m_device) {
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize)
+ {
if (processedSize)
*processedSize = 0;
- m_errorString = QCoreApplication::translate("QIODeviceSequentialOutStream",
- "No device set for output stream");
- return E_FAIL;
- }
- if (!m_device->isOpen()) {
- const bool opened = m_device->open(QIODevice::WriteOnly);
- if (!opened) {
- if (processedSize)
- *processedSize = 0;
+
+ const qint64 written = m_device->write(reinterpret_cast<const char*>(data), size);
+ if (written == -1) {
m_errorString = m_device->errorString();
return E_FAIL;
}
- }
- const qint64 written = m_device->write(reinterpret_cast<const char*>(data), size);
- if (written == -1) {
if (processedSize)
- *processedSize = 0;
- m_errorString = m_device->errorString();
- return E_FAIL;
+ *processedSize = written;
+ m_errorString.clear();
+ return S_OK;
}
- if (processedSize)
- *processedSize = written;
- m_errorString = QString();
- return S_OK;
-}
+private:
+ QString m_errorString;
+ std::unique_ptr<QIODevice> m_device;
+};
class QIODeviceInStream : public IInStream, public CMyUnknownImp
{
+ Q_DISABLE_COPY(QIODeviceInStream)
+
public:
MY_UNKNOWN_IMP
- explicit QIODeviceInStream(QIODevice* device) : IInStream(), CMyUnknownImp(), m_device(device)
+ explicit QIODeviceInStream(QIODevice *device)
+ : IInStream()
+ , CMyUnknownImp()
+ , m_device(device)
{
- assert(m_device);
- assert(!m_device->isSequential());
+ LIB7Z_ASSERTS(m_device, Readable)
}
- /* reimp */ STDMETHOD(Read)(void* data, UInt32 size, UInt32* processedSize)
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize)
{
- assert(m_device);
- assert(m_device->isReadable());
+ if (m_device.isNull())
+ return E_FAIL;
+
const qint64 actual = m_device->read(reinterpret_cast<char*>(data), size);
Q_ASSERT(actual != 0 || m_device->atEnd());
if (processedSize)
@@ -427,29 +441,28 @@ public:
return actual >= 0 ? S_OK : E_FAIL;
}
- /* reimp */ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64* newPosition)
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{
- assert(m_device);
- assert(!m_device->isSequential());
- assert(m_device->isReadable());
+ if (m_device.isNull())
+ return E_FAIL;
if (seekOrigin > STREAM_SEEK_END)
return STG_E_INVALIDFUNCTION;
UInt64 np = 0;
- switch(seekOrigin) {
- case STREAM_SEEK_SET:
- np = offset;
- break;
- case STREAM_SEEK_CUR:
- np = m_device->pos() + offset;
- break;
- case STREAM_SEEK_END:
- np = m_device->size() + offset;
- break;
- default:
- return STG_E_INVALIDFUNCTION;
+ switch (seekOrigin) {
+ case STREAM_SEEK_SET:
+ np = offset;
+ break;
+ case STREAM_SEEK_CUR:
+ np = m_device->pos() + offset;
+ break;
+ case STREAM_SEEK_END:
+ np = m_device->size() + offset;
+ break;
+ default:
+ return STG_E_INVALIDFUNCTION;
}
- np = qBound(static_cast<UInt64>(0), np, static_cast<UInt64>(m_device->size() - 1));
+ np = qBound(static_cast<UInt64>(0), np, static_cast<UInt64>(m_device->size()));
const bool ok = m_device->seek(np);
if (newPosition)
*newPosition = np;
@@ -459,1129 +472,652 @@ public:
private:
QPointer<QIODevice> m_device;
};
-}
-
-File::File()
- : permissions(0)
- , uncompressedSize(0)
- , compressedSize(0)
- , isDirectory(false)
-{
-}
-
-QVector<File> File::subtreeInPreorder() const
-{
- QVector<File> res;
- res += *this;
- Q_FOREACH (const File& child, children)
- res += child.subtreeInPreorder();
- return res;
-}
-
-bool File::operator<(const File& other) const
-{
- if (path != other.path)
- return path < other.path;
- if (mtime != other.mtime)
- return mtime < other.mtime;
- if (uncompressedSize != other.uncompressedSize)
- return uncompressedSize < other.uncompressedSize;
- if (compressedSize != other.compressedSize)
- return compressedSize < other.compressedSize;
- if (isDirectory != other.isDirectory)
- return !isDirectory;
- if (permissions != other.permissions)
- return permissions < other.permissions;
- return false;
-}
-
-bool File::operator==(const File& other) const
-{
- return mtime == other.mtime
- && path == other.path
- && uncompressedSize == other.uncompressedSize
- && compressedSize == other.compressedSize
- && isDirectory == other.isDirectory
- && children == other.children
- && (permissions == other.permissions
- || permissions == static_cast< QFile::Permissions >(-1)
- || other.permissions == static_cast< QFile::Permissions >(-1));
-}
-
-QByteArray Lib7z::formatKeyValuePairs(const QVariantList& l)
-{
- assert(l.size() % 2 == 0);
- QByteArray res;
- for (QVariantList::ConstIterator it = l.constBegin(); it != l.constEnd(); ++it) {
- if (!res.isEmpty())
- res += ", ";
- res += qPrintable(it->toString()) + QByteArray(" = ");
- ++it;
- res += qPrintable(it->toString());
- }
- return res;
-}
-
-class Job::Private
-{
-public:
- Private()
- : error(Lib7z::NoError)
- {}
-
- int error;
- QString errorString;
-};
-
-Job::Job(QObject* parent)
- : QObject(parent)
- , QRunnable()
- , d(new Private)
-{
-}
-
-Job::~Job()
-{
- delete d;
-}
-
-void Job::emitResult()
-{
- emit finished(this);
-}
-
-void Job::setError(int code)
-{
- d->error = code;
-}
-void Job::setErrorString(const QString &str)
+bool operator==(const File &lhs, const File &rhs)
{
- d->errorString = str;
+ return lhs.path == rhs.path
+ && lhs.utcTime == rhs.utcTime
+ && lhs.isDirectory == rhs.isDirectory
+ && lhs.compressedSize == rhs.compressedSize
+ && lhs.uncompressedSize == rhs.uncompressedSize
+ && (lhs.permissions == rhs.permissions
+ || lhs.permissions == static_cast<QFile::Permissions>(-1)
+ || rhs.permissions == static_cast<QFile::Permissions>(-1));
}
-void Job::emitProgress(qint64 completed, qint64 total)
+QVector<File> listArchive(QFileDevice *archive)
{
- emit progress(completed, total);
-}
-
-int Job::error() const
-{
- return d->error;
-}
+ LIB7Z_ASSERTS(archive, Readable)
-bool Job::hasError() const
-{
- return d->error != NoError;
-}
-
-void Job::run()
-{
- doStart();
-}
-
-QString Job::errorString() const
-{
- return d->errorString;
-}
+ const qint64 initialPos = archive->pos();
+ try {
+ CCodecs codecs;
+ if (codecs.Load() != S_OK)
+ throw SevenZipException(QCoreApplication::translate("Lib7z", "Cannot load codecs."));
-void Job::start()
-{
- QMetaObject::invokeMethod(this, "doStart", Qt::QueuedConnection);
-}
+ COpenOptions op;
+ op.codecs = &codecs;
-class ListArchiveJob::Private
-{
-public:
- QPointer<QFileDevice> archive;
- QVector<File> files;
-};
+ CObjectVector<COpenType> types;
+ op.types = &types; // Empty, because we use a stream.
-ListArchiveJob::ListArchiveJob(QObject* parent)
- : Job(parent)
- , d(new Private)
-{
-}
+ CIntVector excluded;
+ op.excludedFormats = &excluded;
-ListArchiveJob::~ListArchiveJob()
-{
- delete d;
-}
-
-QFileDevice* ListArchiveJob::archive() const
-{
- return d->archive;
-}
-
-void ListArchiveJob::setArchive(QFileDevice* device)
-{
- d->archive = device;
-}
+ const CMyComPtr<IInStream> stream = new QIODeviceInStream(archive);
+ op.stream = stream; // CMyComPtr is needed, otherwise it crashes in OpenStream().
-QVector<File> ListArchiveJob::index() const
-{
- return d->files;
-}
+ CObjectVector<CProperty> properties;
+ op.props = &properties;
-class OpenArchiveInfo
-{
-private:
- OpenArchiveInfo(QFileDevice* device)
- : codecs(new CCodecs)
- {
- if (codecs->Load() != S_OK) {
- throw SevenZipException(QCoreApplication::translate("OpenArchiveInfo",
- "Could not load codecs"));
- }
- if (!codecs->FindFormatForArchiveType(L"", formatIndices)) {
- throw SevenZipException(QCoreApplication::translate("OpenArchiveInfo",
- "Could not retrieve default format"));
- }
- stream = new QIODeviceInStream(device);
- if (archiveLink.Open2(codecs.data(), formatIndices, false, stream, UString(), 0) != S_OK) {
- throw SevenZipException(QCoreApplication::translate("OpenArchiveInfo",
- "Could not open archive"));
+ CArchiveLink archiveLink;
+ if (archiveLink.Open2(op, nullptr) != S_OK) {
+ throw SevenZipException(QCoreApplication::translate("Lib7z",
+ "Cannot open archive \"%1\".").arg(archive->fileName()));
}
- if (archiveLink.Arcs.Size() == 0)
- throw SevenZipException(QCoreApplication::translate("OpenArchiveInfo", "No CArc found"));
-
- m_cleaner = new OpenArchiveInfoCleaner();
- m_cleaner->moveToThread(device->thread());
- QObject::connect(device, SIGNAL(destroyed(QObject*)), m_cleaner, SLOT(deviceDestroyed(QObject*)));
- }
-
-public:
- ~OpenArchiveInfo()
- {
- m_cleaner->deleteLater();
- }
-
- static OpenArchiveInfo* value(QFileDevice* device)
- {
- QMutexLocker _(&m_mutex);
- if (!instances.contains(device))
- instances.insert(device, new OpenArchiveInfo(device));
- return instances.value(device);
- }
-
- static OpenArchiveInfo* take(QFileDevice *device)
- {
- QMutexLocker _(&m_mutex);
- if (instances.contains(device))
- return instances.take(device);
- return 0;
- }
-
- CArchiveLink archiveLink;
-
-private:
- CIntVector formatIndices;
- CMyComPtr<IInStream> stream;
- QScopedPointer<CCodecs> codecs;
- OpenArchiveInfoCleaner *m_cleaner;
-
- static QMutex m_mutex;
- static QHash< QIODevice*, OpenArchiveInfo* > instances;
-};
-
-QMutex OpenArchiveInfo::m_mutex;
-QHash< QIODevice*, OpenArchiveInfo* > OpenArchiveInfo::instances;
-
-void OpenArchiveInfoCleaner::deviceDestroyed(QObject* dev)
-{
- QFileDevice* device = static_cast<QFileDevice*>(dev);
- Q_ASSERT(device);
- delete OpenArchiveInfo::take(device);
-}
-
-QVector<File> Lib7z::listArchive(QFileDevice* archive)
-{
- assert(archive);
- try {
- const OpenArchiveInfo* const openArchive = OpenArchiveInfo::value(archive);
QVector<File> flat;
-
- for (int i = 0; i < openArchive->archiveLink.Arcs.Size(); ++i) {
- const CArc& arc = openArchive->archiveLink.Arcs[i];
- IInArchive* const arch = arc.Archive;
-
+ for (unsigned i = 0; i < archiveLink.Arcs.Size(); ++i) {
+ IInArchive *const arch = archiveLink.Arcs[i].Archive;
UInt32 numItems = 0;
if (arch->GetNumberOfItems(&numItems) != S_OK) {
throw SevenZipException(QCoreApplication::translate("Lib7z",
- "Could not retrieve number of items in archive"));
+ "Cannot retrieve number of items in archive."));
}
flat.reserve(flat.size() + numItems);
for (uint item = 0; item < numItems; ++item) {
UString s;
- if (arc.GetItemPath(item, s) != S_OK) {
+ if (archiveLink.Arcs[i].GetItemPath(item, s) != S_OK) {
throw SevenZipException(QCoreApplication::translate("Lib7z",
- "Could not retrieve path of archive item %1").arg(item));
+ "Cannot retrieve path of archive item \"%1\".").arg(item));
}
File f;
f.archiveIndex.setX(i);
f.archiveIndex.setY(item);
f.path = UString2QString(s).replace(QLatin1Char('\\'), QLatin1Char('/'));
- IsArchiveItemFolder(arch, item, f.isDirectory);
- f.permissions = getPermissions(arch, item);
- f.mtime = getDateTimeProperty(arch, item, kpidMTime, QDateTime());
+ Archive_IsItem_Folder(arch, item, f.isDirectory);
+ f.permissions = getPermissions(arch, item, 0);
+ getDateTimeProperty(arch, item, kpidMTime, &(f.utcTime));
f.uncompressedSize = getUInt64Property(arch, item, kpidSize, 0);
f.compressedSize = getUInt64Property(arch, item, kpidPackSize, 0);
- flat.push_back(f);
- qApp->processEvents();
+ flat.append(f);
}
}
return flat;
- } catch (const SevenZipException& e) {
- throw e;
} catch (const char *err) {
+ archive->seek(initialPos);
throw SevenZipException(err);
+ } catch (const SevenZipException &e) {
+ archive->seek(initialPos);
+ throw e; // re-throw unmodified
} catch (...) {
+ archive->seek(initialPos);
throw SevenZipException(QCoreApplication::translate("Lib7z",
- "Unknown exception caught (%1)").arg(QString::fromLatin1(Q_FUNC_INFO)));
+ "Unknown exception caught (%1).").arg(QString::fromLatin1(Q_FUNC_INFO)));
}
return QVector<File>(); // never reached
}
-void ListArchiveJob::doStart()
+
+// -- ExtractCallback
+
+STDMETHODIMP ExtractCallback::SetTotal(UInt64 t)
{
- try {
- if (!d->archive)
- throw SevenZipException(tr("Could not list archive: QIODevice already destroyed."));
- d->files = listArchive(d->archive);
- } catch (const SevenZipException& e) {
- setError(Failed);
- setErrorString(e.message());
- } catch (...) {
- setError(Failed);
- setErrorString(tr("Unknown exception caught (%1)").arg(tr("Failed")));
- }
- emitResult();
+ total = t;
+ return S_OK;
}
-class Lib7z::ExtractCallbackImpl : public IArchiveExtractCallback, public CMyUnknownImp
+STDMETHODIMP ExtractCallback::SetCompleted(const UInt64 *c)
{
-public:
- MY_UNKNOWN_IMP
- explicit ExtractCallbackImpl(ExtractCallback* qq)
- : q(qq)
- , currentIndex(0)
- , arc(0)
- , total(0)
- , completed(0)
- , device(0)
- {
- }
+ completed = *c;
+ if (total > 0)
+ return setCompleted(completed, total);
+ return S_OK;
+}
- void setTarget(QIODevice* dev)
- {
- device = dev;
- }
+// this method will be called by CFolderOutStream::OpenFile to stream via
+// CDecoder::CodeSpec extracted content to an output stream.
+STDMETHODIMP ExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 /*askExtractMode*/)
+{
+ *outStream = 0;
+ if (targetDir.isEmpty())
+ return E_FAIL;
- void setTarget(const QString &targetDirectory)
- {
- targetDir = targetDirectory;
- }
+ Q_ASSERT(arc);
+ currentIndex = index;
- // this method will be called by CFolderOutStream::OpenFile to stream via
- // CDecoder::CodeSpec extracted content to an output stream.
- /* reimp */ STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream** outStream, Int32 askExtractMode)
- {
- Q_UNUSED(askExtractMode)
- *outStream = 0;
- if (device != 0) {
- QIODeviceSequentialOutStream *qOutStream = new QIODeviceSequentialOutStream(device,
- QIODeviceSequentialOutStream::KeepDeviceUntouched);
- if (!qOutStream->errorString().isEmpty()) {
- Lib7z::setLastError(qOutStream->errorString());
- return E_FAIL;
- }
- CMyComPtr<ISequentialOutStream> stream = qOutStream;
- *outStream = stream.Detach();
- return S_OK;
- } else if (!targetDir.isEmpty()) {
- assert(arc);
-
- currentIndex = index;
-
- UString s;
- if (arc->GetItemPath(index, s) != S_OK) {
- Lib7z::setLastError(QCoreApplication::translate("ExtractCallbackImpl",
- "Could not retrieve path of archive item %1").arg(index));
- return E_FAIL;
- }
+ UString s;
+ if (arc->GetItemPath(index, s) != S_OK) {
+ setLastError(QCoreApplication::translate("ExtractCallbackImpl",
+ "Cannot retrieve path of archive item %1.").arg(index));
+ return E_FAIL;
+ }
- const QString path = UString2QString(s).replace(QLatin1Char('\\'), QLatin1Char('/'));
- const QFileInfo fi(QString::fromLatin1("%1/%2").arg(targetDir, path));
+ const QFileInfo fi(QString::fromLatin1("%1/%2").arg(targetDir, UString2QString(s)));
- DirectoryGuard guard(fi.absolutePath());
- const QStringList directories = guard.tryCreate();
+ DirectoryGuard guard(fi.absolutePath());
+ const QStringList directories = guard.tryCreate();
- bool isDir = false;
- IsArchiveItemFolder(arc->Archive, index, isDir);
- if (isDir)
- QDir(fi.absolutePath()).mkdir(fi.fileName());
+ bool isDir = false;
+ Archive_IsItem_Folder(arc->Archive, index, isDir);
+ if (isDir)
+ QDir(fi.absolutePath()).mkdir(fi.fileName());
- // this makes sure that all directories created get removed as well
- foreach (const QString &directory, directories)
- q->setCurrentFile(directory);
+ // this makes sure that all directories created get removed as well
+ foreach (const QString &directory, directories)
+ setCurrentFile(directory);
- if (!isDir && !q->prepareForFile(fi.absoluteFilePath()))
- return E_FAIL;
+ if (!isDir && !prepareForFile(fi.absoluteFilePath()))
+ return E_FAIL;
- q->setCurrentFile(fi.absoluteFilePath());
+ setCurrentFile(fi.absoluteFilePath());
- if (!isDir) {
+ if (!isDir) {
#ifndef Q_OS_WIN
- // do not follow symlinks, so we need to remove an existing one
- if (fi.isSymLink() && (!QFile::remove(fi.absoluteFilePath()))) {
- Lib7z::setLastError(QCoreApplication::translate("ExtractCallbackImpl",
- "Could not remove already existing symlink. %1").arg(fi.absoluteFilePath()));
- return E_FAIL;
- }
+ // do not follow symlinks, so we need to remove an existing one
+ if (fi.isSymLink() && (!QFile::remove(fi.absoluteFilePath()))) {
+ setLastError(QCoreApplication::translate("ExtractCallbackImpl",
+ "Cannot remove already existing symlink %1.").arg(fi.absoluteFilePath()));
+ return E_FAIL;
+ }
#endif
- QIODeviceSequentialOutStream *qOutStream = new QIODeviceSequentialOutStream(
- new QFile(fi.absoluteFilePath()), QIODeviceSequentialOutStream::CloseAndDeleteDevice);
- if (!qOutStream->errorString().isEmpty()) {
- Lib7z::setLastError(QCoreApplication::translate("ExtractCallbackImpl",
- "Could not open file: %1 (%2)").arg(fi.absoluteFilePath(),
- qOutStream->errorString()));
- return E_FAIL;
- }
- CMyComPtr<ISequentialOutStream> stream = qOutStream;
- *outStream = stream;
- stream.Detach();
- }
-
- guard.release();
- return S_OK;
+ std::unique_ptr<QFile> file(new QFile(fi.absoluteFilePath()));
+ if (!file->open(QIODevice::WriteOnly)) {
+ setLastError(QCoreApplication::translate("ExtractCallbackImpl",
+ "Cannot open file \"%1\" for writing: %2").arg(
+ QDir::toNativeSeparators(fi.absoluteFilePath()), file->errorString()));
+ return E_FAIL;
}
- return E_FAIL;
+ CMyComPtr<ISequentialOutStream> stream =
+ new QIODeviceSequentialOutStream(std::move(file));
+ *outStream = stream.Detach(); // CMyComPtr is needed, otherwise it crashes in Write().
}
- /* reimp */ STDMETHOD(PrepareOperation)(Int32 askExtractMode)
- {
- Q_UNUSED(askExtractMode)
+ guard.release();
+ return S_OK;
+}
+
+STDMETHODIMP ExtractCallback::PrepareOperation(Int32 /*askExtractMode*/)
+{
+ return S_OK;
+}
+
+STDMETHODIMP ExtractCallback::SetOperationResult(Int32 /*resultEOperationResult*/)
+{
+ if (targetDir.isEmpty())
return S_OK;
- }
- /* reimp */ STDMETHOD(SetOperationResult)(Int32 resultEOperationResult)
- {
- Q_UNUSED(resultEOperationResult)
+ UString s;
+ if (arc->GetItemPath(currentIndex, s) != S_OK) {
+ setLastError(QCoreApplication::translate("ExtractCallbackImpl",
+ "Cannot retrieve path of archive item %1.").arg(currentIndex));
+ return E_FAIL;
+ }
- if (!targetDir.isEmpty()) {
- bool hasPerm = false;
- const QFile::Permissions permissions = getPermissions(arc->Archive, currentIndex, &hasPerm);
+ const QString absFilePath = QFileInfo(QString::fromLatin1("%1/%2").arg(targetDir,
+ UString2QString(s).replace(QLatin1Char('\\'), QLatin1Char('/')))).absoluteFilePath();
- UString s;
- if (arc->GetItemPath(currentIndex, s) != S_OK) {
- Lib7z::setLastError(QCoreApplication::translate("ExtractCallbackImpl",
- "Could not retrieve path of archive item %1").arg(currentIndex));
- return E_FAIL;
- }
- const QString path = UString2QString(s).replace(QLatin1Char('\\'), QLatin1Char('/'));
- const QString absFilePath = QFileInfo(QString::fromLatin1("%1/%2").arg(targetDir, path))
- .absoluteFilePath();
-
- // do we have a symlink?
- const quint32 attributes = getUInt32Property(arc->Archive, currentIndex, kpidAttrib, 0);
- struct stat stat_info;
- stat_info.st_mode = attributes >> 16;
- if (S_ISLNK(stat_info.st_mode)) {
+ // do we have a symlink?
+ const quint32 attributes = getUInt32Property(arc->Archive, currentIndex, kpidAttrib, 0);
+ struct stat stat_info;
+ stat_info.st_mode = attributes >> 16;
+ if (S_ISLNK(stat_info.st_mode)) {
#ifdef Q_OS_WIN
- qFatal(QString::fromLatin1("Creating a link from archive is not implemented for windows. "
- "Link filename: %1").arg(absFilePath).toLatin1());
- // TODO
-// if (!CreateHardLinkWrapper(absFilePath, QLatin1String(symlinkTarget))) {
-// return S_FALSE;
-// }
+ qFatal(QString::fromLatin1("Creating a link from archive is not implemented for "
+ "windows. Link filename: %1").arg(absFilePath).toLatin1());
+ // TODO
+ //if (!NFile::NDir::MyCreateHardLink(CFSTR(QDir::toNativeSeparators(absFilePath).utf16()),
+ // CFSTR(QDir::toNativeSeparators(symlinkTarget).utf16())) {
+ // return S_FALSE;
+ //}
#else
- QFileInfo symlinkPlaceHolderFileInfo(absFilePath);
- if (symlinkPlaceHolderFileInfo.isSymLink()) {
- Lib7z::setLastError(QCoreApplication::translate("ExtractCallbackImpl",
- "Could not create symlink at '%1'. Another one is already existing.")
- .arg(absFilePath));
- return E_FAIL;
- }
- QFile symlinkPlaceHolderFile(absFilePath);
- if (!symlinkPlaceHolderFile.open(QIODevice::ReadOnly)) {
- Lib7z::setLastError(QCoreApplication::translate("ExtractCallbackImpl",
- "Could not read symlink target from file '%1'.").arg(absFilePath));
- return E_FAIL;
- }
+ QFileInfo symlinkPlaceHolderFileInfo(absFilePath);
+ if (symlinkPlaceHolderFileInfo.isSymLink()) {
+ setLastError(QCoreApplication::translate("ExtractCallbackImpl",
+ "Cannot create symlink at \"%1\". Another one is already existing.")
+ .arg(absFilePath));
+ return E_FAIL;
+ }
+ QFile symlinkPlaceHolderFile(absFilePath);
+ if (!symlinkPlaceHolderFile.open(QIODevice::ReadOnly)) {
+ setLastError(QCoreApplication::translate("ExtractCallbackImpl",
+ "Cannot read symlink target from file \"%1\".").arg(absFilePath));
+ return E_FAIL;
+ }
- const QByteArray symlinkTarget = symlinkPlaceHolderFile.readAll();
- symlinkPlaceHolderFile.close();
- symlinkPlaceHolderFile.remove();
- QFile targetFile(QString::fromLatin1(symlinkTarget));
- if (!targetFile.link(absFilePath)) {
- Lib7z::setLastError(QCoreApplication::translate("ExtractCallbackImpl",
- "Could not create symlink at %1. %2").arg(absFilePath,
- targetFile.errorString()));
- return E_FAIL;
- }
- return S_OK;
+ const QByteArray symlinkTarget = symlinkPlaceHolderFile.readAll();
+ symlinkPlaceHolderFile.close();
+ symlinkPlaceHolderFile.remove();
+ QFile targetFile(QString::fromLatin1(symlinkTarget));
+ if (!targetFile.link(absFilePath)) {
+ setLastError(QCoreApplication::translate("ExtractCallbackImpl",
+ "Cannot create symlink at %1: %2").arg(absFilePath,
+ targetFile.errorString()));
+ return E_FAIL;
+ }
+ return S_OK;
#endif
- }
+ }
- try {
- if (!absFilePath.isEmpty()) {
- // This might fail for archives without all properties, we can only be sure about
- // modification time, as it's always stored by default in 7z archives. Also note that
- // we restore modification time on Unix only, as access time and change time are
- // supposed to be set to the time of installation.
- FILETIME mTime;
- if (getFileTimeFromProperty(arc->Archive, currentIndex, kpidMTime, &mTime)) {
- NWindows::NFile::NIO::COutFile file;
- if (file.Open(QString2UString(absFilePath), 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL))
- file.SetTime(&mTime, &mTime, &mTime);
- }
+ try { // Note: This part might also fail while running a elevated installation.
+ if (!absFilePath.isEmpty()) {
+ // This might fail for archives without all properties, we can only be sure
+ // about modification time, as it's always stored by default in 7z archives.
+ // Also note that we restore modification time on Unix only, as access time
+ // and change time are supposed to be set to the time of installation.
+ FILETIME mTime;
+ const UString fileName = QString2UString(absFilePath);
+ if (getFileTimeFromProperty(arc->Archive, currentIndex, kpidMTime, &mTime)) {
+ NWindows::NFile::NIO::COutFile file;
+ if (file.Open(fileName, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL))
+ file.SetTime(&mTime, &mTime, &mTime);
+ }
#ifdef Q_OS_WIN
- FILETIME cTime, aTime;
- bool success = getFileTimeFromProperty(arc->Archive, currentIndex, kpidCTime, &cTime);
- if (success && getFileTimeFromProperty(arc->Archive, currentIndex, kpidATime, &aTime)) {
- NWindows::NFile::NIO::COutFile file;
- if (file.Open(QString2UString(absFilePath), 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL))
- file.SetTime(&cTime, &aTime, &mTime);
- }
+ FILETIME cTime, aTime;
+ if (getFileTimeFromProperty(arc->Archive, currentIndex, kpidCTime, &cTime)
+ && getFileTimeFromProperty(arc->Archive, currentIndex, kpidATime, &aTime)) {
+ NWindows::NFile::NIO::COutFile file;
+ if (file.Open(fileName, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL))
+ file.SetTime(&cTime, &aTime, &mTime);
+ }
#endif
- }
- } catch (...) {}
-
- if (hasPerm)
- QFile::setPermissions(absFilePath, permissions);
}
+ } catch (...) {}
- return S_OK;
- }
-
- /* reimp */ STDMETHOD(SetTotal)(UInt64 t)
- {
- total = t;
- return S_OK;
- }
-
- /* reimp */ STDMETHOD(SetCompleted)(const UInt64* c)
- {
- completed = *c;
- if (total > 0)
- return q->setCompleted(completed, total);
- return S_OK;
- }
-
- void setArchive(const CArc* archive)
- {
- arc = archive;
- }
+ bool hasPerm = false;
+ const QFile::Permissions permissions = getPermissions(arc->Archive, currentIndex, &hasPerm);
+ if (hasPerm)
+ QFile::setPermissions(absFilePath, permissions);
+ return S_OK;
+}
-private:
- ExtractCallback* const q;
- UInt32 currentIndex;
- const CArc* arc;
- UInt64 total;
- UInt64 completed;
- QPointer<QIODevice> device;
- QString targetDir;
-};
+/*!
+ \namespace Lib7z
+ \inmodule QtInstallerFramework
+ \brief The Lib7z namespace contains miscellaneous identifiers used throughout the Lib7z library.
+*/
+/*!
+ \fn virtual bool Lib7z::ExtractCallback::prepareForFile(const QString &filename)
-class Lib7z::ExtractCallbackPrivate
-{
-public:
- explicit ExtractCallbackPrivate(ExtractCallback* qq)
- {
- impl = new ExtractCallbackImpl(qq);
- }
+ Implement to prepare for file \a filename to be extracted, e.g. by renaming existing files.
+ Return \c true if the preparation was successful and extraction can be continued. If \c false
+ is returned, the extraction will be aborted. The default implementation returns \c true.
+*/
- CMyComPtr<ExtractCallbackImpl> impl;
-};
-ExtractCallback::ExtractCallback()
- : d(new ExtractCallbackPrivate(this))
-{
-}
+// -- UpdateCallback
-ExtractCallback::~ExtractCallback()
+HRESULT UpdateCallback::SetTotal(UInt64)
{
- delete d;
+ return S_OK;
}
-ExtractCallbackImpl* ExtractCallback::impl()
+HRESULT UpdateCallback::SetCompleted(const UInt64*)
{
- return d->impl;
+ return S_OK;
}
-const ExtractCallbackImpl* ExtractCallback::impl() const
+HRESULT UpdateCallback::SetRatioInfo(const UInt64*, const UInt64*)
{
- return d->impl;
+ return S_OK;
}
-void ExtractCallback::setTarget(QFileDevice* dev)
+HRESULT UpdateCallback::CheckBreak()
{
- d->impl->setTarget(dev);
+ return S_OK;
}
-void ExtractCallback::setTarget(const QString &dir)
+HRESULT UpdateCallback::Finilize()
{
- d->impl->setTarget(dir);
+ return S_OK;
}
-HRESULT ExtractCallback::setCompleted(quint64, quint64)
+HRESULT UpdateCallback::SetNumFiles(UInt64)
{
return S_OK;
}
-void ExtractCallback::setCurrentFile(const QString&)
+HRESULT UpdateCallback::GetStream(const wchar_t*, bool)
{
+ return S_OK;
}
-bool ExtractCallback::prepareForFile(const QString&)
+HRESULT UpdateCallback::OpenFileError(const wchar_t*, DWORD)
{
- return true;
+ return S_OK;
}
-class Lib7z::ExtractCallbackJobImpl : public ExtractCallback
-{
-public:
- explicit ExtractCallbackJobImpl(ExtractItemJob* j)
- : ExtractCallback()
- , job(j)
- {}
-
-private:
- /* reimp */ HRESULT setCompleted(quint64 c, quint64 t)
- {
- emit job->progress(c, t);
- return S_OK;
- }
-
- ExtractItemJob* const job;
-};
-
-class Lib7z::UpdateCallbackImpl : public IUpdateCallbackUI2, public CMyUnknownImp
-{
-public:
- MY_UNKNOWN_IMP
- UpdateCallbackImpl()
- {
- }
- virtual ~UpdateCallbackImpl()
- {
- }
- /**
- * \reimp
- */
- HRESULT SetTotal(UInt64)
- {
- return S_OK;
- }
- /**
- * \reimp
- */
- HRESULT SetCompleted(const UInt64*)
- {
- return S_OK;
- }
- HRESULT SetRatioInfo(const UInt64*, const UInt64*)
- {
- return S_OK;
- }
- HRESULT CheckBreak()
- {
- return S_OK;
- }
- HRESULT Finilize()
- {
- return S_OK;
- }
- HRESULT SetNumFiles(UInt64)
- {
- return S_OK;
- }
- HRESULT GetStream(const wchar_t*, bool)
- {
- return S_OK;
- }
- HRESULT OpenFileError(const wchar_t*, DWORD)
- {
- return S_OK;
- }
- HRESULT CryptoGetTextPassword2(Int32* passwordIsDefined, OLECHAR** password)
- {
- *password = 0;
- *passwordIsDefined = false;
- return S_OK;
- }
- HRESULT CryptoGetTextPassword(OLECHAR**)
- {
- return E_NOTIMPL;
- }
- HRESULT OpenResult(const wchar_t*, LONG)
- {
- return S_OK;
- }
- HRESULT StartScanning()
- {
- return S_OK;
- }
- HRESULT ScanProgress(UInt64, UInt64, const wchar_t*)
- {
- return S_OK;
- }
- HRESULT CanNotFindError(const wchar_t*, DWORD)
- {
- return S_OK;
- }
- HRESULT FinishScanning()
- {
- return S_OK;
- }
- HRESULT StartArchive(const wchar_t*, bool)
- {
- return S_OK;
- }
- HRESULT FinishArchive()
- {
- return S_OK;
- }
-
- /**
- * \reimp
- */
- HRESULT SetOperationResult(Int32)
- {
- // TODO!
- return S_OK;
- }
- void setSourcePaths(const QStringList &paths)
- {
- sourcePaths = paths;
- }
- void setTarget(QIODevice* archive)
- {
- target = archive;
- }
-
-private:
- QIODevice* target;
- QStringList sourcePaths;
-};
-
-class Lib7z::UpdateCallbackPrivate
-{
-public:
- UpdateCallbackPrivate()
- {
- m_impl = new UpdateCallbackImpl;
- }
-
- UpdateCallbackImpl* impl()
- {
- return m_impl;
- }
-
-private:
- CMyComPtr< UpdateCallbackImpl > m_impl;
-};
-
-UpdateCallback::UpdateCallback()
- : d(new UpdateCallbackPrivate)
+HRESULT UpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
+ *password = 0;
+ *passwordIsDefined = false;
+ return S_OK;
}
-UpdateCallback::~UpdateCallback()
+HRESULT UpdateCallback::CryptoGetTextPassword(BSTR *password)
{
- delete d;
+ *password = 0;
+ return E_NOTIMPL;
}
-UpdateCallbackImpl* UpdateCallback::impl()
+HRESULT UpdateCallback::OpenResult(const wchar_t*, HRESULT, const wchar_t*)
{
- return d->impl();
+ return S_OK;
}
-void UpdateCallback::setSourcePaths(const QStringList &paths)
+HRESULT UpdateCallback::StartScanning()
{
- d->impl()->setSourcePaths(paths);
+ return S_OK;
}
-void UpdateCallback::setTarget(QFileDevice* target)
+HRESULT UpdateCallback::ScanProgress(UInt64, UInt64, UInt64, const wchar_t*, bool)
{
- d->impl()->setTarget(target);
+ return S_OK;
}
-class ExtractItemJob::Private
-{
-public:
- Private(ExtractItemJob* qq)
- : q(qq)
- , target(0)
- , callback(new ExtractCallbackJobImpl(q))
- {
- }
-
- ExtractItemJob* q;
- File item;
- QPointer<QFileDevice> archive;
- QString targetDirectory;
- QFileDevice* target;
- ExtractCallback* callback;
-};
-
-ExtractItemJob::ExtractItemJob(QObject* parent)
- : Job(parent)
- , d(new Private(this))
+HRESULT UpdateCallback::CanNotFindError(const wchar_t*, DWORD)
{
+ return S_OK;
}
-ExtractItemJob::~ExtractItemJob()
+HRESULT UpdateCallback::FinishScanning()
{
- delete d;
+ return S_OK;
}
-File ExtractItemJob::item() const
+HRESULT UpdateCallback::StartArchive(const wchar_t*, bool)
{
- return d->item;
+ return S_OK;
}
-void ExtractItemJob::setItem(const File& item)
+HRESULT UpdateCallback::FinishArchive()
{
- d->item = item;
+ return S_OK;
}
-QFileDevice* ExtractItemJob::archive() const
+HRESULT UpdateCallback::SetOperationResult(Int32)
{
- return d->archive;
+ return S_OK;
}
-void ExtractItemJob::setArchive(QFileDevice* archive)
+/*!
+ Function to create an empty 7z container. Using a temporary file only is not working, since
+ 7z checks the output file for a valid signature, otherwise it rejects overwriting the file.
+*/
+static QString createTmp7z()
{
- d->archive = archive;
-}
+ QTemporaryFile file;
+ if (!file.open()) {
+ throw SevenZipException(QCoreApplication::translate("Lib7z", "Cannot create "
+ "temporary file: %1").arg(file.errorString()));
+ }
-QString ExtractItemJob::targetDirectory() const
-{
- return d->targetDirectory;
+ file.write(QByteArray::fromHex("377A.BCAF.271C" // Signature.
+ ".0003.8D9B.D50F.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000" // Crc + Data.
+ ));
+ file.setAutoRemove(false);
+ return file.fileName();
}
-void ExtractItemJob::setTargetDirectory(const QString &dir)
-{
- d->targetDirectory = dir;
- d->target = 0;
-}
+/*!
+ Creates an archive using the given file device \a archive. \a sourcePaths can contain one or
+ more files, one or more directories or a combination of files and folders. The \c * wildcard
+ is supported also. The value of \a level specifies the compression ratio, the default is set
+ to \c 5 (Normal compression). The \a callback can be used to get information about the archive
+ creation process. If no \a callback is given, an empty implementation is used.
-void ExtractItemJob::setTarget(QFileDevice* dev)
+ \note Throws SevenZipException on error.
+ \note Filenames are stored case-sensitive with UTF-8 encoding.
+ \note The ownership of \a callback is transferred to the function and gets delete on exit.
+*/
+void INSTALLER_EXPORT createArchive(QFileDevice *archive, const QStringList &sources,
+ Compression level, UpdateCallback *callback)
{
- d->target = dev;
-}
+ LIB7Z_ASSERTS(archive, Writable)
-namespace{
- QString errorMessageFrom7zResult(const LONG & extractResult)
- {
- if (!Lib7z::lastError().isEmpty())
- return Lib7z::lastError();
-
- QString errorMessage = QCoreApplication::translate("Lib7z", "internal code: %1");
- switch (extractResult) {
- case S_OK:
- qFatal("S_OK value is not a valid error code.");
- break;
- case E_NOTIMPL:
- errorMessage = errorMessage.arg(QLatin1String("E_NOTIMPL"));
- break;
- case E_NOINTERFACE:
- errorMessage = errorMessage.arg(QLatin1String("E_NOINTERFACE"));
- break;
- case E_ABORT:
- errorMessage = errorMessage.arg(QLatin1String("E_ABORT"));
- break;
- case E_FAIL:
- errorMessage = errorMessage.arg(QLatin1String("E_FAIL"));
- break;
- case STG_E_INVALIDFUNCTION:
- errorMessage = errorMessage.arg(QLatin1String("STG_E_INVALIDFUNCTION"));
- break;
- case E_OUTOFMEMORY:
- errorMessage = QCoreApplication::translate("Lib7z", "not enough memory");
- break;
- case E_INVALIDARG:
- errorMessage = errorMessage.arg(QLatin1String("E_INVALIDARG"));
- break;
- default:
- errorMessage = QCoreApplication::translate("Lib7z", "Error: %1").arg(extractResult);
- break;
- }
- return errorMessage;
- }
-}
+ const QString tmpArchive = createTmp7z();
+ Lib7z::createArchive(tmpArchive, sources, QTmpFile::No, level, callback);
-void Lib7z::createArchive(QFileDevice* archive, const QStringList &sourcePaths, UpdateCallback* callback)
+ try {
+ QFile source(tmpArchive);
+ QInstaller::openForRead(&source);
+ QInstaller::blockingCopy(&source, archive, source.size());
+ } catch (const QInstaller::Error &error) {
+ throw SevenZipException(error.message());
+ }
+}
+
+/*!
+ Creates an archive with the given filename \a archive. \a sourcePaths can contain one or more
+ files, one or more directories or a combination of files and folders. Also the \c * wildcard
+ is supported. To be able to use the function during an elevated installation, set \a mode to
+ \c QTmpFile::Yes. The value of \a level specifies the compression ratio, the default is set
+ to \c 5 (Normal compression). The \a callback can be used to get information about the archive
+ creation process. If no \a callback is given, an empty implementation is used.
+
+ \note Throws SevenZipException on error.
+ \note If \a archive exists, it will be overwritten.
+ \note Filenames are stored case-sensitive with UTF-8 encoding.
+ \note The ownership of \a callback is transferred to the function and gets delete on exit.
+*/
+void createArchive(const QString &archive, const QStringList &sources, QTmpFile mode,
+ Compression level, UpdateCallback *callback)
{
- assert(archive);
-
- QScopedPointer<UpdateCallback> dummyCallback(callback ? 0 : new UpdateCallback);
- if (!callback)
- callback = dummyCallback.data();
-
try {
- callback->setTarget(archive);
-
- QScopedPointer<CCodecs> codecs(new CCodecs);
- if (codecs->Load() != S_OK)
- throw SevenZipException(QCoreApplication::translate("Lib7z", "Could not load codecs"));
-
- CIntVector formatIndices;
-
- if (!codecs.data()->FindFormatForArchiveType(L"", formatIndices)) {
- throw SevenZipException(QCoreApplication::translate("Lib7z",
- "Could not retrieve default format"));
- }
-
- // yes this is crap, but there seems to be no streaming solution to this...
-
- const QString tempFile = generateTempFileName();
-
- NWildcard::CCensor censor;
- foreach (const QString &path, sourcePaths) {
- const QString cleanPath = QDir::toNativeSeparators(QDir::cleanPath(path));
- const UString nativePath = QString2UString(cleanPath);
- if (UString2QString(nativePath) != cleanPath) {
- throw SevenZipException(QCoreApplication::translate("Lib7z", "Could not convert"
- " path: %1.").arg(path));
- }
- censor.AddItem(true /* always include item */, nativePath, false /* never recurse*/);
+ QString target = archive;
+ if (mode == QTmpFile::Yes)
+ target = createTmp7z();
+
+ CArcCmdLineOptions options;
+ try {
+ UStringVector commandStrings;
+ commandStrings.Add(L"a"); // mode: add
+ commandStrings.Add(L"-t7z"); // type: 7z
+ commandStrings.Add(L"-mtm=on"); // time: modeifier|creation|access
+ commandStrings.Add(L"-mtc=on");
+ commandStrings.Add(L"-mta=on");
+ commandStrings.Add(L"-mmt=on"); // threads: multi-threaded
+#ifdef Q_OS_WIN
+ commandStrings.Add(L"-sccUTF-8"); // files: case-sensitive|UTF8
+#endif
+ commandStrings.Add(QString2UString(QString::fromLatin1("-mx=%1").arg(int(level)))); // compression: level
+ commandStrings.Add(QString2UString(QDir::toNativeSeparators(target)));
+ foreach (const QString &source, sources)
+ commandStrings.Add(QString2UString(source));
+
+ CArcCmdLineParser parser;
+ parser.Parse1(commandStrings, options);
+ parser.Parse2(options);
+ } catch (const CArcCmdLineException &e) {
+ throw SevenZipException(UString2QString(e));
}
- callback->setSourcePaths(sourcePaths);
-
- CArchivePath archivePath;
- archivePath.ParseFromPath(QString2UString(tempFile));
- CUpdateArchiveCommand command;
- command.ArchivePath = archivePath;
- command.ActionSet = NUpdateArchive::kAddActionSet;
+ CCodecs codecs;
+ if (codecs.Load() != S_OK)
+ throw SevenZipException(QCoreApplication::translate("Lib7z", "Cannot load codecs."));
- CUpdateOptions options;
- options.Commands.Add(command);
- options.ArchivePath = archivePath;
- options.MethodMode.FormatIndex = codecs->FindFormatForArchiveType(L"7z");
-
- // preserve creation time
- CProperty tc;
- tc.Name = UString(L"TC");
- tc.Value = UString(L"ON");
- options.MethodMode.Properties.Add(tc);
-
- // preserve access time
- CProperty ta;
- ta.Name = UString(L"TA");
- ta.Value = UString(L"ON");
- options.MethodMode.Properties.Add(ta);
+ CObjectVector<COpenType> types;
+ if (!ParseOpenTypes(codecs, options.ArcType, types))
+ throw SevenZipException(QCoreApplication::translate("Lib7z", "Unsupported archive type."));
CUpdateErrorInfo errorInfo;
- const HRESULT res = UpdateArchive(codecs.data(), censor, options, errorInfo, 0, callback->impl());
- if (res != S_OK || !QFile::exists(tempFile)) {
- throw SevenZipException(QCoreApplication::translate("Lib7z",
- "Could not create archive %1. %2").arg(tempFile, errorMessageFrom7zResult(res)));
+ CMyComPtr<UpdateCallback> comCallback = callback == 0 ? new UpdateCallback : callback;
+ const HRESULT res = UpdateArchive(&codecs, types, options.ArchiveName, options.Censor,
+ options.UpdateOptions, errorInfo, nullptr, comCallback, true);
+
+ const QFile tempFile(UString2QString(options.ArchiveName));
+ if (res != S_OK || !tempFile.exists()) {
+ QString errorMsg;
+ if (res == S_OK) {
+ errorMsg = QCoreApplication::translate("Lib7z", "Cannot create archive \"%1\"")
+ .arg(QDir::toNativeSeparators(tempFile.fileName()));
+ } else {
+ errorMsg = QCoreApplication::translate("Lib7z", "Cannot create archive \"%1\": %2")
+ .arg(QDir::toNativeSeparators(tempFile.fileName()), errorMessageFrom7zResult(res));
+ }
+ throw SevenZipException(errorMsg);
}
- {
- //TODO remove temp file even if one the following throws
- QFile file(tempFile);
- QInstaller::openForRead(&file);
- QInstaller::blockingCopy(&file, archive, file.size());
- }
+ if (mode == QTmpFile::Yes) {
+ QFile org(archive);
+ if (org.exists() && !org.remove()) {
+ throw SevenZipException(QCoreApplication::translate("Lib7z", "Cannot remove "
+ "old archive \"%1\": %2").arg(QDir::toNativeSeparators(org.fileName()),
+ org.errorString()));
+ }
- QFile file(tempFile);
- if (!file.remove()) {
- qWarning("%s: Could not remove temporary file %s: %s", Q_FUNC_INFO, qPrintable(tempFile),
- qPrintable(file.errorString()));
+ QFile arc(UString2QString(options.ArchiveName));
+ if(!arc.rename(archive)) {
+ throw SevenZipException(QCoreApplication::translate("Lib7z", "Cannot rename "
+ "temporary archive \"%1\" to \"%2\": %3").arg(
+ QDir::toNativeSeparators(arc.fileName()),
+ QDir::toNativeSeparators(archive),
+ arc.errorString()));
+ }
}
} catch (const char *err) {
- qDebug() << err;
throw SevenZipException(err);
+ } catch (SevenZipException &e) {
+ throw e; // re-throw unmodified
} catch (const QInstaller::Error &err) {
throw SevenZipException(err.message());
} catch (...) {
- throw SevenZipException(QCoreApplication::translate("Lib7z", "Unknown exception caught (%1)")
- .arg(QString::fromLatin1(Q_FUNC_INFO)));
+ throw SevenZipException(QCoreApplication::translate("Lib7z",
+ "Unknown exception caught (%1)").arg(QString::fromLatin1(Q_FUNC_INFO)));
}
}
-void Lib7z::extractFileFromArchive(QFileDevice* archive, const File& item, QFileDevice* target,
- ExtractCallback* callback)
+/*!
+ Extracts the given \a archive content into target directory \a directory using the provided
+ extract callback \a callback. The output filenames are deduced from the \a archive content.
+
+ \note Throws SevenZipException on error.
+ \note The ownership of \a callback is not transferred to the function.
+*/
+void extractArchive(QFileDevice *archive, const QString &directory, ExtractCallback *callback)
{
- assert(archive);
- assert(target);
+ LIB7Z_ASSERTS(archive, Readable)
- std::auto_ptr<ExtractCallback> dummyCallback(callback ? 0 : new ExtractCallback);
- if (!callback)
- callback = dummyCallback.get();
+ // Guard a given object against unwanted delete.
+ CMyComPtr<ExtractCallback> externCallback = callback;
+
+ CMyComPtr<ExtractCallback> localCallback;
+ if (!externCallback) {
+ callback = new ExtractCallback;
+ localCallback = callback;
+ }
+ DirectoryGuard outDir(QFileInfo(directory).absolutePath());
try {
- const OpenArchiveInfo* const openArchive = OpenArchiveInfo::value(archive);
+ outDir.tryCreate();
- const int arcIdx = item.archiveIndex.x();
- if (arcIdx < 0 || arcIdx >= openArchive->archiveLink.Arcs.Size()) {
- throw SevenZipException(QCoreApplication::translate("Lib7z",
- "CArc index %1 out of bounds [0, %2]").arg(openArchive->archiveLink.Arcs.Size() - 1));
- }
- const CArc& arc = openArchive->archiveLink.Arcs[arcIdx];
- IInArchive* const parchive = arc.Archive;
+ CCodecs codecs;
+ if (codecs.Load() != S_OK)
+ throw SevenZipException(QCoreApplication::translate("Lib7z", "Cannot load codecs."));
- const UInt32 itemIdx = item.archiveIndex.y();
- UInt32 numItems = 0;
- if (parchive->GetNumberOfItems(&numItems) != S_OK) {
- throw SevenZipException(QCoreApplication::translate("Lib7z",
- "Could not retrieve number of items in archive"));
- }
+ COpenOptions op;
+ op.codecs = &codecs;
- if (itemIdx >= numItems) {
- throw SevenZipException(QCoreApplication::translate("Lib7z",
- "Item index %1 out of bounds [0, %2]").arg(itemIdx).arg(numItems - 1));
- }
+ CObjectVector<COpenType> types;
+ op.types = &types; // Empty, because we use a stream.
- UString s;
- if (arc.GetItemPath(itemIdx, s) != S_OK) {
- throw SevenZipException(QCoreApplication::translate("Lib7z",
- "Could not retrieve path of archive item %1").arg(itemIdx));
- }
- assert(item.path == UString2QString(s).replace(QLatin1Char('\\'), QLatin1Char('/')));
+ CIntVector excluded;
+ op.excludedFormats = &excluded;
- callback->setTarget(target);
- const LONG extractResult = parchive->Extract(&itemIdx, 1, /*testmode=*/0, callback->impl());
+ const CMyComPtr<IInStream> stream = new QIODeviceInStream(archive);
+ op.stream = stream; // CMyComPtr is needed, otherwise it crashes in OpenStream().
- if (extractResult != S_OK)
- throw SevenZipException(errorMessageFrom7zResult(extractResult));
+ CObjectVector<CProperty> properties;
+ op.props = &properties;
- } catch (const char *err) {
- throw SevenZipException(err);
- } catch (const Lib7z::SevenZipException& e) {
- throw e;
- } catch (...) {
- throw SevenZipException(QCoreApplication::translate("Lib7z", "Unknown exception caught (%1)")
- .arg(QString::fromLatin1(Q_FUNC_INFO)));
- }
-}
-
-void Lib7z::extractFileFromArchive(QFileDevice* archive, const File& item,
- const QString &targetDirectory, ExtractCallback* callback)
-{
- assert(archive);
+ CArchiveLink archiveLink;
+ if (archiveLink.Open2(op, nullptr) != S_OK) {
+ throw SevenZipException(QCoreApplication::translate("Lib7z",
+ "Cannot open archive \"%1\".").arg(archive->fileName()));
+ }
- QScopedPointer<ExtractCallback> dummyCallback(callback ? 0 : new ExtractCallback);
- if (!callback)
- callback = dummyCallback.data();
+ callback->setTarget(directory);
+ for (unsigned a = 0; a < archiveLink.Arcs.Size(); ++a) {
+ callback->setArchive(&archiveLink.Arcs[a]);
+ IInArchive *const arch = archiveLink.Arcs[a].Archive;
- QFileInfo fi(targetDirectory + QLatin1String("/") + item.path);
- DirectoryGuard outDir(fi.absolutePath());
- outDir.tryCreate();
- QFile out(fi.absoluteFilePath());
- if (!out.open(QIODevice::WriteOnly)) { //TODO use tmp file
+ const LONG result = arch->Extract(0, static_cast<UInt32>(-1), false, callback);
+ if (result != S_OK)
+ throw SevenZipException(errorMessageFrom7zResult(result));
+ }
+ } catch (const SevenZipException &e) {
+ externCallback.Detach();
+ throw e; // re-throw unmodified
+ } catch (...) {
+ externCallback.Detach();
throw SevenZipException(QCoreApplication::translate("Lib7z",
- "Could not create output file for writing: %1").arg(fi.absoluteFilePath()));
+ "Unknown exception caught (%1).").arg(QString::fromLatin1(Q_FUNC_INFO)));
}
- callback->setTarget(&out);
- extractFileFromArchive(archive, item, &out, callback);
- if (item.permissions)
- out.setPermissions(item.permissions);
outDir.release();
+ externCallback.Detach();
}
-void Lib7z::extractArchive(QFileDevice* archive, const QString &targetDirectory,
- ExtractCallback* callback)
-{
- assert(archive);
-
- QScopedPointer<ExtractCallback> dummyCallback(callback ? 0 : new ExtractCallback);
- if (!callback)
- callback = dummyCallback.data();
-
- callback->setTarget(targetDirectory);
-
- const QFileInfo fi(targetDirectory);
- DirectoryGuard outDir(fi.absolutePath());
- outDir.tryCreate();
-
- const OpenArchiveInfo* const openArchive = OpenArchiveInfo::value(archive);
-
- for (int a = 0; a < openArchive->archiveLink.Arcs.Size(); ++a)
- {
- const CArc& arc = openArchive->archiveLink.Arcs[a];
- IInArchive* const arch = arc.Archive;
- callback->impl()->setArchive(&arc);
- const LONG extractResult = arch->Extract(0, static_cast< UInt32 >(-1), false, callback->impl());
-
- if (extractResult != S_OK)
- throw SevenZipException(errorMessageFrom7zResult(extractResult));
- }
-
- outDir.release();
-}
+/*!
+ Returns \c true if the given \a archive is supported; otherwise returns \c false.
-bool Lib7z::isSupportedArchive(const QString &archive)
+ \note Throws SevenZipException on error.
+*/
+bool isSupportedArchive(QFileDevice *archive)
{
- QFile file(archive);
- if (!file.open(QIODevice::ReadOnly))
- return false;
+ LIB7Z_ASSERTS(archive, Readable)
- return isSupportedArchive(&file);
-}
-
-bool Lib7z::isSupportedArchive(QFileDevice* archive)
-{
- assert(archive);
- assert(!archive->isSequential());
const qint64 initialPos = archive->pos();
try {
- QScopedPointer<CCodecs> codecs(new CCodecs);
- if (codecs->Load() != S_OK)
- throw SevenZipException(QCoreApplication::translate("Lib7z", "Could not load codecs"));
+ CCodecs codecs;
+ if (codecs.Load() != S_OK)
+ throw SevenZipException(QCoreApplication::translate("Lib7z", "Cannot load codecs."));
- CIntVector formatIndices;
+ COpenOptions op;
+ op.codecs = &codecs;
+
+ CObjectVector<COpenType> types;
+ op.types = &types; // Empty, because we use a stream.
+
+ CIntVector excluded;
+ op.excludedFormats = &excluded;
- if (!codecs->FindFormatForArchiveType(L"", formatIndices)) {
- throw SevenZipException(QCoreApplication::translate("Lib7z",
- "Could not retrieve default format"));
- }
- CArchiveLink archiveLink;
- //CMyComPtr is needed, otherwise it crashes in OpenStream()
const CMyComPtr<IInStream> stream = new QIODeviceInStream(archive);
+ op.stream = stream; // CMyComPtr is needed, otherwise it crashes in OpenStream().
+
+ CObjectVector<CProperty> properties;
+ op.props = &properties;
- const HRESULT result = archiveLink.Open2(codecs.data(), formatIndices, /*stdInMode*/false, stream,
- UString(), 0);
+ CArchiveLink archiveLink;
+ const HRESULT result = archiveLink.Open2(op, nullptr);
archive->seek(initialPos);
return result == S_OK;
- } catch (const SevenZipException& e) {
- archive->seek(initialPos);
- throw e;
} catch (const char *err) {
archive->seek(initialPos);
throw SevenZipException(err);
+ } catch (const SevenZipException &e) {
+ archive->seek(initialPos);
+ throw e; // re-throw unmodified
} catch (...) {
archive->seek(initialPos);
- throw SevenZipException(QCoreApplication::translate("Lib7z", "Unknown exception caught (%1)")
- .arg(QString::fromLatin1(Q_FUNC_INFO)));
+ throw SevenZipException(QCoreApplication::translate("Lib7z",
+ "Unknown exception caught (%1).").arg(QString::fromLatin1(Q_FUNC_INFO)));
}
return false; // never reached
}
-void ExtractItemJob::doStart()
+/*!
+ Returns \c true if the given \a archive is supported; otherwise returns \c false.
+
+ \note Throws SevenZipException on error.
+*/
+bool isSupportedArchive(const QString &archive)
{
- try {
- if (!d->archive)
- throw SevenZipException(tr("Could not list archive: QIODevice not set or already destroyed."));
- if (d->target)
- extractFileFromArchive(d->archive, d->item, d->target, d->callback);
- else if (!d->item.path.isEmpty())
- extractFileFromArchive(d->archive, d->item, d->targetDirectory, d->callback);
- else
- extractArchive(d->archive, d->targetDirectory, d->callback);
- } catch (const SevenZipException& e) {
- setError(Failed);
- setErrorString(tr("Error while extracting '%1': %2").arg(d->item.path, e.message()));
- } catch (...) {
- setError(Failed);
- setErrorString(tr("Unknown exception caught (%1)").arg(tr("Failed")));
- }
- emitResult();
+ QFile file(archive);
+ if (!file.open(QIODevice::ReadOnly))
+ return false;
+ return isSupportedArchive(&file);
}
+
+} // namespace Lib7z
diff --git a/src/libs/installer/lib7z_facade.h b/src/libs/installer/lib7z_facade.h
index f0599b4ce..1c8811cfa 100644
--- a/src/libs/installer/lib7z_facade.h
+++ b/src/libs/installer/lib7z_facade.h
@@ -29,253 +29,48 @@
#define LIB7Z_FACADE_H
#include "installer_global.h"
+#include "errors.h"
-#include <QCoreApplication>
-#include <QDateTime>
-#include <QFile>
-#include <QPoint>
-#include <QRunnable>
-#include <QString>
-#include <QVariant>
-#include <QVector>
-
-#include "Common/MyWindows.h"
-
-#include <stdexcept>
-#include <string>
+#include <Common/MyWindows.h>
+#include <7zip/UI/Console/PercentPrinter.h>
QT_BEGIN_NAMESPACE
-class QStringList;
-template <typename T> class QVector;
+class QFileDevice;
QT_END_NAMESPACE
-namespace Lib7z {
- class INSTALLER_EXPORT SevenZipException : public std::runtime_error {
- public:
- explicit SevenZipException( const QString& msg ) : std::runtime_error( msg.toStdString() ), m_message( msg ) {}
- explicit SevenZipException( const char* msg ) : std::runtime_error( msg ), m_message( QString::fromLocal8Bit( msg ) ) {}
- explicit SevenZipException( const std::string& msg ) : std::runtime_error( msg ), m_message( QString::fromLocal8Bit( msg.c_str() ) ) {}
-
- ~SevenZipException() throw() {}
- QString message() const { return m_message; }
- private:
- QString m_message;
- };
-
- class INSTALLER_EXPORT File {
- public:
- File();
- QVector<File> subtreeInPreorder() const;
-
- bool operator<( const File& other ) const;
- bool operator==( const File& other ) const;
-
- QFile::Permissions permissions;
- QString path;
- QDateTime mtime;
- quint64 uncompressedSize;
- quint64 compressedSize;
- bool isDirectory;
- QVector<File> children;
- QPoint archiveIndex;
- };
-
- class ExtractCallbackPrivate;
- class ExtractCallbackImpl;
-
- class ExtractCallback {
- friend class ::Lib7z::ExtractCallbackImpl;
- public:
- ExtractCallback();
- virtual ~ExtractCallback();
-
- void setTarget(QFileDevice* archive);
- void setTarget(const QString& dir );
-
- protected:
- /**
- * Reimplement to prepare for file @p filename to be extracted, e.g. by renaming existing files.
- * @return @p true if the preparation was successful and extraction can be continued.
- * If @p false is returned, the extraction will be aborted. Default implementation returns @p true.
- */
- virtual bool prepareForFile( const QString& filename );
- virtual void setCurrentFile( const QString& filename );
- virtual HRESULT setCompleted( quint64 completed, quint64 total );
+namespace Lib7z
+{
+ void INSTALLER_EXPORT initSevenZ();
+ bool INSTALLER_EXPORT isSupportedArchive(QFileDevice *archive);
+ bool INSTALLER_EXPORT isSupportedArchive(const QString &archive);
- public: //for internal use
- const ExtractCallbackImpl* impl() const;
- ExtractCallbackImpl* impl();
-
- private:
- ExtractCallbackPrivate* const d;
- };
-
- class UpdateCallbackPrivate;
- class UpdateCallbackImpl;
-
- class UpdateCallback
+ class INSTALLER_EXPORT SevenZipException : public QInstaller::Error
{
- friend class ::Lib7z::UpdateCallbackImpl;
public:
- UpdateCallback();
- virtual ~UpdateCallback();
-
- void setTarget(QFileDevice* archive);
- void setSourcePaths(const QStringList& paths);
-
- virtual UpdateCallbackImpl* impl();
-
- private:
- UpdateCallbackPrivate* const d;
- };
-
- class OpenArchiveInfoCleaner : public QObject {
- Q_OBJECT
- public:
- OpenArchiveInfoCleaner() {}
- private Q_SLOTS:
- void deviceDestroyed(QObject*);
- };
-
- /*!
- Extracts the given File \a file from \a archive into output device \a out using the
- provided extract callback \a callback.
-
- Throws Lib7z::SevenZipException on error.
- */
- void INSTALLER_EXPORT extractFileFromArchive(QFileDevice* archive, const File& item,
- QFileDevice* out, ExtractCallback* callback=0 );
-
- /*!
- Extracts the given File \a file from \a archive into target directory \a targetDirectory
- using the provided extract callback \a callback. The output filename is deduced from the
- \a file path name.
-
- Throws Lib7z::SevenZipException on error.
- */
- void INSTALLER_EXPORT extractFileFromArchive(QFileDevice* archive, const File& item,
- const QString& targetDirectory, ExtractCallback* callback = 0);
-
- /*!
- Extracts the given \a archive content into target directory \a targetDirectory using the
- provided extract callback \a callback. The output filenames are deduced from the \a archive
- content.
+ explicit SevenZipException(const QString &msg)
+ : QInstaller::Error(msg)
+ {}
- Throws Lib7z::SevenZipException on error.
- */
- void INSTALLER_EXPORT extractArchive(QFileDevice* archive, const QString& targetDirectory,
- ExtractCallback* callback = 0);
-
- /*
- * @thows Lib7z::SevenZipException
- */
- void INSTALLER_EXPORT createArchive(QFileDevice* archive, const QStringList& sourcePaths,
- UpdateCallback* callback = 0 );
-
- /*
- * @throws Lib7z::SevenZipException
- */
- QVector<File> INSTALLER_EXPORT listArchive(QFileDevice* archive);
-
- /*
- * @throws Lib7z::SevenZipException
- */
- bool INSTALLER_EXPORT isSupportedArchive(QFileDevice* archive);
-
- /*
- * @throws Lib7z::SevenZipException
- */
- bool INSTALLER_EXPORT isSupportedArchive(const QString& archive);
-
- enum Error {
- NoError=0,
- Failed=1,
- UserDefinedError=128
+ explicit SevenZipException(const char *msg)
+ : QInstaller::Error(QString::fromLocal8Bit(msg))
+ {}
};
- class ExtractCallbackJobImpl;
-
- class INSTALLER_EXPORT Job : public QObject, public QRunnable
+ class INSTALLER_EXPORT PercentPrinter : public CPercentPrinter
{
- friend class ::Lib7z::ExtractCallbackJobImpl;
- Q_OBJECT
- public:
-
- explicit Job( QObject* parent=0 );
- ~Job();
- void start();
- int error() const;
- bool hasError() const;
- QString errorString() const;
-
- /* reimp */ void run();
-
- protected:
- void emitResult();
- void setError( int code );
- void setErrorString( const QString& err );
- void emitProgress( qint64 completed, qint64 total );
-
- Q_SIGNALS:
- void finished( Lib7z::Job* job );
- void progress( qint64 completed, qint64 total );
-
- private Q_SLOTS:
- virtual void doStart() = 0;
-
- private:
- class Private;
- Private* const d;
- };
-
- class INSTALLER_EXPORT ListArchiveJob : public Job {
- Q_OBJECT
public:
-
- explicit ListArchiveJob( QObject* parent=0 );
- ~ListArchiveJob();
-
- QFileDevice* archive() const;
- void setArchive(QFileDevice* archive);
-
- QVector<File> index() const;
-
- private:
- /* reimp */ void doStart();
-
- private:
- class Private;
- Private* const d;
- };
-
- class INSTALLER_EXPORT ExtractItemJob : public Job {
- Q_OBJECT
- friend class ::Lib7z::ExtractCallback;
- public:
-
- explicit ExtractItemJob( QObject* parent=0 );
- ~ExtractItemJob();
-
- File item() const;
- void setItem( const File& item );
-
- QFileDevice* archive() const;
- void setArchive(QFileDevice* archive);
-
- QString targetDirectory() const;
- void setTargetDirectory( const QString& dir );
-
- void setTarget(QFileDevice* dev);
-
- private:
- /* reimp */ void doStart();
-
- private:
- class Private;
- Private* const d;
+ PercentPrinter() : CPercentPrinter(1 << 16) {
+ OutStream = &g_StdOut;
+ }
+
+ void PrintRatio() { CPercentPrinter::PrintRatio(); }
+ void ClosePrint() { CPercentPrinter::ClosePrint(); }
+ void RePrintRatio() { CPercentPrinter::RePrintRatio(); }
+ void PrintNewLine() { CPercentPrinter::PrintNewLine(); }
+ void PrintString(const char *s) { CPercentPrinter::PrintString(s); }
+ void PrintString(const wchar_t *s) { CPercentPrinter::PrintString(s); }
};
- QByteArray INSTALLER_EXPORT formatKeyValuePairs( const QVariantList& l );
-}
+} // namespace Lib7z
#endif // LIB7Z_FACADE_H
diff --git a/src/libs/installer/lib7z_guid.h b/src/libs/installer/lib7z_guid.h
new file mode 100644
index 000000000..16434558c
--- /dev/null
+++ b/src/libs/installer/lib7z_guid.h
@@ -0,0 +1,97 @@
+/**************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+#ifndef LIB7Z_GUID_H
+#define LIB7Z_GUID_H
+
+#include <Common/MyInitGuid.h>
+
+#ifdef __cplusplus
+#define DEFINE_7Z_GUID(name, b4, b5, b6) extern "C" const GUID IID_ ## name = { 0x23170F69, \
+ 0x40C1, 0x278A, { 0x00, 0x00, 0x00, b4, b5, b6, 0x00, 0x00 } }
+#else
+#define DEFINE_7Z_GUID(name, b4, b5, b6) extern const GUID IID_ ## name = { 0x23170F69, \
+ 0x40C1, 0x278A, { 0x00, 0x00, 0x00, b4, b5, b6, 0x00, 0x00 } }
+#endif
+
+DEFINE_7Z_GUID(IInArchiveGetStream, 0x06, 0x00, 0x40);
+DEFINE_7Z_GUID(IInArchive, 0x06, 0x00, 0x60);
+
+DEFINE_7Z_GUID(IOutStream, 0x03, 0x00, 0x04);
+DEFINE_7Z_GUID(IOutStreamFlush, 0x03, 0x00, 0x07);
+DEFINE_7Z_GUID(IOutArchive, 0x06, 0x00, 0xA0);
+
+DEFINE_7Z_GUID(IInStream, 0x03, 0x00, 0x03);
+
+DEFINE_7Z_GUID(ISetProperties, 0x06, 0x00, 0x03);
+
+DEFINE_7Z_GUID(ISequentialInStream, 0x03, 0x00, 0x01);
+DEFINE_7Z_GUID(ISequentialOutStream, 0x03, 0x00, 0x02);
+
+DEFINE_7Z_GUID(IStreamGetSize, 0x03, 0x00, 0x06);
+DEFINE_7Z_GUID(IStreamGetProps, 0x03, 0x00, 0x08);
+DEFINE_7Z_GUID(IStreamGetProps2, 0x03, 0x00, 0x09);
+
+DEFINE_7Z_GUID(IArchiveKeepModeForNextOpen, 0x06, 0x00, 0x04);
+DEFINE_7Z_GUID(IArchiveAllowTail, 0x06, 0x00, 0x05);
+DEFINE_7Z_GUID(IArchiveOpenCallback, 0x06, 0x00, 0x10);
+DEFINE_7Z_GUID(IArchiveExtractCallback, 0x06, 0x00, 0x20);
+DEFINE_7Z_GUID(IArchiveOpenVolumeCallback, 0x06, 0x00, 0x30);
+DEFINE_7Z_GUID(IArchiveOpenSetSubArchiveName, 0x06, 0x00, 0x50);
+DEFINE_7Z_GUID(IArchiveOpenSeq, 0x06, 0x00, 0x61);
+DEFINE_7Z_GUID(IArchiveGetRawProps, 0x06, 0x00, 0x70);
+DEFINE_7Z_GUID(IArchiveGetRootProps, 0x06, 0x00, 0x71);
+DEFINE_7Z_GUID(IArchiveUpdateCallback, 0x06, 0x00, 0x80);
+DEFINE_7Z_GUID(IArchiveUpdateCallback2, 0x06, 0x00, 0x82);
+
+DEFINE_7Z_GUID(ICompressProgressInfo, 0x04, 0x00, 0x04);
+DEFINE_7Z_GUID(ICompressCoder, 0x04, 0x00, 0x05);
+DEFINE_7Z_GUID(ICompressSetCoderProperties, 0x04, 0x00, 0x20);
+DEFINE_7Z_GUID(ICompressSetDecoderProperties2, 0x04, 0x00, 0x22);
+DEFINE_7Z_GUID(ICompressWriteCoderProperties, 0x04, 0x00, 0x23);
+DEFINE_7Z_GUID(ICompressGetInStreamProcessedSize, 0x04, 0x00, 0x24);
+DEFINE_7Z_GUID(ICompressSetCoderMt, 0x04, 0x00, 0x25);
+DEFINE_7Z_GUID(ICompressSetOutStream, 0x04, 0x00, 0x32);
+DEFINE_7Z_GUID(ICompressSetInStream, 0x04, 0x00, 0x31);
+DEFINE_7Z_GUID(ICompressSetOutStreamSize, 0x04, 0x00, 0x34);
+DEFINE_7Z_GUID(ICompressSetBufSize, 0x04, 0x00, 0x35);
+DEFINE_7Z_GUID(ICompressGetSubStreamSize, 0x04, 0x00, 0x30);
+DEFINE_7Z_GUID(ICryptoResetInitVector, 0x04, 0x00, 0x8C);
+DEFINE_7Z_GUID(ICryptoSetPassword, 0x04, 0x00, 0x90);
+
+DEFINE_7Z_GUID(ICryptoGetTextPassword, 0x05, 0x00, 0x10);
+DEFINE_7Z_GUID(ICryptoGetTextPassword2, 0x05, 0x00, 0x11);
+
+#undef DEFINE_7Z_GUID
+
+#endif // LIB7Z_GUID_H
diff --git a/src/libs/installer/lib7z_list.h b/src/libs/installer/lib7z_list.h
new file mode 100644
index 000000000..6e2646025
--- /dev/null
+++ b/src/libs/installer/lib7z_list.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+#ifndef LIB7Z_LIST_H
+#define LIB7Z_LIST_H
+
+#include "installer_global.h"
+
+#include <QDateTime>
+#include <QFile>
+#include <QPoint>
+
+namespace Lib7z
+{
+ struct INSTALLER_EXPORT File
+ {
+ public:
+ QString path;
+ QDateTime utcTime;
+ QPoint archiveIndex;
+ bool isDirectory = false;
+ quint64 compressedSize = 0;
+ quint64 uncompressedSize = 0;
+ QFile::Permissions permissions = 0;
+ };
+ INSTALLER_EXPORT bool operator==(const File &lhs, const File &rhs);
+
+ QVector<File> INSTALLER_EXPORT listArchive(QFileDevice *archive);
+
+} // namespace Lib7z
+
+#endif // LIB7Z_LIST_H
diff --git a/src/libs/installer/licenseoperation.cpp b/src/libs/installer/licenseoperation.cpp
index 25637b5a3..059798338 100644
--- a/src/libs/installer/licenseoperation.cpp
+++ b/src/libs/installer/licenseoperation.cpp
@@ -37,7 +37,8 @@
using namespace QInstaller;
-LicenseOperation::LicenseOperation()
+LicenseOperation::LicenseOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("License"));
}
@@ -55,26 +56,25 @@ bool LicenseOperation::performOperation()
return false;
}
- PackageManagerCore *const core = value(QLatin1String("installer")).value<PackageManagerCore*>();
+ PackageManagerCore *const core = packageManager();
if (!core) {
setError( UserDefinedError );
setErrorString(tr("Needed installer object in %1 operation is empty.").arg(name()));
return false;
}
- QString targetDir = QString::fromLatin1("%1/%2").arg(core->value(scTargetDir),
- QLatin1String("Licenses"));
+ QString targetDir = QString::fromLatin1("%1%2%3").arg(core->value(scTargetDir),
+ QDir::separator(), QLatin1String("Licenses"));
QDir dir;
dir.mkpath(targetDir);
setArguments(QStringList(targetDir));
- for (QVariantMap::const_iterator it = licenses.begin(); it != licenses.end(); ++it) {
- QFile file(targetDir + QDir::separator() + it.key());
+ for (QVariantMap::const_iterator it = licenses.constBegin(); it != licenses.constEnd(); ++it) {
+ QFile file(targetDir + QLatin1Char('/') + it.key());
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
setError(UserDefinedError);
- setErrorString(tr("Can not write license file: %1.").arg(targetDir + QDir::separator()
- + it.key()));
+ setErrorString(tr("Can not write license file \"%1\".").arg(QDir::toNativeSeparators(file.fileName())));
return false;
}
@@ -87,7 +87,7 @@ bool LicenseOperation::performOperation()
bool LicenseOperation::undoOperation()
{
- QVariantMap licenses = value(QLatin1String("licenses")).toMap();
+ const QVariantMap licenses = value(QLatin1String("licenses")).toMap();
if (licenses.isEmpty()) {
setError(UserDefinedError);
setErrorString(tr("No license files found to delete."));
@@ -108,8 +108,3 @@ bool LicenseOperation::testOperation()
{
return true;
}
-
-Operation *LicenseOperation::clone() const
-{
- return new LicenseOperation();
-}
diff --git a/src/libs/installer/licenseoperation.h b/src/libs/installer/licenseoperation.h
index 37820fbe5..49b885565 100644
--- a/src/libs/installer/licenseoperation.h
+++ b/src/libs/installer/licenseoperation.h
@@ -37,13 +37,12 @@ class INSTALLER_EXPORT LicenseOperation : public Operation
{
Q_DECLARE_TR_FUNCTIONS(QInstaller::LicenseOperation)
public:
- LicenseOperation();
+ explicit LicenseOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation* clone() const;
};
} // namespace QInstaller
diff --git a/src/libs/installer/linereplaceoperation.cpp b/src/libs/installer/linereplaceoperation.cpp
index 87e1f2bf7..e67335e55 100644
--- a/src/libs/installer/linereplaceoperation.cpp
+++ b/src/libs/installer/linereplaceoperation.cpp
@@ -34,7 +34,8 @@
using namespace QInstaller;
-LineReplaceOperation::LineReplaceOperation()
+LineReplaceOperation::LineReplaceOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("LineReplace"));
}
@@ -45,18 +46,14 @@ void LineReplaceOperation::backup()
bool LineReplaceOperation::performOperation()
{
- const QStringList args = arguments();
-
// Arguments:
// 1. filename
// 2. startsWith Search-String
// 3. Replace-Line-String
- if (args.count() != 3) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("exactly 3"), QLatin1String("")));
+ if (!checkArgumentCount(3))
return false;
- }
+
+ const QStringList args = arguments();
const QString fileName = args.at(0);
const QString searchString = args.at(1);
const QString replaceString = args.at(2);
@@ -64,7 +61,8 @@ bool LineReplaceOperation::performOperation()
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
setError(UserDefinedError);
- setErrorString(tr("Failed to open '%1' for reading.").arg(fileName));
+ setErrorString(tr("Cannot open file \"%1\" for reading: %2").arg(
+ QDir::toNativeSeparators(fileName), file.errorString()));
return false;
}
@@ -81,7 +79,8 @@ bool LineReplaceOperation::performOperation()
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
setError(UserDefinedError);
- setErrorString(tr("Failed to open '%1' for writing.").arg(fileName));
+ setErrorString(tr("Cannot open file \"%1\" for writing: %2").arg(
+ QDir::toNativeSeparators(fileName), file.errorString()));
return false;
}
@@ -101,8 +100,3 @@ bool LineReplaceOperation::testOperation()
{
return true;
}
-
-Operation *LineReplaceOperation::clone() const
-{
- return new LineReplaceOperation();
-}
diff --git a/src/libs/installer/linereplaceoperation.h b/src/libs/installer/linereplaceoperation.h
index 6370a535c..d15e11fef 100644
--- a/src/libs/installer/linereplaceoperation.h
+++ b/src/libs/installer/linereplaceoperation.h
@@ -37,13 +37,12 @@ class INSTALLER_EXPORT LineReplaceOperation : public Operation
{
Q_DECLARE_TR_FUNCTIONS(QInstaller::LineReplaceOperation)
public:
- LineReplaceOperation();
+ explicit LineReplaceOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
};
} // namespace
diff --git a/src/libs/installer/link.cpp b/src/libs/installer/link.cpp
index ac4935a8b..ef91828ce 100644
--- a/src/libs/installer/link.cpp
+++ b/src/libs/installer/link.cpp
@@ -88,8 +88,7 @@ public:
OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0);
if (m_dirHandle == INVALID_HANDLE_VALUE) {
- qWarning() << QString::fromLatin1("Could not open: '%1'; error: %2\n").arg(path)
- .arg(QInstaller::windowsErrorString(GetLastError()));
+ qWarning() << "Cannot open" << path << ":" << QInstaller::windowsErrorString(GetLastError());
}
}
@@ -138,14 +137,12 @@ QString readWindowsSymLink(const QString &path)
Link createJunction(const QString &linkPath, const QString &targetPath)
{
if (!QDir().mkpath(linkPath)) {
- qWarning() << QString::fromLatin1("Could not create the mount directory: %1").arg(
- linkPath);
+ qWarning() << "Cannot create the mount directory" << linkPath;
return Link(linkPath);
}
FileHandleWrapper dirHandle(linkPath);
if (dirHandle.handle() == INVALID_HANDLE_VALUE) {
- qWarning() << QString::fromLatin1("Could not open: '%1'; error: %2\n").arg(linkPath)
- .arg(QInstaller::windowsErrorString(GetLastError()));
+ qWarning() << "Cannot open" << linkPath << ":" << QInstaller::windowsErrorString(GetLastError());
return Link(linkPath);
}
@@ -175,8 +172,8 @@ Link createJunction(const QString &linkPath, const QString &targetPath)
if (!::DeviceIoControl(dirHandle.handle(), FSCTL_SET_REPARSE_POINT, reparseStructData,
reparseStructData->ReparseDataLength + REPARSE_DATA_BUFFER_HEADER_SIZE, 0, 0,
&bytesReturned, 0)) {
- qWarning() << QString::fromLatin1("Could not set the reparse point: for '%1' to %2; error: %3"
- ).arg(linkPath, targetPath).arg(QInstaller::windowsErrorString(GetLastError()));
+ qWarning() << "Cannot set the reparse point for" << linkPath << "to" << targetPath
+ << ":" << QInstaller::windowsErrorString(GetLastError());
}
return Link(linkPath);
}
@@ -197,8 +194,7 @@ bool removeJunction(const QString &path)
REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, 0, 0,
&bytesReturned, 0)) {
- qWarning() << QString::fromLatin1("Could not remove the reparse point: '%1'; error: %3"
- ).arg(path).arg(QInstaller::windowsErrorString(GetLastError()));
+ qWarning() << "Cannot remove the reparse point" << path << ":" << QInstaller::windowsErrorString(GetLastError());
return false;
}
}
@@ -211,8 +207,7 @@ Link createLnSymlink(const QString &linkPath, const QString &targetPath)
int linkedError = symlink(QFileInfo(targetPath).absoluteFilePath().toUtf8(),
QFileInfo(linkPath).absoluteFilePath().toUtf8());
if (linkedError != 0) {
- qWarning() << QString::fromLatin1("Could not create a symlink: from '%1' to %2; error: %3"
- ).arg(linkPath, targetPath).arg(linkedError);
+ qWarning() << "Cannot create a symlink from" << linkPath << "to" << targetPath << ":" << linkedError;
}
@@ -239,8 +234,7 @@ Link Link::create(const QString &link, const QString &targetPath)
if (!linkPathExists)
linkPathExists = QDir().mkpath(linkPath);
if (!linkPathExists) {
- qWarning() << QString::fromLatin1("Could not create the needed directories: %1").arg(
- link);
+ qWarning() << "Cannot create the needed directories" << link;
return Link(link);
}
@@ -248,8 +242,8 @@ Link Link::create(const QString &link, const QString &targetPath)
if (QFileInfo(targetPath).isDir())
return createJunction(link, targetPath);
- qWarning() << QString::fromLatin1("At the moment the %1 can not create anything else as "\
- "junctions for directories under windows").arg(QLatin1String(Q_FUNC_INFO));
+ qWarning() << "At the moment the" << Q_FUNC_INFO << "can not create anything else as "
+ << "junctions for directories under windows";
return Link(link);
#else
return createLnSymlink(link, targetPath);
diff --git a/src/libs/installer/messageboxhandler.cpp b/src/libs/installer/messageboxhandler.cpp
index f99a9ebd3..fcdee4a5f 100644
--- a/src/libs/installer/messageboxhandler.cpp
+++ b/src/libs/installer/messageboxhandler.cpp
@@ -401,8 +401,8 @@ QMessageBox::StandardButton MessageBoxHandler::showMessageBox(MessageType messag
messageTypeHash.insert(warningType, QLatin1String("warning"));
};
- qDebug() << QString::fromLatin1("created %1 message box %2: '%3', %4").arg(messageTypeHash
- .value(messageType),identifier, title, text);
+ qDebug().nospace() << "Created " << messageTypeHash.value(messageType).toUtf8().constData()
+ << " message box " << identifier << ": " << title << ", " << text;
if (qobject_cast<QApplication*> (qApp) == 0)
return defaultButton;
diff --git a/src/libs/installer/metadatajob.cpp b/src/libs/installer/metadatajob.cpp
index b88f71137..0c674e313 100644
--- a/src/libs/installer/metadatajob.cpp
+++ b/src/libs/installer/metadatajob.cpp
@@ -34,6 +34,7 @@
#include "proxycredentialsdialog.h"
#include "serverauthenticationdialog.h"
#include "settings.h"
+#include "testrepository.h"
#include <QTemporaryDir>
@@ -48,17 +49,19 @@ static QUrl resolveUrl(const FileTaskResult &result, const QString &url)
}
MetadataJob::MetadataJob(QObject *parent)
- : KDJob(parent)
+ : Job(parent)
, m_core(0)
+ , m_addCompressedPackages(false)
{
setCapabilities(Cancelable);
- connect(&m_xmlTask, SIGNAL(finished()), this, SLOT(xmlTaskFinished()));
- connect(&m_metadataTask, SIGNAL(finished()), this, SLOT(metadataTaskFinished()));
- connect(&m_metadataTask, SIGNAL(progressValueChanged(int)), this, SLOT(progressChanged(int)));
+ connect(&m_xmlTask, &QFutureWatcherBase::finished, this, &MetadataJob::xmlTaskFinished);
+ connect(&m_metadataTask, &QFutureWatcherBase::finished, this, &MetadataJob::metadataTaskFinished);
+ connect(&m_metadataTask, &QFutureWatcherBase::progressValueChanged, this, &MetadataJob::progressChanged);
}
MetadataJob::~MetadataJob()
{
+ resetCompressedFetch();
reset();
}
@@ -72,46 +75,183 @@ Repository MetadataJob::repositoryForDirectory(const QString &directory) const
void MetadataJob::doStart()
{
- reset();
if (!m_core) {
- emitFinishedWithError(KDJob::Canceled, tr("Missing package manager core engine."));
+ emitFinishedWithError(Job::Canceled, tr("Missing package manager core engine."));
return; // We can't do anything here without core, so avoid tons of !m_core checks.
}
-
- emit infoMessage(this, tr("Preparing meta information download..."));
- const bool onlineInstaller = m_core->isInstaller() && !m_core->isOfflineOnly();
- if (onlineInstaller || (m_core->isUpdater() || m_core->isPackageManager())) {
- QList<FileTaskItem> items;
- const ProductKeyCheck *const productKeyCheck = ProductKeyCheck::instance();
- foreach (const Repository &repo, m_core->settings().repositories()) {
- if (repo.isEnabled() && productKeyCheck->isValidRepository(repo)) {
- QAuthenticator authenticator;
- authenticator.setUser(repo.username());
- authenticator.setPassword(repo.password());
-
- QString url = repo.url().toString() + QLatin1String("/Updates.xml?");
- if (!m_core->value(QLatin1String("UrlQueryString")).isEmpty())
- url += m_core->value(QLatin1String("UrlQueryString")) + QLatin1Char('&');
-
- // also append a random string to avoid proxy caches
- FileTaskItem item(url.append(QString::number(qrand() * qrand())));
- item.insert(TaskRole::UserRole, QVariant::fromValue(repo));
- item.insert(TaskRole::Authenticator, QVariant::fromValue(authenticator));
- items.append(item);
+ const ProductKeyCheck *const productKeyCheck = ProductKeyCheck::instance();
+ if (!m_addCompressedPackages) {
+ reset();
+ emit infoMessage(this, tr("Preparing meta information download..."));
+ const bool onlineInstaller = m_core->isInstaller() && !m_core->isOfflineOnly();
+
+ if (onlineInstaller || m_core->isMaintainer()) {
+ QList<FileTaskItem> items;
+ foreach (const Repository &repo, m_core->settings().repositories()) {
+ if (repo.isEnabled() &&
+ productKeyCheck->isValidRepository(repo)) {
+ QAuthenticator authenticator;
+ authenticator.setUser(repo.username());
+ authenticator.setPassword(repo.password());
+
+ if (!repo.isCompressed()) {
+ QString url = repo.url().toString() + QLatin1String("/Updates.xml?");
+ if (!m_core->value(scUrlQueryString).isEmpty())
+ url += m_core->value(scUrlQueryString) + QLatin1Char('&');
+
+ // also append a random string to avoid proxy caches
+ FileTaskItem item(url.append(QString::number(qrand() * qrand())));
+ item.insert(TaskRole::UserRole, QVariant::fromValue(repo));
+ item.insert(TaskRole::Authenticator, QVariant::fromValue(authenticator));
+ items.append(item);
+ }
+ else {
+ qDebug() << "Trying to parse compressed repo as normal repository."\
+ "Check repository syntax.";
+ }
+ }
}
+ if (items.count() > 0) {
+ startXMLTask(items);
+ } else {
+ emitFinished();
+ }
+ } else {
+ emitFinished();
}
- DownloadFileTask *const xmlTask = new DownloadFileTask(items);
- xmlTask->setProxyFactory(m_core->proxyFactory());
- m_xmlTask.setFuture(QtConcurrent::run(&DownloadFileTask::doTask, xmlTask));
} else {
- emitFinished();
+ resetCompressedFetch();
+
+ bool repositoriesFound = false;
+ foreach (const Repository &repo, m_core->settings().temporaryRepositories()) {
+ if (repo.isCompressed() && repo.isEnabled() &&
+ productKeyCheck->isValidRepository(repo)) {
+ repositoriesFound = true;
+ startUnzipRepositoryTask(repo);
+
+ //Set the repository disabled so we don't handle it many times
+ Repository replacement = repo;
+ replacement.setEnabled(false);
+ Settings &s = m_core->settings();
+ QSet<Repository> temporaries = s.temporaryRepositories();
+ if (temporaries.contains(repo)) {
+ temporaries.remove(repo);
+ temporaries.insert(replacement);
+ s.setTemporaryRepositories(temporaries, true);
+ }
+ }
+ }
+ if (!repositoriesFound) {
+ emitFinished();
+ }
+ else {
+ setProgressTotalAmount(0);
+ emit infoMessage(this, tr("Unpacking compressed repositories. This may take a while..."));
+ }
}
}
+void MetadataJob::startXMLTask(const QList<FileTaskItem> items)
+{
+ DownloadFileTask *const xmlTask = new DownloadFileTask(items);
+ xmlTask->setProxyFactory(m_core->proxyFactory());
+ m_xmlTask.setFuture(QtConcurrent::run(&DownloadFileTask::doTask, xmlTask));
+}
+
void MetadataJob::doCancel()
{
reset();
- emitFinishedWithError(KDJob::Canceled, tr("Meta data download canceled."));
+ emitFinishedWithError(Job::Canceled, tr("Meta data download canceled."));
+}
+
+void MetadataJob::startUnzipRepositoryTask(const Repository &repo)
+{
+ QTemporaryDir tempRepoDir(QDir::tempPath() + QLatin1String("/compressedRepo-XXXXXX"));
+ if (!tempRepoDir.isValid()) {
+ qDebug() << "Cannot create unique temporary directory.";
+ return;
+ }
+ tempRepoDir.setAutoRemove(false);
+ m_tempDirDeleter.add(tempRepoDir.path());
+ QString url = repo.url().toLocalFile();
+ UnzipArchiveTask *task = new UnzipArchiveTask(url, tempRepoDir.path());
+ QFutureWatcher<void> *watcher = new QFutureWatcher<void>();
+ m_unzipRepositoryTasks.insert(watcher, qobject_cast<QObject*> (task));
+ connect(watcher, &QFutureWatcherBase::finished, this,
+ &MetadataJob::unzipRepositoryTaskFinished);
+ connect(watcher, &QFutureWatcherBase::progressValueChanged, this,
+ &MetadataJob::progressChanged);
+ watcher->setFuture(QtConcurrent::run(&UnzipArchiveTask::doTask, task));
+}
+
+void MetadataJob::unzipRepositoryTaskFinished()
+{
+ QFutureWatcher<void> *watcher = static_cast<QFutureWatcher<void> *>(sender());
+ int error = Job::NoError;
+ QString errorString;
+ try {
+ watcher->waitForFinished(); // trigger possible exceptions
+
+ QHashIterator<QFutureWatcher<void> *, QObject*> i(m_unzipRepositoryTasks);
+ while (i.hasNext()) {
+
+ i.next();
+ if (i.key() == watcher) {
+ UnzipArchiveTask *task = qobject_cast<UnzipArchiveTask*> (i.value());
+ QString url = task->target();
+
+ QUrl targetUrl = targetUrl.fromLocalFile(url);
+ Repository repo(targetUrl, false, true);
+ url = repo.url().toString() + QLatin1String("/Updates.xml");
+ TestRepository testJob(m_core);
+ testJob.setRepository(repo);
+ testJob.start();
+ testJob.waitForFinished();
+ error = testJob.error();
+ errorString = testJob.errorString();
+ if (error == Job::NoError) {
+ FileTaskItem item(url);
+ item.insert(TaskRole::UserRole, QVariant::fromValue(repo));
+ m_unzipRepositoryitems.append(item);
+ } else {
+ //Repository is not valid, remove it
+ Repository repository;
+ repository.setUrl(QUrl(task->archive()));
+ Settings &s = m_core->settings();
+ QSet<Repository> temporaries = s.temporaryRepositories();
+ foreach (Repository repository, temporaries) {
+ if (repository.url().toLocalFile() == task->archive()) {
+ temporaries.remove(repository);
+ }
+ }
+ s.setTemporaryRepositories(temporaries, false);
+ }
+ }
+ }
+ delete m_unzipRepositoryTasks.value(watcher);
+ m_unzipRepositoryTasks.remove(watcher);
+ delete watcher;
+
+ //One can specify many zipped repository items at once. As the repositories are
+ //unzipped one by one, we collect here all items before parsing xml files from those.
+ if (m_unzipRepositoryitems.count() > 0 && m_unzipRepositoryTasks.isEmpty()) {
+ startXMLTask(m_unzipRepositoryitems);
+ } else {
+ if (error != Job::NoError) {
+ emitFinishedWithError(QInstaller::DownloadError, errorString);
+ }
+ }
+
+ } catch (const UnzipArchiveException &e) {
+ reset();
+ emitFinishedWithError(QInstaller::ExtractionError, e.message());
+ } catch (const QUnhandledException &e) {
+ reset();
+ emitFinishedWithError(QInstaller::DownloadError, QLatin1String(e.what()));
+ } catch (...) {
+ reset();
+ emitFinishedWithError(QInstaller::DownloadError, tr("Unknown exception during extracting."));
+ }
}
void MetadataJob::xmlTaskFinished()
@@ -124,7 +264,7 @@ void MetadataJob::xmlTaskFinished()
if (e.type() == AuthenticationRequiredException::Type::Proxy) {
const QNetworkProxy proxy = e.proxy();
ProxyCredentialsDialog proxyCredentials(proxy);
- qDebug() << e.message();
+ qDebug().noquote() << e.message();
if (proxyCredentials.exec() == QDialog::Accepted) {
qDebug() << "Retrying with new credentials ...";
@@ -139,7 +279,7 @@ void MetadataJob::xmlTaskFinished()
emitFinishedWithError(QInstaller::DownloadError, tr("Missing proxy credentials."));
}
} else if (e.type() == AuthenticationRequiredException::Type::Server) {
- qDebug() << e.message();
+ qDebug().noquote() << e.message();
ServerAuthenticationDialog dlg(e.message(), e.taskItem());
if (dlg.exec() == QDialog::Accepted) {
Repository original = e.taskItem().value(TaskRole::UserRole)
@@ -160,7 +300,7 @@ void MetadataJob::xmlTaskFinished()
if (s.updateDefaultRepositories(update) == Settings::UpdatesApplied
|| s.updateUserRepositories(update) == Settings::UpdatesApplied) {
- if (m_core->isUpdater() || m_core->isPackageManager())
+ if (m_core->isMaintainer())
m_core->writeMaintenanceConfigFiles();
}
}
@@ -181,7 +321,7 @@ void MetadataJob::xmlTaskFinished()
emitFinishedWithError(QInstaller::DownloadError, tr("Unknown exception during download."));
}
- if (error() != KDJob::NoError)
+ if (error() != Job::NoError)
return;
if (status == XmlDownloadSuccess) {
@@ -189,6 +329,7 @@ void MetadataJob::xmlTaskFinished()
DownloadFileTask *const metadataTask = new DownloadFileTask(m_packages);
metadataTask->setProxyFactory(m_core->proxyFactory());
m_metadataTask.setFuture(QtConcurrent::run(&DownloadFileTask::doTask, metadataTask));
+ setProgressTotalAmount(100);
emit infoMessage(this, tr("Retrieving meta information from remote repository..."));
} else if (status == XmlDownloadRetry) {
QMetaObject::invokeMethod(this, "doStart", Qt::QueuedConnection);
@@ -204,17 +345,14 @@ void MetadataJob::unzipTaskFinished()
try {
watcher->waitForFinished(); // trigger possible exceptions
} catch (const UnzipArchiveException &e) {
- reset();
emitFinishedWithError(QInstaller::ExtractionError, e.message());
} catch (const QUnhandledException &e) {
- reset();
emitFinishedWithError(QInstaller::DownloadError, QLatin1String(e.what()));
} catch (...) {
- reset();
emitFinishedWithError(QInstaller::DownloadError, tr("Unknown exception during extracting."));
}
- if (error() != KDJob::NoError)
+ if (error() != Job::NoError)
return;
delete m_unzipTasks.value(watcher);
@@ -232,6 +370,11 @@ void MetadataJob::progressChanged(int progress)
setProcessedAmount(progress);
}
+void MetadataJob::setProgressTotalAmount(int maximum)
+{
+ setTotalAmount(maximum);
+}
+
void MetadataJob::metadataTaskFinished()
{
try {
@@ -246,7 +389,7 @@ void MetadataJob::metadataTaskFinished()
QFutureWatcher<void> *watcher = new QFutureWatcher<void>();
m_unzipTasks.insert(watcher, qobject_cast<QObject*> (task));
- connect(watcher, SIGNAL(finished()), this, SLOT(unzipTaskFinished()));
+ connect(watcher, &QFutureWatcherBase::finished, this, &MetadataJob::unzipTaskFinished);
watcher->setFuture(QtConcurrent::run(&UnzipArchiveTask::doTask, task));
}
} else {
@@ -272,13 +415,24 @@ void MetadataJob::reset()
m_packages.clear();
m_metadata.clear();
- setError(KDJob::NoError);
+ setError(Job::NoError);
setErrorString(QString());
setCapabilities(Cancelable);
try {
m_xmlTask.cancel();
m_metadataTask.cancel();
+ } catch (...) {}
+ m_tempDirDeleter.releaseAndDeleteAll();
+}
+
+void MetadataJob::resetCompressedFetch()
+{
+ setError(Job::NoError);
+ setErrorString(QString());
+ m_unzipRepositoryitems.clear();
+
+ try {
foreach (QFutureWatcher<void> *const watcher, m_unzipTasks.keys()) {
watcher->cancel();
watcher->deleteLater();
@@ -286,20 +440,32 @@ void MetadataJob::reset()
foreach (QObject *const object, m_unzipTasks)
object->deleteLater();
m_unzipTasks.clear();
+
+ foreach (QFutureWatcher<void> *const watcher, m_unzipRepositoryTasks.keys()) {
+ watcher->cancel();
+ watcher->deleteLater();
+ }
+ foreach (QObject *const object, m_unzipRepositoryTasks)
+ object->deleteLater();
+ m_unzipRepositoryTasks.clear();
} catch (...) {}
- m_tempDirDeleter.releaseAndDeleteAll();
}
MetadataJob::Status MetadataJob::parseUpdatesXml(const QList<FileTaskResult> &results)
{
foreach (const FileTaskResult &result, results) {
- if (error() != KDJob::NoError)
+ if (error() != Job::NoError)
return XmlDownloadFailure;
+ //If repository is not found, target might be empty. Do not continue parsing the
+ //repository and do not prevent further repositories usage.
+ if (result.target().isEmpty()) {
+ continue;
+ }
Metadata metadata;
QTemporaryDir tmp(QDir::tempPath() + QLatin1String("/remoterepo-XXXXXX"));
if (!tmp.isValid()) {
- qDebug() << "Could not create unique temporary directory.";
+ qDebug() << "Cannot create unique temporary directory.";
return XmlDownloadFailure;
}
@@ -309,21 +475,22 @@ MetadataJob::Status MetadataJob::parseUpdatesXml(const QList<FileTaskResult> &re
QFile file(result.target());
if (!file.rename(metadata.directory + QLatin1String("/Updates.xml"))) {
- qDebug() << "Could not rename target to Updates.xml. Error:" << file.errorString();
+ qDebug() << "Cannot rename target to Updates.xml:" << file.errorString();
return XmlDownloadFailure;
}
if (!file.open(QIODevice::ReadOnly)) {
- qDebug() << "Could not open Updates.xml for reading. Error:" << file.errorString();
+ qDebug() << "Cannot open Updates.xml for reading:" << file.errorString();
return XmlDownloadFailure;
}
QString error;
QDomDocument doc;
if (!doc.setContent(&file, &error)) {
- qDebug() << QString::fromLatin1("Could not fetch a valid version of Updates.xml from "
- "repository: %1. Error: %2").arg(metadata.repository.displayname(), error);
- return XmlDownloadFailure;
+ qDebug().nospace() << "Cannot fetch a valid version of Updates.xml from repository "
+ << metadata.repository.displayname() << ": " << error;
+ //If there are other repositories, try to use those
+ continue;
}
file.close();
@@ -346,7 +513,7 @@ MetadataJob::Status MetadataJob::parseUpdatesXml(const QList<FileTaskResult> &re
for (int j = 0; j < c2.count(); ++j) {
if (c2.at(j).toElement().tagName() == scName)
packageName = c2.at(j).toElement().text();
- else if (c2.at(j).toElement().tagName() == scRemoteVersion)
+ else if (c2.at(j).toElement().tagName() == scVersion)
packageVersion = (online ? c2.at(j).toElement().text() : QString());
else if ((c2.at(j).toElement().tagName() == QLatin1String("SHA1")) && testCheckSum)
packageHash = c2.at(j).toElement().text();
@@ -408,12 +575,12 @@ MetadataJob::Status MetadataJob::parseUpdatesXml(const QList<FileTaskResult> &re
if (ProductKeyCheck::instance()->isValidRepository(newRepository)) {
// store the new repository and the one old it replaces
repositoryUpdates.insertMulti(action, qMakePair(newRepository, oldRepository));
- qDebug() << "Replace repository:" << oldRepository.displayname() << "with:"
+ qDebug() << "Replace repository" << oldRepository.displayname() << "with"
<< newRepository.displayname();
}
} else {
qDebug() << "Invalid additional repositories action set in Updates.xml fetched "
- "from:" << metadata.repository.displayname() << "Line:" << el.lineNumber();
+ "from" << metadata.repository.displayname() << "line:" << el.lineNumber();
}
}
}
@@ -441,7 +608,7 @@ MetadataJob::Status MetadataJob::parseUpdatesXml(const QList<FileTaskResult> &re
return XmlDownloadRetry;
}
} else if (s.updateDefaultRepositories(repositoryUpdates) == Settings::UpdatesApplied) {
- if (m_core->isUpdater() || m_core->isPackageManager())
+ if (m_core->isMaintainer())
m_core->writeMaintenanceConfigFiles();
QFile::remove(result.target());
return XmlDownloadRetry;
diff --git a/src/libs/installer/metadatajob.h b/src/libs/installer/metadatajob.h
index bf1c8f54a..c6d5ad353 100644
--- a/src/libs/installer/metadatajob.h
+++ b/src/libs/installer/metadatajob.h
@@ -31,7 +31,7 @@
#include "downloadfiletask.h"
#include "fileutils.h"
-#include "kdjob.h"
+#include "job.h"
#include "repository.h"
#include <QFutureWatcher>
@@ -46,7 +46,7 @@ struct Metadata
Repository repository;
};
-class INSTALLER_EXPORT MetadataJob : public KDJob
+class INSTALLER_EXPORT MetadataJob : public Job
{
Q_OBJECT
Q_DISABLE_COPY(MetadataJob)
@@ -64,6 +64,7 @@ public:
QList<Metadata> metadata() const { return m_metadata.values(); }
Repository repositoryForDirectory(const QString &directory) const;
void setPackageManagerCore(PackageManagerCore *core) { m_core = core; }
+ void addCompressedPackages(bool addCompressPackage) { m_addCompressedPackages = addCompressPackage;}
private slots:
void doStart();
@@ -73,9 +74,14 @@ private slots:
void unzipTaskFinished();
void metadataTaskFinished();
void progressChanged(int progress);
+ void setProgressTotalAmount(int maximum);
+ void unzipRepositoryTaskFinished();
+ void startXMLTask(const QList<FileTaskItem> items);
private:
+ void startUnzipRepositoryTask(const Repository &repo);
void reset();
+ void resetCompressedFetch();
Status parseUpdatesXml(const QList<FileTaskResult> &results);
private:
@@ -87,6 +93,9 @@ private:
QFutureWatcher<FileTaskResult> m_xmlTask;
QFutureWatcher<FileTaskResult> m_metadataTask;
QHash<QFutureWatcher<void> *, QObject*> m_unzipTasks;
+ QHash<QFutureWatcher<void> *, QObject*> m_unzipRepositoryTasks;
+ bool m_addCompressedPackages;
+ QList<FileTaskItem> m_unzipRepositoryitems;
};
} // namespace QInstaller
diff --git a/src/libs/installer/metadatajob_p.h b/src/libs/installer/metadatajob_p.h
index 34e23cd78..9160f4cc9 100644
--- a/src/libs/installer/metadatajob_p.h
+++ b/src/libs/installer/metadatajob_p.h
@@ -29,9 +29,13 @@
#ifndef METADATAJOB_P_H
#define METADATAJOB_P_H
+#include "lib7z_extract.h"
#include "lib7z_facade.h"
#include "metadatajob.h"
+#include <QDir>
+#include <QFile>
+
namespace QInstaller{
class UnzipArchiveException : public QException
@@ -60,7 +64,8 @@ public:
UnzipArchiveTask(const QString &arcive, const QString &target)
: m_archive(arcive), m_targetDir(target)
{}
-
+ QString target() { return m_targetDir; }
+ QString archive() { return m_archive; }
void doTask(QFutureInterface<void> &fi)
{
fi.reportStarted();
@@ -77,14 +82,14 @@ public:
Lib7z::extractArchive(&archive, m_targetDir);
} catch (const Lib7z::SevenZipException& e) {
fi.reportException(UnzipArchiveException(MetadataJob::tr("Error while extracting "
- "'%1': %2").arg(m_archive, e.message())));
+ "archive \"%1\": %2").arg(QDir::toNativeSeparators(m_archive), e.message())));
} catch (...) {
fi.reportException(UnzipArchiveException(MetadataJob::tr("Unknown exception "
- "caught while extracting %1.").arg(m_archive)));
+ "caught while extracting archive \"%1\".").arg(QDir::toNativeSeparators(m_archive))));
}
} else {
- fi.reportException(UnzipArchiveException(MetadataJob::tr("Could not open %1 for "
- "reading. Error: %2").arg(m_archive, archive.errorString())));
+ fi.reportException(UnzipArchiveException(MetadataJob::tr("Cannot open file \"%1\" for "
+ "reading: %2").arg(QDir::toNativeSeparators(m_archive), archive.errorString())));
}
fi.reportFinished();
diff --git a/src/libs/installer/minimumprogressoperation.cpp b/src/libs/installer/minimumprogressoperation.cpp
index 92762d3b1..5ae571a59 100644
--- a/src/libs/installer/minimumprogressoperation.cpp
+++ b/src/libs/installer/minimumprogressoperation.cpp
@@ -30,7 +30,8 @@
using namespace QInstaller;
-MinimumProgressOperation::MinimumProgressOperation()
+MinimumProgressOperation::MinimumProgressOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
// This shouldn't be callable by script, but we need a name for the binary format
setName(QLatin1String("MinimumProgress"));
@@ -56,9 +57,3 @@ bool MinimumProgressOperation::testOperation()
{
return true;
}
-
-Operation *MinimumProgressOperation::clone() const
-{
- return new MinimumProgressOperation();
-}
-
diff --git a/src/libs/installer/minimumprogressoperation.h b/src/libs/installer/minimumprogressoperation.h
index bfea8de72..4cdafca70 100644
--- a/src/libs/installer/minimumprogressoperation.h
+++ b/src/libs/installer/minimumprogressoperation.h
@@ -40,13 +40,12 @@ class MinimumProgressOperation : public QObject, public Operation
Q_OBJECT
public:
- MinimumProgressOperation();
+ explicit MinimumProgressOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
signals:
void progressChanged(double progress);
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index 8f492c06a..7b6842720 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -41,6 +41,7 @@
#include "qprocesswrapper.h"
#include "qsettingswrapper.h"
#include "remoteclient.h"
+#include "remotefileengine.h"
#include "settings.h"
#include "utils.h"
#include "installercalculator.h"
@@ -56,12 +57,16 @@
#include <QtCore/QRegExp>
#include <QtCore/QSettings>
#include <QtCore/QTemporaryFile>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTextDecoder>
+#include <QtCore/QTextEncoder>
+#include <QtCore/QTextStream>
#include <QDesktopServices>
#include <QFileDialog>
-#include "kdsysinfo.h"
-#include "kdupdaterupdateoperationfactory.h"
+#include "sysinfo.h"
+#include "updateoperationfactory.h"
#ifdef Q_OS_WIN
# include "qt_windows.h"
@@ -423,7 +428,7 @@ void PackageManagerCore::writeMaintenanceTool()
gainAdminRights();
gainedAdminRights = true;
}
- d->m_updaterApplication.packagesInfo()->writeToDisk();
+ d->m_localPackageHub->writeToDisk();
if (gainedAdminRights)
dropAdminRights();
d->m_needToWriteMaintenanceTool = false;
@@ -634,11 +639,11 @@ int PackageManagerCore::downloadNeededArchives(double partProgressSize)
DownloadArchivesJob archivesJob(this);
archivesJob.setAutoDelete(false);
archivesJob.setArchivesToDownload(archivesToDownload);
- connect(this, SIGNAL(installationInterrupted()), &archivesJob, SLOT(cancel()));
- connect(&archivesJob, SIGNAL(outputTextChanged(QString)), ProgressCoordinator::instance(),
- SLOT(emitLabelAndDetailTextChanged(QString)));
- connect(&archivesJob, SIGNAL(downloadStatusChanged(QString)), ProgressCoordinator::instance(),
- SIGNAL(downloadStatusChanged(QString)));
+ connect(this, &PackageManagerCore::installationInterrupted, &archivesJob, &Job::cancel);
+ connect(&archivesJob, &DownloadArchivesJob::outputTextChanged,
+ ProgressCoordinator::instance(), &ProgressCoordinator::emitLabelAndDetailTextChanged);
+ connect(&archivesJob, &DownloadArchivesJob::downloadStatusChanged,
+ ProgressCoordinator::instance(), &ProgressCoordinator::downloadStatusChanged);
ProgressCoordinator::instance()->registerPartProgress(&archivesJob,
SIGNAL(progressChanged(double)), partProgressSize);
@@ -646,13 +651,13 @@ int PackageManagerCore::downloadNeededArchives(double partProgressSize)
archivesJob.start();
archivesJob.waitForFinished();
- if (archivesJob.error() == KDJob::Canceled)
+ if (archivesJob.error() == Job::Canceled)
interrupt();
- else if (archivesJob.error() != KDJob::NoError)
+ else if (archivesJob.error() != Job::NoError)
throw Error(archivesJob.errorString());
if (d->statusCanceledOrFailed())
- throw Error(tr("Installation canceled by user"));
+ throw Error(tr("Installation canceled by user."));
ProgressCoordinator::instance()->emitDownloadStatus(tr("All downloads finished."));
@@ -701,7 +706,6 @@ void PackageManagerCore::rollBackInstallation()
}
}
- KDUpdater::PackagesInfo &packages = *d->m_updaterApplication.packagesInfo();
while (!d->m_performedOperationsCurrentSession.isEmpty()) {
try {
Operation *const operation = d->m_performedOperationsCurrentSession.takeLast();
@@ -728,14 +732,14 @@ void PackageManagerCore::rollBackInstallation()
component = d->componentsToReplace().value(componentName).second;
if (component) {
component->setUninstalled();
- packages.removePackage(component->name());
+ d->m_localPackageHub->removePackage(component->name());
}
}
- packages.writeToDisk();
+ d->m_localPackageHub->writeToDisk();
if (isInstaller()) {
- if (packages.packageInfoCount() == 0) {
- QFile file(packages.fileName());
+ if (d->m_localPackageHub->packageInfoCount() == 0) {
+ QFile file(d->m_localPackageHub->fileName());
file.remove();
}
}
@@ -745,7 +749,7 @@ void PackageManagerCore::rollBackInstallation()
} catch (const Error &e) {
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
QLatin1String("ElevationError"), tr("Authentication Error"), tr("Some components "
- "could not be removed completely because admin rights could not be acquired: %1.")
+ "could not be removed completely because administrative rights could not be acquired: %1.")
.arg(e.message()));
} catch (...) {
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), QLatin1String("unknown"),
@@ -781,6 +785,32 @@ bool PackageManagerCore::fileExists(const QString &filePath) const
return QFileInfo(filePath).exists();
}
+/*!
+ Returns the contents of the file \a filePath using the encoding specified
+ by \a codecName. The file is read in the text mode, that is, end-of-line
+ terminators are translated to the local encoding.
+
+ \note If the file does not exist or an error occurs while reading the file, an
+ empty string is returned.
+
+ \sa {installer::readFile}{installer.readFile}
+
+ */
+QString PackageManagerCore::readFile(const QString &filePath, const QString &codecName) const
+{
+ QFile f(filePath);
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
+ return QString();
+
+ QTextCodec *codec = QTextCodec::codecForName(qPrintable(codecName));
+ if (!codec)
+ return QString();
+
+ QTextStream stream(&f);
+ stream.setCodec(codec);
+ return stream.readAll();
+}
+
// -- QInstaller
/*!
@@ -820,6 +850,8 @@ PackageManagerCore::PackageManagerCore(qint64 magicmaker, const QList<OperationB
d->initialize(QHash<QString, QString>());
+ RemoteClient::instance().setAuthorizationFallbackDisabled(settings().disableAuthorizationFallback());
+
//
// Sanity check to detect a broken installations with missing operations.
// Every installed package should have at least one MinimalProgress operation.
@@ -849,6 +881,40 @@ PackageManagerCore::PackageManagerCore(qint64 magicmaker, const QList<OperationB
}
}
+class VerboseWriterAdminOutput : public VerboseWriterOutput
+{
+public:
+ VerboseWriterAdminOutput(PackageManagerCore *core) : m_core(core) {}
+
+ virtual bool write(const QString &fileName, QIODevice::OpenMode openMode, const QByteArray &data)
+ {
+ bool gainedAdminRights = false;
+
+ if (!RemoteClient::instance().isActive()) {
+ m_core->gainAdminRights();
+ gainedAdminRights = true;
+ }
+
+ RemoteFileEngine file;
+ file.setFileName(fileName);
+ if (file.open(openMode)) {
+ file.write(data.constData(), data.size());
+ file.close();
+ if (gainedAdminRights)
+ m_core->dropAdminRights();
+ return true;
+ }
+
+ if (gainedAdminRights)
+ m_core->dropAdminRights();
+
+ return false;
+ }
+
+private:
+ PackageManagerCore *m_core;
+};
+
/*!
Destroys the instance.
*/
@@ -862,8 +928,19 @@ PackageManagerCore::~PackageManagerCore()
}
delete d;
+ try {
+ PlainVerboseWriterOutput plainOutput;
+ if (!VerboseWriter::instance()->flush(&plainOutput)) {
+ VerboseWriterAdminOutput adminOutput(this);
+ VerboseWriter::instance()->flush(&adminOutput);
+ }
+ } catch (...) {
+ // Intentionally left blank; don't permit exceptions from VerboseWriter
+ // to escape destructor.
+ }
+
RemoteClient::instance().setActive(false);
- RemoteClient::instance().shutdown();
+ RemoteClient::instance().destroy();
QMutexLocker _(globalVirtualComponentsFontMutex());
delete sVirtualComponentsFont;
@@ -962,7 +1039,7 @@ bool PackageManagerCore::fetchLocalPackagesTree()
d->setStatus(Running);
if (!isPackageManager()) {
- d->setStatus(Failure, tr("Application not running in Package Manager mode!"));
+ d->setStatus(Failure, tr("Application not running in Package Manager mode."));
return false;
}
@@ -984,7 +1061,7 @@ bool PackageManagerCore::fetchLocalPackagesTree()
component->loadDataFromPackage(installedPackages.value(key));
const QString &name = component->name();
if (components.contains(name)) {
- qCritical("Could not register component! Component with identifier %s already registered.",
+ qCritical("Cannot register component! Component with identifier %s already registered.",
qPrintable(name));
continue;
}
@@ -1021,7 +1098,7 @@ void PackageManagerCore::networkSettingsChanged()
d->m_repoFetched = false;
d->m_updateSourcesAdded = false;
- if (d->isUpdater() || d->isPackageManager()) {
+ if (isMaintainer() ) {
bool gainedAdminRights = false;
QTemporaryFile tempAdminFile(d->targetDir() + QStringLiteral("/XXXXXX"));
if (!tempAdminFile.open() || !tempAdminFile.isWritable()) {
@@ -1032,6 +1109,7 @@ void PackageManagerCore::networkSettingsChanged()
if (gainedAdminRights)
dropAdminRights();
}
+
KDUpdater::FileDownloaderFactory::instance().setProxyFactory(proxyFactory());
emit coreNetworkSettingsChanged();
@@ -1071,15 +1149,44 @@ PackagesList PackageManagerCore::remotePackages()
}
/*!
+ Checks for compressed packages to install. Returns \c true if newer versions exist
+ and they can be installed.
+*/
+bool PackageManagerCore::fetchCompressedPackagesTree()
+{
+ const LocalPackagesHash installedPackages = d->localInstalledPackages();
+ if (!isInstaller() && status() == Failure)
+ return false;
+
+ if (!d->fetchMetaInformationFromCompressedRepositories())
+ return false;
+
+ if (!d->addUpdateResourcesFromRepositories(true, true)) {
+ return false;
+ }
+
+ PackagesList packages;
+ const PackagesList &compPackages = d->compressedPackages();
+ if (compPackages.isEmpty())
+ return false;
+ packages.append(compPackages);
+ const PackagesList &rPackages = d->remotePackages();
+ packages.append(rPackages);
+
+ return fetchPackagesTree(packages, installedPackages);
+}
+
+
+/*!
Checks for packages to install. Returns \c true if newer versions exist
- and they can be installed and sets the status of the update to \c Success.
+ and they can be installed.
*/
bool PackageManagerCore::fetchRemotePackagesTree()
{
d->setStatus(Running);
if (isUninstaller()) {
- d->setStatus(Failure, tr("Application running in Uninstaller mode!"));
+ d->setStatus(Failure, tr("Application running in Uninstaller mode."));
return false;
}
@@ -1095,6 +1202,9 @@ bool PackageManagerCore::fetchRemotePackagesTree()
if (!d->fetchMetaInformationFromRepositories())
return false;
+ if (!d->fetchMetaInformationFromCompressedRepositories())
+ return false;
+
if (!d->addUpdateResourcesFromRepositories(true))
return false;
@@ -1102,6 +1212,11 @@ bool PackageManagerCore::fetchRemotePackagesTree()
if (packages.isEmpty())
return false;
+ return fetchPackagesTree(packages, installedPackages);
+}
+
+bool PackageManagerCore::fetchPackagesTree(const PackagesList &packages, const LocalPackagesHash installedPackages) {
+
bool success = false;
if (!isUpdater()) {
success = fetchAllPackages(packages, installedPackages);
@@ -1115,7 +1230,7 @@ bool PackageManagerCore::fetchRemotePackagesTree()
}
const LocalPackage localPackage = installedPackages.value(name);
- const QString updateVersion = update->data(scRemoteVersion).toString();
+ const QString updateVersion = update->data(scVersion).toString();
if (KDUpdater::compareVersion(updateVersion, localPackage.version) <= 0)
break; // remote version equals or is less than the installed maintenance tool
@@ -1284,12 +1399,12 @@ void PackageManagerCore::addUserRepositories(const QStringList &repositories)
\sa {installer::setTemporaryRepositories}{installer.setTemporaryRepositories}
\sa addUserRepositories()
*/
-void PackageManagerCore::setTemporaryRepositories(const QStringList &repositories, bool replace)
+void PackageManagerCore::setTemporaryRepositories(const QStringList &repositories, bool replace,
+ bool compressed)
{
QSet<Repository> repositorySet;
foreach (const QString &repository, repositories)
- repositorySet.insert(Repository::fromUserInput(repository));
-
+ repositorySet.insert(Repository::fromUserInput(repository, compressed));
settings().setTemporaryRepositories(repositorySet, replace);
}
@@ -1513,6 +1628,52 @@ QList<Component*> PackageManagerCore::orderedComponentsToInstall() const
return d->installerCalculator()->orderedComponentsToInstall();
}
+bool PackageManagerCore::calculateComponents(QString *displayString)
+{
+ QString htmlOutput;
+ QString lastInstallReason;
+ if (!calculateComponentsToUninstall() ||
+ !calculateComponentsToInstall()) {
+ htmlOutput.append(QString::fromLatin1("<h2><font color=\"red\">%1</font></h2><ul>")
+ .arg(tr("Cannot resolve all dependencies.")));
+ //if we have a missing dependency or a recursion we can display it
+ if (!componentsToInstallError().isEmpty()) {
+ htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(
+ componentsToInstallError()));
+ }
+ htmlOutput.append(QLatin1String("</ul>"));
+ if (displayString)
+ *displayString = htmlOutput;
+ return false;
+ }
+
+ // In case of updater mode we don't uninstall components.
+ if (!isUpdater()) {
+ QList<Component*> componentsToRemove = componentsToUninstall();
+ if (!componentsToRemove.isEmpty()) {
+ htmlOutput.append(QString::fromLatin1("<h3>%1</h3><ul>").arg(tr("Components about to "
+ "be removed.")));
+ foreach (Component *component, componentsToRemove)
+ htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(component->name()));
+ htmlOutput.append(QLatin1String("</ul>"));
+ }
+ }
+
+ foreach (Component *component, orderedComponentsToInstall()) {
+ const QString reason = installReason(component);
+ if (lastInstallReason != reason) {
+ if (!lastInstallReason.isEmpty()) // means we had to close the previous list
+ htmlOutput.append(QLatin1String("</ul>"));
+ htmlOutput.append(QString::fromLatin1("<h3>%1</h3><ul>").arg(reason));
+ lastInstallReason = reason;
+ }
+ htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(component->name()));
+ }
+ if (displayString)
+ *displayString = htmlOutput;
+ return true;
+}
+
/*!
Calculates a list of components to uninstall based on the current run mode.
The aboutCalculateComponentsToUninstall() signal is emitted
@@ -1616,8 +1777,8 @@ ComponentModel *PackageManagerCore::defaultComponentModel() const
d->m_defaultModel = componentModel(const_cast<PackageManagerCore*> (this),
QLatin1String("AllComponentsModel"));
}
- connect(this, SIGNAL(finishAllComponentsReset(QList<QInstaller::Component*>)), d->m_defaultModel,
- SLOT(setRootComponents(QList<QInstaller::Component*>)));
+ connect(this, &PackageManagerCore::finishAllComponentsReset, d->m_defaultModel,
+ &ComponentModel::setRootComponents);
return d->m_defaultModel;
}
@@ -1631,11 +1792,70 @@ ComponentModel *PackageManagerCore::updaterComponentModel() const
d->m_updaterModel = componentModel(const_cast<PackageManagerCore*> (this),
QLatin1String("UpdaterComponentsModel"));
}
- connect(this, SIGNAL(finishUpdaterComponentsReset(QList<QInstaller::Component*>)), d->m_updaterModel,
- SLOT(setRootComponents(QList<QInstaller::Component*>)));
+ connect(this, &PackageManagerCore::finishUpdaterComponentsReset, d->m_updaterModel,
+ &ComponentModel::setRootComponents);
return d->m_updaterModel;
}
+void PackageManagerCore::updateComponentsSilently()
+{
+ //Check if there are processes running in the install
+ QStringList excludeFiles;
+ excludeFiles.append(maintenanceToolName());
+
+ QStringList runningProcesses = d->runningInstallerProcesses(excludeFiles);
+ if (!runningProcesses.isEmpty()) {
+ qDebug() << "Unable to update components. Please stop these processes: "
+ << runningProcesses << " and try again.";
+ return;
+ }
+
+ autoAcceptMessageBoxes();
+
+ //Prevent infinite loop if installation for some reason fails.
+ setMessageBoxAutomaticAnswer(QLatin1String("installationErrorWithRetry"), QMessageBox::Cancel);
+
+ fetchRemotePackagesTree();
+
+ const QList<QInstaller::Component*> componentList = components(
+ ComponentType::Root | ComponentType::Descendants);
+
+ if (componentList.count() == 0) {
+ qDebug() << "No updates available.";
+ } else {
+ // Check if essential components are available (essential components are disabled).
+ // If essential components are found, update first essential updates,
+ // restart installer and install rest of the updates.
+ bool essentialUpdatesFound = false;
+ foreach (Component *component, componentList) {
+ if (component->value(scEssential, scFalse).toLower() == scTrue)
+ essentialUpdatesFound = true;
+ }
+ if (!essentialUpdatesFound) {
+ //Mark all components to be updated
+ foreach (Component *comp, componentList) {
+ comp->setCheckState(Qt::Checked);
+ }
+ }
+ QString htmlOutput;
+ bool componentsOk = calculateComponents(&htmlOutput);
+ if (componentsOk) {
+ if (runPackageUpdater()) {
+ writeMaintenanceTool();
+ if (essentialUpdatesFound) {
+ qDebug() << "Essential components updated successfully.";
+ }
+ else {
+ qDebug() << "Components updated successfully.";
+ }
+ }
+ }
+ else {
+ qDebug() << htmlOutput;
+ }
+ }
+}
+
/*!
Returns the settings for the package manager.
*/
@@ -1700,20 +1920,21 @@ bool PackageManagerCore::killProcess(const QString &absoluteFilePath) const
processPath = QDir::cleanPath(processPath.replace(QLatin1Char('\\'), QLatin1Char('/')));
if (processPath == normalizedPath) {
- qDebug() << QString::fromLatin1("try to kill process: %1(%2)").arg(process.name).arg(process.id);
+ qDebug().nospace() << "try to kill process " << process.name << " (" << process.id << ")";
//to keep the ui responsible use QtConcurrent::run
QFutureWatcher<bool> futureWatcher;
const QFuture<bool> future = QtConcurrent::run(KDUpdater::killProcess, process, 30000);
QEventLoop loop;
- loop.connect(&futureWatcher, SIGNAL(finished()), SLOT(quit()), Qt::QueuedConnection);
+ connect(&futureWatcher, &QFutureWatcher<bool>::finished,
+ &loop, &QEventLoop::quit, Qt::QueuedConnection);
futureWatcher.setFuture(future);
if (!future.isFinished())
loop.exec();
- qDebug() << QString::fromLatin1("\"%1\" killed!").arg(process.name);
+ qDebug() << process.name << "killed!";
return future.result();
}
}
@@ -1757,6 +1978,12 @@ bool PackageManagerCore::localInstallerBinaryUsed()
\a stdIn is sent as standard input to the application.
+ \a stdInCodec is the name of the codec to use for converting the input string
+ into bytes to write to the standard input of the application.
+
+ \a stdOutCodec is the name of the codec to use for converting data written by the
+ application to standard output into a string.
+
Returns an empty array if the program could not be executed, otherwise
the output of command as the first item, and the return code as the second.
@@ -1766,7 +1993,7 @@ bool PackageManagerCore::localInstallerBinaryUsed()
\sa executeDetached()
*/
QList<QVariant> PackageManagerCore::execute(const QString &program, const QStringList &arguments,
- const QString &stdIn) const
+ const QString &stdIn, const QString &stdInCodec, const QString &stdOutCodec) const
{
QProcessWrapper process;
@@ -1783,13 +2010,23 @@ QList<QVariant> PackageManagerCore::execute(const QString &program, const QStrin
return QList< QVariant >();
if (!adjustedStdIn.isNull()) {
- process.write(adjustedStdIn.toLatin1());
+ QTextCodec *codec = QTextCodec::codecForName(qPrintable(stdInCodec));
+ if (!codec)
+ return QList<QVariant>();
+
+ QTextEncoder encoder(codec);
+ process.write(encoder.fromUnicode(adjustedStdIn));
process.closeWriteChannel();
}
process.waitForFinished(-1);
- return QList<QVariant>() << QString::fromLatin1(process.readAllStandardOutput()) << process.exitCode();
+ QTextCodec *codec = QTextCodec::codecForName(qPrintable(stdOutCodec));
+ if (!codec)
+ return QList<QVariant>();
+ return QList<QVariant>()
+ << QTextDecoder(codec).toUnicode(process.readAllStandardOutput())
+ << process.exitCode();
}
/*!
@@ -1864,14 +2101,7 @@ QString PackageManagerCore::environmentVariable(const QString &name) const
*/
bool PackageManagerCore::operationExists(const QString &name)
{
- static QSet<QString> existingOperations;
- if (existingOperations.contains(name))
- return true;
- QScopedPointer<Operation> op(KDUpdater::UpdateOperationFactory::instance().create(name));
- if (!op.data())
- return false;
- existingOperations.insert(name);
- return true;
+ return KDUpdater::UpdateOperationFactory::instance().containsProduct(name);
}
/*!
@@ -1883,7 +2113,7 @@ bool PackageManagerCore::operationExists(const QString &name)
*/
bool PackageManagerCore::performOperation(const QString &name, const QStringList &arguments)
{
- QScopedPointer<Operation> op(KDUpdater::UpdateOperationFactory::instance().create(name));
+ QScopedPointer<Operation> op(KDUpdater::UpdateOperationFactory::instance().create(name, this));
if (!op.data())
return false;
@@ -2260,6 +2490,14 @@ bool PackageManagerCore::isPackageManager() const
}
/*!
+ Returns \c true if it is a package manager or an updater.
+*/
+bool PackageManagerCore::isMaintainer() const
+{
+ return isPackageManager() || isUpdater();
+}
+
+/*!
Runs the installer. Returns \c true on success, \c false otherwise.
\sa {installer::runInstaller}{installer.runInstaller}
@@ -2308,7 +2546,7 @@ bool PackageManagerCore::run()
return d->runInstaller();
else if (isUninstaller())
return d->runUninstaller();
- else if (isPackageManager() || isUpdater())
+ else if (isMaintainer())
return d->runPackageUpdater();
return false;
}
@@ -2327,7 +2565,7 @@ bool PackageManagerCore::updateComponentData(struct Data &data, Component *compo
// check if we already added the component to the available components list
const QString name = data.package->data(scName).toString();
if (data.components->contains(name)) {
- qCritical("Could not register component! Component with identifier %s already registered.",
+ qCritical("Cannot register component! Component with identifier %s already registered.",
qPrintable(name));
return false;
}
@@ -2413,7 +2651,7 @@ void PackageManagerCore::storeReplacedComponents(QHash<QString, Component *> &co
// installer binary or the installed component list, just ignore it. This
// can happen when in installer mode and probably package manager mode too.
if (isUpdater())
- qWarning() << componentName << "- Does not exist in the repositories anymore.";
+ qDebug() << componentName << "- Does not exist in the repositories anymore.";
continue;
}
if (!componentToReplace && !d->componentsToReplace().contains(componentName)) {
@@ -2529,7 +2767,7 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
continue; // Update for not installed package found, skip it.
const LocalPackage &localPackage = locals.value(name);
- const QString updateVersion = update->data(scRemoteVersion).toString();
+ const QString updateVersion = update->data(scVersion).toString();
if (KDUpdater::compareVersion(updateVersion, localPackage.version) <= 0)
continue;
@@ -2650,7 +2888,7 @@ void PackageManagerCore::updateDisplayVersions(const QString &displayKey)
}
visited.clear();
const QString displayVersionRemote = findDisplayVersion(key, componentsHash,
- scRemoteVersion, visited);
+ scVersion, visited);
if (displayVersionRemote.isEmpty())
componentsHash.value(key)->setValue(displayKey, tr("invalid"));
else
@@ -2698,3 +2936,13 @@ ComponentModel *PackageManagerCore::componentModel(PackageManagerCore *core, con
return model;
}
+
+QStringList PackageManagerCore::filesForDelayedDeletion() const
+{
+ return d->m_filesForDelayedDeletion;
+}
+
+void PackageManagerCore::addFilesForDelayedDeletion(const QStringList &files)
+{
+ d->m_filesForDelayedDeletion.append(files);
+}
diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h
index dc24bb46c..2a235bd44 100644
--- a/src/libs/installer/packagemanagercore.h
+++ b/src/libs/installer/packagemanagercore.h
@@ -122,6 +122,7 @@ public:
PackagesList remotePackages();
bool fetchRemotePackagesTree();
+ bool fetchCompressedPackagesTree();
bool run();
void reset(const QHash<QString, QString> &params);
@@ -133,7 +134,9 @@ public:
Q_INVOKABLE bool localInstallerBinaryUsed();
Q_INVOKABLE QList<QVariant> execute(const QString &program,
- const QStringList &arguments = QStringList(), const QString &stdIn = QString()) const;
+ const QStringList &arguments = QStringList(), const QString &stdIn = QString(),
+ const QString &stdInCodec = QLatin1String("latin1"),
+ const QString &stdOutCodec = QLatin1String("latin1")) const;
Q_INVOKABLE bool executeDetached(const QString &program,
const QStringList &arguments = QStringList(),
const QString &workingDirectory = QString()) const;
@@ -174,8 +177,8 @@ public:
void setTestChecksum(bool test);
Q_INVOKABLE void addUserRepositories(const QStringList &repositories);
- Q_INVOKABLE void setTemporaryRepositories(const QStringList &repositories, bool replace = false);
-
+ Q_INVOKABLE void setTemporaryRepositories(const QStringList &repositories,
+ bool replace = false, bool compressed = false);
Q_INVOKABLE void autoAcceptMessageBoxes();
Q_INVOKABLE void autoRejectMessageBoxes();
Q_INVOKABLE void setMessageBoxAutomaticAnswer(const QString &identifier, int button);
@@ -184,6 +187,7 @@ public:
Q_INVOKABLE bool isFileExtensionRegistered(const QString &extension) const;
Q_INVOKABLE bool fileExists(const QString &filePath) const;
+ Q_INVOKABLE QString readFile(const QString &filePath, const QString &codecName) const;
public:
ScriptEngine *componentScriptEngine() const;
@@ -199,6 +203,7 @@ public:
Q_INVOKABLE bool calculateComponentsToInstall() const;
QList<Component*> orderedComponentsToInstall() const;
+ bool calculateComponents(QString *displayString);
Q_INVOKABLE bool calculateComponentsToUninstall() const;
QList<Component*> componentsToUninstall() const;
@@ -210,6 +215,7 @@ public:
ComponentModel *defaultComponentModel() const;
ComponentModel *updaterComponentModel() const;
+ void updateComponentsSilently();
// convenience
Q_INVOKABLE bool isInstaller() const;
@@ -224,6 +230,8 @@ public:
Q_INVOKABLE void setPackageManager();
Q_INVOKABLE bool isPackageManager() const;
+ bool isMaintainer() const;
+
bool isVerbose() const;
void setVerbose(bool on);
@@ -254,6 +262,9 @@ public:
void setNeedsHardRestart(bool needsHardRestart = true);
bool finishedWithSuccess() const;
+ QStringList filesForDelayedDeletion() const;
+ void addFilesForDelayedDeletion(const QStringList &files);
+
public Q_SLOTS:
bool runInstaller();
bool runUninstaller();
@@ -279,6 +290,7 @@ Q_SIGNALS:
void finishButtonClicked();
void metaJobProgress(int progress);
+ void metaJobTotalProgress(int progress);
void metaJobInfoMessage(const QString &message);
void startAllComponentsReset();
@@ -327,6 +339,8 @@ private:
ComponentModel *componentModel(PackageManagerCore *core, const QString &objectName) const;
QList<Component *> componentsMarkedForInstallation() const;
+ bool fetchPackagesTree(const PackagesList &packages, const LocalPackagesHash installedPackages);
+
private:
PackageManagerCorePrivate *const d;
friend class PackageManagerCorePrivate;
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index c0723d72c..fb802ef8b 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -49,13 +49,13 @@
#include "componentchecker.h"
#include "globals.h"
-#include "kdselfrestarter.h"
-#include "kdupdaterfiledownloaderfactory.h"
-#include "kdupdaterupdatesourcesinfo.h"
-#include "kdupdaterupdateoperationfactory.h"
+#include "selfrestarter.h"
+#include "filedownloaderfactory.h"
+#include "updateoperationfactory.h"
#include <productkeycheck.h>
+#include <QSettings>
#include <QtConcurrentRun>
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
@@ -92,9 +92,9 @@ public:
{
if (!m_operation)
return;
- qDebug() << QString::fromLatin1("%1 %2 operation: %3").arg(state, m_operation->value(
+ qDebug().noquote() << QString::fromLatin1("%1 %2 operation: %3").arg(state, m_operation->value(
QLatin1String("component")).toString(), m_operation->name());
- qDebug() << QString::fromLatin1("\t- arguments: %1").arg(m_operation->arguments()
+ qDebug().noquote() << QString::fromLatin1("\t- arguments: %1").arg(m_operation->arguments()
.join(QLatin1String(", ")));
}
~OperationTracer() {
@@ -151,6 +151,7 @@ static void deferredRename(const QString &oldName, const QString &newName, bool
.fileName()));
QTextStream batch(&f);
+ batch.setCodec("UTF-16");
batch << "Set fso = WScript.CreateObject(\"Scripting.FileSystemObject\")\n";
batch << "Set tmp = WScript.CreateObject(\"WScript.Shell\")\n";
batch << QString::fromLatin1("file = \"%1\"\n").arg(arguments[2]);
@@ -161,8 +162,16 @@ static void deferredRename(const QString &oldName, const QString &newName, bool
batch << " WScript.Sleep(1000)\n";
batch << "wend\n";
batch << QString::fromLatin1("fso.MoveFile \"%1\", file\n").arg(arguments[1]);
- if (restart)
- batch << QString::fromLatin1("tmp.exec \"%1 --updater\"\n").arg(arguments[2]);
+ if (restart) {
+ //Restart with same command line arguments as first executable
+ QStringList commandLineArguments = QCoreApplication::arguments();
+ batch << QString::fromLatin1("tmp.exec \"%1 --updater").arg(arguments[2]);
+ //Skip the first argument as that is executable itself
+ for (int i = 1; i < commandLineArguments.count(); i++) {
+ batch << QString::fromLatin1(" %1").arg(commandLineArguments.at(i));
+ }
+ batch << QString::fromLatin1("\"\n");
+ }
batch << "fso.DeleteFile(WScript.ScriptFullName)\n";
}
@@ -171,7 +180,7 @@ static void deferredRename(const QString &oldName, const QString &newName, bool
#else
QFile::remove(newName);
QFile::rename(oldName, newName);
- KDSelfRestarter::setRestartOnQuit(restart);
+ SelfRestarter::setRestartOnQuit(restart);
#endif
}
@@ -180,7 +189,8 @@ static void deferredRename(const QString &oldName, const QString &newName, bool
PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
: m_updateFinder(0)
- , m_updaterApplication(new DummyConfigurationInterface)
+ , m_compressedFinder(0)
+ , m_localPackageHub(std::make_shared<LocalPackageHub>())
, m_core(core)
, m_updates(false)
, m_repoFetched(false)
@@ -201,7 +211,8 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, qint64 magicInstallerMaker,
const QList<OperationBlob> &performedOperations)
: m_updateFinder(0)
- , m_updaterApplication(new DummyConfigurationInterface)
+ , m_compressedFinder(0)
+ , m_localPackageHub(std::make_shared<LocalPackageHub>())
, m_status(PackageManagerCore::Unfinished)
, m_needsHardRestart(false)
, m_testChecksum(false)
@@ -227,24 +238,27 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q
{
foreach (const OperationBlob &operation, performedOperations) {
QScopedPointer<QInstaller::Operation> op(KDUpdater::UpdateOperationFactory::instance()
- .create(operation.name));
+ .create(operation.name, core));
if (op.isNull()) {
- qWarning() << QString::fromLatin1("Failed to load unknown operation %1")
- .arg(operation.name);
+ qWarning() << "Failed to load unknown operation" << operation.name;
continue;
}
if (!op->fromXml(operation.xml)) {
- qWarning() << "Failed to load XML for operation:" << operation.name;
+ qWarning() << "Failed to load XML for operation" << operation.name;
continue;
}
m_performedOperationsOld.append(op.take());
}
- connect(this, SIGNAL(installationStarted()), m_core, SIGNAL(installationStarted()));
- connect(this, SIGNAL(installationFinished()), m_core, SIGNAL(installationFinished()));
- connect(this, SIGNAL(uninstallationStarted()), m_core, SIGNAL(uninstallationStarted()));
- connect(this, SIGNAL(uninstallationFinished()), m_core, SIGNAL(uninstallationFinished()));
+ connect(this, &PackageManagerCorePrivate::installationStarted,
+ m_core, &PackageManagerCore::installationStarted);
+ connect(this, &PackageManagerCorePrivate::installationFinished,
+ m_core, &PackageManagerCore::installationFinished);
+ connect(this, &PackageManagerCorePrivate::uninstallationStarted,
+ m_core, &PackageManagerCore::uninstallationStarted);
+ connect(this, &PackageManagerCorePrivate::uninstallationFinished,
+ m_core, &PackageManagerCore::uninstallationFinished);
}
PackageManagerCorePrivate::~PackageManagerCorePrivate()
@@ -306,7 +320,8 @@ bool PackageManagerCorePrivate::performOperationThreaded(Operation *operation, O
const QFuture<bool> future = QtConcurrent::run(runOperation, operation, type);
QEventLoop loop;
- loop.connect(&futureWatcher, SIGNAL(finished()), SLOT(quit()), Qt::QueuedConnection);
+ QObject::connect(&futureWatcher, &decltype(futureWatcher)::finished, &loop, &QEventLoop::quit,
+ Qt::QueuedConnection);
futureWatcher.setFuture(future);
if (!future.isFinished())
@@ -338,7 +353,7 @@ bool PackageManagerCorePrivate::buildComponentTree(QHash<QString, Component*> &c
return false;
// append all components to their respective parents
QHash<QString, Component*>::const_iterator it;
- for (it = components.begin(); it != components.end(); ++it) {
+ for (it = components.constBegin(); it != components.constEnd(); ++it) {
QString id = it.key();
QInstaller::Component *component = it.value();
while (!id.isEmpty() && component->parentComponent() == 0) {
@@ -390,7 +405,7 @@ bool PackageManagerCorePrivate::buildComponentTree(QHash<QString, Component*> &c
foreach (QInstaller::Component *component, components) {
const QStringList warnings = ComponentChecker::checkComponent(component);
foreach (const QString &warning, warnings)
- qCWarning(lcComponentChecker) << warning;
+ qCWarning(lcComponentChecker).noquote() << warning;
}
} catch (const Error &error) {
clearAllComponentLists();
@@ -408,7 +423,7 @@ bool PackageManagerCorePrivate::buildComponentTree(QHash<QString, Component*> &c
void PackageManagerCorePrivate::cleanUpComponentEnvironment()
{
// clean up registered (downloaded) data
- if (m_core->isUpdater() || m_core->isPackageManager())
+ if (m_core->isMaintainer())
BinaryFormatEngineHandler::instance()->clear();
// there could be still some references to already deleted components,
@@ -543,45 +558,38 @@ void PackageManagerCorePrivate::initialize(const QHash<QString, QString> &params
readMaintenanceConfigFiles(QCoreApplication::applicationDirPath());
#endif
}
+ processFilesForDelayedDeletion();
+ m_data.setDynamicPredefinedVariables();
+
+ disconnect(this, &PackageManagerCorePrivate::installationStarted,
+ ProgressCoordinator::instance(), &ProgressCoordinator::reset);
+ connect(this, &PackageManagerCorePrivate::installationStarted,
+ ProgressCoordinator::instance(), &ProgressCoordinator::reset);
+ disconnect(this, &PackageManagerCorePrivate::uninstallationStarted,
+ ProgressCoordinator::instance(), &ProgressCoordinator::reset);
+ connect(this, &PackageManagerCorePrivate::uninstallationStarted,
+ ProgressCoordinator::instance(), &ProgressCoordinator::reset);
- foreach (Operation *currentOperation, m_performedOperationsOld)
- currentOperation->setValue(QLatin1String("installer"), QVariant::fromValue(m_core));
-
- disconnect(this, SIGNAL(installationStarted()), ProgressCoordinator::instance(), SLOT(reset()));
- connect(this, SIGNAL(installationStarted()), ProgressCoordinator::instance(), SLOT(reset()));
- disconnect(this, SIGNAL(uninstallationStarted()), ProgressCoordinator::instance(), SLOT(reset()));
- connect(this, SIGNAL(uninstallationStarted()), ProgressCoordinator::instance(), SLOT(reset()));
-
- m_updaterApplication.updateSourcesInfo()->setFileName(QString());
- KDUpdater::PackagesInfo &packagesInfo = *m_updaterApplication.packagesInfo();
- packagesInfo.setFileName(componentsXmlPath());
+ if (!isInstaller())
+ m_localPackageHub->setFileName(componentsXmlPath());
- // Note: force overwriting the application name and version in case we run as installer. Both will be
- // set to wrong initial values if we install into an already existing installation. This can happen
- // if the components.xml path has not been changed, but name or version of the new installer.
- if (isInstaller() || packagesInfo.applicationName().isEmpty()) {
+ if (isInstaller() || m_localPackageHub->applicationName().isEmpty()) {
// TODO: this seems to be wrong, we should ask for ProductName defaulting to applicationName...
- packagesInfo.setApplicationName(m_data.settings().applicationName());
+ m_localPackageHub->setApplicationName(m_data.settings().applicationName());
}
- if (isInstaller() || packagesInfo.applicationVersion().isEmpty()) {
- packagesInfo.setApplicationVersion(QLatin1String(QUOTE(IFW_REPOSITORY_FORMAT_VERSION)));
- }
+ if (isInstaller() || m_localPackageHub->applicationVersion().isEmpty())
+ m_localPackageHub->setApplicationVersion(QLatin1String(QUOTE(IFW_REPOSITORY_FORMAT_VERSION)));
- if (isInstaller()) {
- // TODO: this seems to be wrong, we should ask for ProductName defaulting to applicationName...
- m_updaterApplication.addUpdateSource(m_data.settings().applicationName(),
- m_data.settings().applicationName(), QString(), QUrl(QLatin1String("resource://metadata/")), 0);
- m_updaterApplication.updateSourcesInfo()->setModified(false);
- }
+ if (isInstaller())
+ m_packageSources.insert(PackageSource(QUrl(QLatin1String("resource://metadata/")), 0));
m_metadataJob.disconnect();
m_metadataJob.setAutoDelete(false);
m_metadataJob.setPackageManagerCore(m_core);
- connect(&m_metadataJob, SIGNAL(infoMessage(KDJob*, QString)), this,
- SLOT(infoMessage(KDJob*, QString)));
- connect(&m_metadataJob, SIGNAL(progress(KDJob *, quint64, quint64)), this,
- SLOT(infoProgress(KDJob *, quint64, quint64)));
+ connect(&m_metadataJob, &Job::infoMessage, this, &PackageManagerCorePrivate::infoMessage);
+ connect(&m_metadataJob, &Job::progress, this, &PackageManagerCorePrivate::infoProgress);
+ connect(&m_metadataJob, &Job::totalProgress, this, &PackageManagerCorePrivate::totalProgress);
KDUpdater::FileDownloaderFactory::instance().setProxyFactory(m_core->proxyFactory());
}
@@ -651,7 +659,7 @@ QByteArray PackageManagerCorePrivate::replaceVariables(const QByteArray &ba) con
*/
Operation *PackageManagerCorePrivate::createOwnedOperation(const QString &type)
{
- m_ownedOperations.append(KDUpdater::UpdateOperationFactory::instance().create(type));
+ m_ownedOperations.append(KDUpdater::UpdateOperationFactory::instance().create(type, m_core));
return m_ownedOperations.last();
}
@@ -732,24 +740,30 @@ void PackageManagerCorePrivate::writeMaintenanceConfigFiles()
// write current state (variables) to the maintenance tool ini file
const QString iniPath = targetDir() + QLatin1Char('/') + m_data.settings().maintenanceToolIniFile();
- QVariantHash variables;
+ QVariantHash variables; // Do not change to QVariantMap! Breaks existing .ini files,
+ // cause the variant types do not match while restoring the variables from the file.
QSettingsWrapper cfg(iniPath, QSettingsWrapper::IniFormat);
foreach (const QString &key, m_data.keys()) {
- if (key != scRunProgramDescription && key != scRunProgram && key != scRunProgramArguments)
- variables.insert(key, m_data.value(key));
+ if (key == scRunProgramDescription || key == scRunProgram || key == scRunProgramArguments)
+ continue;
+ QVariant value = m_data.value(key);
+ if (value.canConvert(QVariant::String))
+ value = replacePath(value.toString(), targetDir(), QLatin1String(scRelocatable));
+ variables.insert(key, value);
}
cfg.setValue(QLatin1String("Variables"), variables);
- QVariantList repos;
+ QVariantList repos; // Do not change either!
foreach (const Repository &repo, m_data.settings().defaultRepositories())
repos.append(QVariant().fromValue(repo));
cfg.setValue(QLatin1String("DefaultRepositories"), repos);
- cfg.sync();
+ cfg.setValue(QLatin1String("FilesForDelayedDeletion"), m_filesForDelayedDeletion);
+ cfg.sync();
if (cfg.status() != QSettingsWrapper::NoError) {
const QString reason = cfg.status() == QSettingsWrapper::AccessError ? tr("Access error")
: tr("Format error");
- throw Error(tr("Could not write installer configuration to %1: %2").arg(iniPath, reason));
+ throw Error(tr("Cannot write installer configuration to %1: %2").arg(iniPath, reason));
}
QFile file(targetDir() + QLatin1Char('/') + QLatin1String("network.xml"));
@@ -794,17 +808,22 @@ void PackageManagerCorePrivate::readMaintenanceConfigFiles(const QString &target
{
QSettingsWrapper cfg(targetDir + QLatin1Char('/') + m_data.settings().maintenanceToolIniFile(),
QSettingsWrapper::IniFormat);
- const QVariantHash vars = cfg.value(QLatin1String("Variables")).toHash();
- for (QHash<QString, QVariant>::ConstIterator it = vars.constBegin(); it != vars.constEnd(); ++it)
- m_data.setValue(it.key(), it.value().toString());
-
+ const QVariantHash v = cfg.value(QLatin1String("Variables")).toHash(); // Do not change to
+ // QVariantMap! Breaks reading from existing .ini files, cause the variant types do not match.
+ for (QVariantHash::const_iterator it = v.constBegin(); it != v.constEnd(); ++it) {
+ m_data.setValue(it.key(), replacePath(it.value().toString(), QLatin1String(scRelocatable),
+ targetDir));
+ }
QSet<Repository> repos;
- const QVariantList variants = cfg.value(QLatin1String("DefaultRepositories")).toList();
+ const QVariantList variants = cfg.value(QLatin1String("DefaultRepositories"))
+ .toList(); // Do not change either!
foreach (const QVariant &variant, variants)
repos.insert(variant.value<Repository>());
if (!repos.isEmpty())
m_data.settings().setDefaultRepositories(repos);
+ m_filesForDelayedDeletion = cfg.value(QLatin1String("FilesForDelayedDeletion")).toStringList();
+
QFile file(targetDir + QLatin1String("/network.xml"));
if (!file.open(QIODevice::ReadOnly))
return;
@@ -1003,13 +1022,13 @@ void PackageManagerCorePrivate::writeMaintenanceToolBinary(QFile *const input, q
{
QFile dummy(resourcePath.filePath(QLatin1String("installer.dat")));
if (dummy.exists() && !dummy.remove()) {
- throw Error(tr("Could not remove data file '%1': %2").arg(dummy.fileName(),
+ throw Error(tr("Cannot remove data file \"%1\": %2").arg(dummy.fileName(),
dummy.errorString()));
}
}
if (!dataOut.rename(resourcePath.filePath(QLatin1String("installer.dat")))) {
- throw Error(tr("Could not write maintenance tool data to %1: %2").arg(out.fileName(),
+ throw Error(tr("Cannot write maintenance tool data to %1: %2").arg(out.fileName(),
out.errorString()));
}
dataOut.setAutoRemove(false);
@@ -1028,13 +1047,13 @@ void PackageManagerCorePrivate::writeMaintenanceToolBinary(QFile *const input, q
{
QFile dummy(maintenanceToolRenamedName);
if (dummy.exists() && !dummy.remove()) {
- throw Error(tr("Could not remove data file '%1': %2").arg(dummy.fileName(),
+ throw Error(tr("Cannot remove data file \"%1\": %2").arg(dummy.fileName(),
dummy.errorString()));
}
}
if (!out.copy(maintenanceToolRenamedName)) {
- throw Error(tr("Could not write maintenance tool to %1: %2").arg(maintenanceToolRenamedName,
+ throw Error(tr("Cannot write maintenance tool to \"%1\": %2").arg(maintenanceToolRenamedName,
out.errorString()));
}
@@ -1066,8 +1085,7 @@ void PackageManagerCorePrivate::writeMaintenanceToolBinaryData(QFileDevice *outp
file.remove(); // clear all possible leftovers
m_core->setValue(QString::fromLatin1("DefaultResourceReplacement"), QString());
} else {
- qWarning() << QString::fromLatin1("Could not replace default resource with '%1'.")
- .arg(newDefaultResource);
+ qWarning() << "Cannot replace default resource with" << QDir::toNativeSeparators(newDefaultResource);
}
}
@@ -1080,9 +1098,6 @@ void PackageManagerCorePrivate::writeMaintenanceToolBinaryData(QFileDevice *outp
const qint64 operationsStart = output->pos();
QInstaller::appendInt64(output, performedOperations.count());
foreach (Operation *operation, performedOperations) {
- // the installer can't be put into XML, remove it first
- operation->clearValue(QLatin1String("installer"));
-
QInstaller::appendString(output, operation->name());
QInstaller::appendString(output, operation->toXml().toString());
@@ -1258,17 +1273,17 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
if (!replacementBinary.remove()) {
// Is there anything more sensible we can do with this error? I think not. It's not serious
// enough for throwing / aborting the process.
- qDebug() << QString::fromLatin1("Could not remove installer base binary '%1' after updating "
- "the maintenance tool: %2").arg(installerBaseBinary, replacementBinary.errorString());
+ qDebug() << "Cannot remove installer base binary" << installerBaseBinary
+ << "after updating the maintenance tool:" << replacementBinary.errorString();
} else {
- qDebug() << QString::fromLatin1("Removed installer base binary '%1' after updating the "
- "maintenance tool.").arg(installerBaseBinary);
+ qDebug() << "Removed installer base binary" << installerBaseBinary
+ << "after updating the maintenance tool.";
}
m_installerBaseBinaryUnreplaced.clear();
} else if (!installerBaseBinary.isEmpty() && !QFileInfo(installerBaseBinary).exists()) {
- qWarning() << QString::fromLatin1("The current maintenance tool could not be "
- "updated. '%1' does not exist. Please fix the 'setInstallerBaseBinary(<temp_installer_base_"
- "binary_path>)' call in your script.").arg(installerBaseBinary);
+ qWarning() << "The current maintenance tool could not be updated." << installerBaseBinary
+ << "does not exist. Please fix the \"setInstallerBaseBinary(<temp_installer_base_"
+ "binary_path>)\" call in your script.";
}
QFile input;
@@ -1278,9 +1293,9 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
try {
if (isInstaller()) {
if (QFile::exists(dataFile)) {
- qWarning() << QString::fromLatin1("Found binary data file '%1' but "
+ qWarning() << "Found binary data file" << dataFile << "but "
"deliberately not used. Running as installer requires to read the "
- "resources from the application binary.").arg(dataFile);
+ "resources from the application binary.";
}
throw Error();
}
@@ -1329,12 +1344,12 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
QFile dummy(dataFile + QLatin1String(".new"));
if (dummy.exists() && !dummy.remove()) {
- throw Error(tr("Could not remove data file '%1': %2").arg(dummy.fileName(),
+ throw Error(tr("Cannot remove data file \"%1\": %2").arg(dummy.fileName(),
dummy.errorString()));
}
if (!file.rename(dataFile + QLatin1String(".new"))) {
- throw Error(tr("Could not write maintenance tool binary data to %1: %2")
+ throw Error(tr("Cannot write maintenance tool binary data to %1: %2")
.arg(file.fileName(), file.errorString()));
}
file.setAutoRemove(false);
@@ -1394,7 +1409,7 @@ QString PackageManagerCorePrivate::registerPath()
}
QString path = QLatin1String("HKEY_CURRENT_USER");
- if (m_data.value(QLatin1String("AllUsers"), scFalse).toString() == scTrue)
+ if (m_data.value(scAllUsers, scFalse).toString() == scTrue)
path = QLatin1String("HKEY_LOCAL_MACHINE");
return path + QLatin1String("\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\")
@@ -1486,14 +1501,13 @@ bool PackageManagerCorePrivate::runInstaller()
componentsInstallPartProgressSize = double(1);
// Force an update on the components xml as the install dir might have changed.
- KDUpdater::PackagesInfo &info = *m_updaterApplication.packagesInfo();
- info.setFileName(componentsXmlPath());
+ m_localPackageHub->setFileName(componentsXmlPath());
// Clear the packages as we might install into an already existing installation folder.
- info.clearPackageInfoList();
+ m_localPackageHub->clearPackageInfos();
// also update the application name, might be set from a script as well
- info.setApplicationName(m_data.value(QLatin1String("ProductName"),
+ m_localPackageHub->setApplicationName(m_data.value(QLatin1String("ProductName"),
m_data.settings().applicationName()).toString());
- info.setApplicationVersion(QLatin1String(QUOTE(IFW_REPOSITORY_FORMAT_VERSION)));
+ m_localPackageHub->setApplicationVersion(QLatin1String(QUOTE(IFW_REPOSITORY_FORMAT_VERSION)));
const int progressOperationCount = countProgressOperations(componentsToInstall)
// add one more operation as we support progress
@@ -1521,7 +1535,6 @@ bool PackageManagerCorePrivate::runInstaller()
binaryFile = resourcePath.filePath(QLatin1String("installer.dat"));
#endif
createRepo->setValue(QLatin1String("uninstall-only"), true);
- createRepo->setValue(QLatin1String("installer"), QVariant::fromValue(m_core));
createRepo->setArguments(QStringList() << binaryFile << target
+ QLatin1String("/repository"));
@@ -1862,7 +1875,7 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr
bool ignoreError = false;
bool ok = performOperationThreaded(operation);
while (!ok && !ignoreError && m_core->status() != PackageManagerCore::Canceled) {
- qDebug() << QString::fromLatin1("Operation '%1' with arguments: '%2' failed: %3")
+ qDebug() << QString::fromLatin1("Operation \"%1\" with arguments \"%2\" failed: %3")
.arg(operation->name(), operation->arguments().join(QLatin1String("; ")),
operation->errorString());
const QMessageBox::StandardButton button =
@@ -1900,7 +1913,7 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr
if (!component->stopProcessForUpdateRequests().isEmpty()) {
Operation *stopProcessForUpdatesOp = KDUpdater::UpdateOperationFactory::instance()
- .create(QLatin1String("FakeStopProcessForUpdate"));
+ .create(QLatin1String("FakeStopProcessForUpdate"), m_core);
const QStringList arguments(component->stopProcessForUpdateRequests().join(QLatin1String(",")));
stopProcessForUpdatesOp->setArguments(arguments);
addPerformed(stopProcessForUpdatesOp);
@@ -1908,12 +1921,18 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr
}
// now mark the component as installed
- KDUpdater::PackagesInfo &packages = *m_updaterApplication.packagesInfo();
- packages.installPackage(component->name(), component->value(scVersion), component->value(scDisplayName),
- component->value(scDescription), component->dependencies(), component->forcedInstallation(),
- component->isVirtual(), component->value(scUncompressedSize).toULongLong(),
- component->value(scInheritVersion));
- packages.writeToDisk();
+ m_localPackageHub->addPackage(component->name(),
+ component->value(scVersion),
+ component->value(scDisplayName),
+ component->value(scDescription),
+ component->dependencies(),
+ component->autoDependencies(),
+ component->forcedInstallation(),
+ component->isVirtual(),
+ component->value(scUncompressedSize).toULongLong(),
+ component->value(scInheritVersion),
+ component->isCheckable());
+ m_localPackageHub->writeToDisk();
component->setInstalled();
component->markAsPerformedInstallation();
@@ -2018,7 +2037,13 @@ void PackageManagerCorePrivate::registerMaintenanceTool()
const quint64 limit = std::numeric_limits<quint32>::max(); // maximum 32 bit value
if (estimatedSizeKB <= limit)
settings.setValue(QLatin1String("EstimatedSize"), static_cast<quint32>(estimatedSizeKB));
- settings.setValue(QLatin1String("NoModify"), 0);
+
+ const bool supportsModify = m_core->value(scSupportsModify, scTrue) == scTrue;
+ if (supportsModify)
+ settings.setValue(QLatin1String("NoModify"), 0);
+ else
+ settings.setValue(QLatin1String("NoModify"), 1);
+
settings.setValue(QLatin1String("NoRepair"), 1);
#endif
}
@@ -2034,7 +2059,6 @@ void PackageManagerCorePrivate::unregisterMaintenanceTool()
void PackageManagerCorePrivate::runUndoOperations(const OperationList &undoOperations, double progressSize,
bool adminRightsGained, bool deleteOperation)
{
- KDUpdater::PackagesInfo &packages = *m_updaterApplication.packagesInfo();
try {
foreach (Operation *undoOperation, undoOperations) {
if (statusCanceledOrFailed())
@@ -2070,7 +2094,7 @@ void PackageManagerCorePrivate::runUndoOperations(const OperationList &undoOpera
component = componentsToReplace().value(componentName).second;
if (component) {
component->setUninstalled();
- packages.removePackage(component->name());
+ m_localPackageHub->removePackage(component->name());
}
}
@@ -2081,13 +2105,13 @@ void PackageManagerCorePrivate::runUndoOperations(const OperationList &undoOpera
delete undoOperation;
}
} catch (const Error &error) {
- packages.writeToDisk();
+ m_localPackageHub->writeToDisk();
throw Error(error.message());
} catch (...) {
- packages.writeToDisk();
+ m_localPackageHub->writeToDisk();
throw Error(tr("Unknown error"));
}
- packages.writeToDisk();
+ m_localPackageHub->writeToDisk();
}
PackagesList PackageManagerCorePrivate::remotePackages()
@@ -2098,12 +2122,14 @@ PackagesList PackageManagerCorePrivate::remotePackages()
m_updates = false;
delete m_updateFinder;
- m_updateFinder = new KDUpdater::UpdateFinder(&m_updaterApplication);
+ m_updateFinder = new KDUpdater::UpdateFinder;
m_updateFinder->setAutoDelete(false);
+ m_updateFinder->setPackageSources(m_packageSources);
+ m_updateFinder->setLocalPackageHub(m_localPackageHub);
m_updateFinder->run();
if (m_updateFinder->updates().isEmpty()) {
- setStatus(PackageManagerCore::Failure, tr("Could not retrieve remote tree: %1.")
+ setStatus(PackageManagerCore::Failure, tr("Cannot retrieve remote tree %1.")
.arg(m_updateFinder->errorString()));
return PackagesList();
}
@@ -2112,6 +2138,29 @@ PackagesList PackageManagerCorePrivate::remotePackages()
return m_updateFinder->updates();
}
+PackagesList PackageManagerCorePrivate::compressedPackages()
+{
+ if (m_compressedUpdates && m_compressedFinder)
+ return m_compressedFinder->updates();
+ m_compressedUpdates = false;
+ delete m_compressedFinder;
+
+ m_compressedFinder = new KDUpdater::UpdateFinder;
+ m_compressedFinder->setAutoDelete(false);
+ m_compressedFinder->addCompressedPackage(true);
+ m_compressedFinder->setPackageSources(m_compressedPackageSources);
+
+ m_compressedFinder->setLocalPackageHub(m_localPackageHub);
+ m_compressedFinder->run();
+ if (m_compressedFinder->updates().isEmpty()) {
+ setStatus(PackageManagerCore::Failure, tr("Cannot retrieve remote tree %1.")
+ .arg(m_compressedFinder->errorString()));
+ return PackagesList();
+ }
+ m_compressedUpdates = true;
+ return m_compressedFinder->updates();
+}
+
/*!
Returns a hash containing the installed package name and it's associated package information. If
the application is running in installer mode or the local components file could not be parsed, the
@@ -2119,27 +2168,32 @@ PackagesList PackageManagerCorePrivate::remotePackages()
*/
LocalPackagesHash PackageManagerCorePrivate::localInstalledPackages()
{
+ if (isInstaller())
+ return LocalPackagesHash();
+
LocalPackagesHash installedPackages;
+ if (m_localPackageHub->error() != LocalPackageHub::NoError) {
+ if (m_localPackageHub->fileName().isEmpty())
+ m_localPackageHub->setFileName(componentsXmlPath());
+ else
+ m_localPackageHub->refresh();
- if (!isInstaller()) {
- KDUpdater::PackagesInfo &packagesInfo = *m_updaterApplication.packagesInfo();
- if (!packagesInfo.isValid()) {
- packagesInfo.setFileName(componentsXmlPath());
- if (packagesInfo.applicationName().isEmpty())
- packagesInfo.setApplicationName(m_data.settings().applicationName());
- if (packagesInfo.applicationVersion().isEmpty())
- packagesInfo.setApplicationVersion(QLatin1String(QUOTE(IFW_REPOSITORY_FORMAT_VERSION)));
- }
+ if (m_localPackageHub->applicationName().isEmpty())
+ m_localPackageHub->setApplicationName(m_data.settings().applicationName());
+ if (m_localPackageHub->applicationVersion().isEmpty())
+ m_localPackageHub->setApplicationVersion(QLatin1String(QUOTE(IFW_REPOSITORY_FORMAT_VERSION)));
+ }
- if (packagesInfo.error() != KDUpdater::PackagesInfo::NoError)
- setStatus(PackageManagerCore::Failure, tr("Failure to read packages from: %1.").arg(componentsXmlPath()));
+ if (m_localPackageHub->error() != LocalPackageHub::NoError) {
+ setStatus(PackageManagerCore::Failure, tr("Failure to read packages from %1.")
+ .arg(componentsXmlPath()));
+ }
- foreach (const LocalPackage &package, packagesInfo.packageInfos()) {
- if (statusCanceledOrFailed())
- break;
- installedPackages.insert(package.name, package);
- }
- }
+ foreach (const LocalPackage &package, m_localPackageHub->packageInfos()) {
+ if (statusCanceledOrFailed())
+ break;
+ installedPackages.insert(package.name, package);
+ }
return installedPackages;
}
@@ -2157,12 +2211,12 @@ bool PackageManagerCorePrivate::fetchMetaInformationFromRepositories()
m_metadataJob.start();
m_metadataJob.waitForFinished();
} catch (Error &error) {
- setStatus(PackageManagerCore::Failure, tr("Could not retrieve meta information: %1")
+ setStatus(PackageManagerCore::Failure, tr("Cannot retrieve meta information: %1")
.arg(error.message()));
return m_repoFetched;
}
- if (m_metadataJob.error() != KDJob::NoError) {
+ if (m_metadataJob.error() != Job::NoError) {
switch (m_metadataJob.error()) {
case QInstaller::UserIgnoreError:
break; // we can simply ignore this error, the user knows about it
@@ -2176,9 +2230,46 @@ bool PackageManagerCorePrivate::fetchMetaInformationFromRepositories()
return m_repoFetched;
}
-bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChecksum)
+bool PackageManagerCorePrivate::fetchMetaInformationFromCompressedRepositories()
+{
+ bool compressedRepoFetched = false;
+
+ m_compressedUpdates = false;
+ m_updateSourcesAdded = false;
+
+ try {
+ //Tell MetadataJob that only compressed packages needed to be fetched and not all.
+ //We cannot do this in general fetch meta method as the compressed packages might be
+ //installed after components tree is generated
+ m_metadataJob.addCompressedPackages(true);
+ m_metadataJob.start();
+ m_metadataJob.waitForFinished();
+ m_metadataJob.addCompressedPackages(false);
+ } catch (Error &error) {
+ setStatus(PackageManagerCore::Failure, tr("Cannot retrieve meta information: %1")
+ .arg(error.message()));
+ return compressedRepoFetched;
+ }
+
+ if (m_metadataJob.error() != Job::NoError) {
+ switch (m_metadataJob.error()) {
+ case QInstaller::UserIgnoreError:
+ break; // we can simply ignore this error, the user knows about it
+ default:
+ //Do not change core status here, we can recover if there is invalid
+ //compressed repository
+ setStatus(m_core->status(), m_metadataJob.errorString());
+ return compressedRepoFetched;
+ }
+ }
+
+ compressedRepoFetched = true;
+ return compressedRepoFetched;
+}
+
+bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChecksum, bool compressedRepository)
{
- if (m_updateSourcesAdded)
+ if (!compressedRepository && m_updateSourcesAdded)
return m_updateSourcesAdded;
const QList<Metadata> metadata = m_metadataJob.metadata();
@@ -2186,21 +2277,21 @@ bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChe
m_updateSourcesAdded = true;
return m_updateSourcesAdded;
}
-
- // forces an refresh / clear on all update sources
- m_updaterApplication.updateSourcesInfo()->refresh();
- if (isInstaller()) {
- m_updaterApplication.addUpdateSource(m_data.settings().applicationName(),
- m_data.settings().applicationName(), QString(),
- QUrl(QLatin1String("resource://metadata/")), 0);
- m_updaterApplication.updateSourcesInfo()->setModified(false);
+ if (compressedRepository) {
+ m_compressedPackageSources.clear();
+ }
+ else {
+ m_packageSources.clear();
+ m_updates = false;
+ m_updateSourcesAdded = false;
+ if (isInstaller())
+ m_packageSources.insert(PackageSource(QUrl(QLatin1String("resource://metadata/")), 0));
}
- m_updates = false;
- m_updateSourcesAdded = false;
-
- const QString &appName = m_data.settings().applicationName();
foreach (const Metadata &data, metadata) {
+ if (compressedRepository && !data.repository.isCompressed()) {
+ continue;
+ }
if (statusCanceledOrFailed())
return false;
@@ -2214,7 +2305,7 @@ bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChe
QInstaller::openForRead(&updatesFile);
} catch(const Error &e) {
qDebug() << "Error opening Updates.xml:" << e.message();
- setStatus(PackageManagerCore::Failure, tr("Could not add temporary update source information."));
+ setStatus(PackageManagerCore::Failure, tr("Cannot add temporary update source information."));
return false;
}
@@ -2223,9 +2314,9 @@ bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChe
QString error;
QDomDocument doc;
if (!doc.setContent(&updatesFile, &error, &line, &column)) {
- qDebug() << QString::fromLatin1("Parse error in file %4: %1 at line %2 col %3").arg(error,
- QString::number(line), QString::number(column), updatesFile.fileName());
- setStatus(PackageManagerCore::Failure, tr("Could not add temporary update source information."));
+ qDebug().nospace() << "Parse error in file" << updatesFile.fileName()
+ << ": " << error << " at line " << line << " col " << column;
+ setStatus(PackageManagerCore::Failure, tr("Cannot add temporary update source information."));
return false;
}
@@ -2233,14 +2324,16 @@ bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChe
if (!checksum.isNull())
m_core->setTestChecksum(checksum.toElement().text().toLower() == scTrue);
}
- m_updaterApplication.addUpdateSource(appName, appName, QString(),
- QUrl::fromLocalFile(data.directory), 1);
+ if (compressedRepository)
+ m_compressedPackageSources.insert(PackageSource(QUrl::fromLocalFile(data.directory), 1));
+ else
+ m_packageSources.insert(PackageSource(QUrl::fromLocalFile(data.directory), 1));
+
ProductKeyCheck::instance()->addPackagesFromXml(data.directory + QLatin1String("/Updates.xml"));
}
- m_updaterApplication.updateSourcesInfo()->setModified(false);
-
- if (m_updaterApplication.updateSourcesInfo()->updateSourceInfoCount() == 0) {
- setStatus(PackageManagerCore::Failure, tr("Could not find any update source information."));
+ if ((compressedRepository && m_compressedPackageSources.count() == 0 ) ||
+ (!compressedRepository && m_packageSources.count() == 0)) {
+ setStatus(PackageManagerCore::Failure, tr("Cannot find any update source information."));
return false;
}
@@ -2292,25 +2385,20 @@ OperationList PackageManagerCorePrivate::sortOperationsBasedOnComponentDependenc
const QString componentName = operation->value(QLatin1String("component")).toString();
if (componentName.isEmpty())
sortedOperations.append(operation);
- else {
- OperationList componentOperationList = componentOperationHash.value(componentName);
- componentOperationList.append(operation);
- componentOperationHash.insert(operation->value(QLatin1String("component")).toString(),
- componentOperationList);
- }
+ else
+ componentOperationHash[componentName].append(operation);
}
- const QString empty;
const QRegExp dash(QLatin1String("-.*"));
Graph<QString> componentGraph; // create the complete component graph
foreach (const Component* node, m_core->components(PackageManagerCore::ComponentType::All)) {
componentGraph.addNode(node->name());
- componentGraph.addEdges(node->name(), node->dependencies().replaceInStrings(dash, empty));
+ componentGraph.addEdges(node->name(), node->dependencies().replaceInStrings(dash, QString()));
}
const QStringList resolvedComponents = componentGraph.sort();
if (componentGraph.hasCycle()) {
- throw Error(tr("Dependency cycle between components detected: '%1' and '%2'.")
+ throw Error(tr("Dependency cycle between components \"%1\" and \"%2\" detected.")
.arg(componentGraph.cycle().first, componentGraph.cycle().second));
}
foreach (const QString &componentName, resolvedComponents)
@@ -2326,4 +2414,44 @@ void PackageManagerCorePrivate::handleMethodInvocationRequest(const QString &inv
QMetaObject::invokeMethod(obj, qPrintable(invokableMethodName));
}
+void PackageManagerCorePrivate::processFilesForDelayedDeletion()
+{
+ if (m_filesForDelayedDeletion.isEmpty())
+ return;
+
+ const QStringList filesForDelayedDeletion = std::move(m_filesForDelayedDeletion);
+ foreach (const QString &i, filesForDelayedDeletion) {
+ QFile file(i); //TODO: this should happen asnyc and report errors, I guess
+ if (file.exists() && !file.remove()) {
+ qWarning("Cannot delete file %s: %s", qPrintable(i),
+ qPrintable(file.errorString()));
+ m_filesForDelayedDeletion << i; // try again next time
+ }
+ }
+}
+
+void PackageManagerCorePrivate::findExecutablesRecursive(const QString &path, const QStringList &excludeFiles, QStringList *result)
+{
+ QString executable;
+ QDirIterator it(path, QDir::NoDotAndDotDot | QDir::Executable | QDir::Files | QDir::System, QDirIterator::Subdirectories );
+
+ while (it.hasNext()) {
+ executable = it.next();
+ foreach (QString exclude, excludeFiles) {
+ if (QDir::toNativeSeparators(executable.toLower())
+ != QDir::toNativeSeparators(exclude.toLower())) {
+ result->append(executable);
+ }
+ }
+ }
+}
+
+QStringList PackageManagerCorePrivate::runningInstallerProcesses(const QStringList &excludeFiles)
+{
+ QStringList resultFiles;
+ findExecutablesRecursive(QCoreApplication::applicationDirPath(), excludeFiles, &resultFiles);
+ return checkRunningProcessesFromList(resultFiles);
+}
+
+
} // namespace QInstaller
diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h
index 663bb19bd..21ab3fc40 100644
--- a/src/libs/installer/packagemanagercore_p.h
+++ b/src/libs/installer/packagemanagercore_p.h
@@ -33,15 +33,15 @@
#include "packagemanagercore.h"
#include "packagemanagercoredata.h"
#include "packagemanagerproxyfactory.h"
+#include "packagesource.h"
#include "qinstallerglobal.h"
-#include "kdsysinfo.h"
-#include "kdupdaterapplication.h"
-#include "kdupdaterupdatefinder.h"
+#include "sysinfo.h"
+#include "updatefinder.h"
#include <QObject>
-class KDJob;
+class Job;
QT_FORWARD_DECLARE_CLASS(QFile)
QT_FORWARD_DECLARE_CLASS(QFileDevice)
@@ -60,27 +60,6 @@ class InstallerCalculator;
class UninstallerCalculator;
class RemoteFileEngineHandler;
-/*
- The default configuration interface implementation does call QSettings to save files for later deletion,
- though according to QSettings there should nothing be written if QSettings is not setup properly (which
- we do not in our case). Still, caused by a broken QSettings implementation at least on Linux we write an
- empty config file which resulted in QTIFW-196. To workaround the issue we now use this empty dummy class.
-*/
-class DummyConfigurationInterface : public KDUpdater::ConfigurationInterface
-{
-public:
- QVariant value(const QString &key) const
- {
- Q_UNUSED(key)
- return QVariant();
- }
- void setValue(const QString &key, const QVariant &value)
- {
- if (value.isNull())
- qDebug() << "DummyConfigurationInterface called with key:" << key << "and value:" << value;
- }
-};
-
class PackageManagerCorePrivate : public QObject
{
Q_OBJECT
@@ -191,7 +170,11 @@ signals:
public:
UpdateFinder *m_updateFinder;
- Application m_updaterApplication;
+ UpdateFinder *m_compressedFinder;
+ QSet<PackageSource> m_packageSources;
+ QSet<PackageSource> m_compressedPackageSources;
+ std::shared_ptr<LocalPackageHub> m_localPackageHub;
+ QStringList m_filesForDelayedDeletion;
int m_status;
QString m_error;
@@ -219,13 +202,17 @@ public:
bool m_dependsOnLocalInstallerBinary;
private slots:
- void infoMessage(KDJob *, const QString &message) {
+ void infoMessage(Job *, const QString &message) {
emit m_core->metaJobInfoMessage(message);
}
- void infoProgress(KDJob *, quint64 progress, quint64) {
+ void infoProgress(Job *, quint64 progress, quint64) {
emit m_core->metaJobProgress(progress);
}
+ void totalProgress(quint64 total) {
+ emit m_core->metaJobTotalProgress(total);
+ }
+
void handleMethodInvocationRequest(const QString &invokableMethodName);
private:
@@ -241,15 +228,21 @@ private:
bool adminRightsGained, bool deleteOperation);
PackagesList remotePackages();
+ PackagesList compressedPackages();
LocalPackagesHash localInstalledPackages();
bool fetchMetaInformationFromRepositories();
- bool addUpdateResourcesFromRepositories(bool parseChecksum);
+ bool fetchMetaInformationFromCompressedRepositories();
+ bool addUpdateResourcesFromRepositories(bool parseChecksum, bool compressedRepository = false);
+ void processFilesForDelayedDeletion();
+ void findExecutablesRecursive(const QString &path, const QStringList &excludeFiles, QStringList *result);
+ QStringList runningInstallerProcesses(const QStringList &exludeFiles);
private:
PackageManagerCore *m_core;
MetadataJob m_metadataJob;
bool m_updates;
+ bool m_compressedUpdates;
bool m_repoFetched;
bool m_updateSourcesAdded;
qint64 m_magicBinaryMarker;
diff --git a/src/libs/installer/packagemanagercoredata.cpp b/src/libs/installer/packagemanagercoredata.cpp
index 2a92a468e..3b35794cf 100644
--- a/src/libs/installer/packagemanagercoredata.cpp
+++ b/src/libs/installer/packagemanagercoredata.cpp
@@ -47,27 +47,14 @@ namespace QInstaller
PackageManagerCoreData::PackageManagerCoreData(const QHash<QString, QString> &variables)
{
m_variables = variables;
+ setDynamicPredefinedVariables();
// Set some common variables that may used e.g. as placeholder in some of the settings variables or
// in a script or...
- m_variables.insert(QLatin1String("rootDir"), QDir::rootPath());
- m_variables.insert(QLatin1String("homeDir"), QDir::homePath());
- m_variables.insert(QLatin1String("RootDir"), QDir::rootPath());
- m_variables.insert(QLatin1String("HomeDir"), QDir::homePath());
m_variables.insert(scTargetConfigurationFile, QLatin1String("components.xml"));
m_variables.insert(QLatin1String("InstallerDirPath"), QCoreApplication::applicationDirPath());
m_variables.insert(QLatin1String("InstallerFilePath"), QCoreApplication::applicationFilePath());
- QString dir = QLatin1String("/opt");
-#ifdef Q_OS_WIN
- TCHAR buffer[MAX_PATH + 1] = { 0 };
- SHGetFolderPath(0, CSIDL_PROGRAM_FILES, 0, 0, buffer);
- dir = QString::fromWCharArray(buffer);
-#elif defined (Q_OS_OSX)
- dir = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).value(0);
-#endif
- m_variables.insert(QLatin1String("ApplicationsDir"), dir);
-
#ifdef Q_OS_WIN
m_variables.insert(QLatin1String("os"), QLatin1String("win"));
#elif defined(Q_OS_OSX)
@@ -78,26 +65,6 @@ PackageManagerCoreData::PackageManagerCoreData(const QHash<QString, QString> &va
// TODO: add more platforms as needed...
#endif
-#ifdef Q_OS_WIN
- QSettingsWrapper user(QLatin1String("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\"
- "CurrentVersion\\Explorer\\User Shell Folders"), QSettingsWrapper::NativeFormat);
- QSettingsWrapper system(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\"
- "CurrentVersion\\Explorer\\Shell Folders"), QSettingsWrapper::NativeFormat);
-
- const QString programs = user.value(QLatin1String("Programs"), QString()).toString();
- const QString allPrograms = system.value(QLatin1String("Common Programs"), QString()).toString();
-
- QString desktop;
- if (m_variables.value(QLatin1String("AllUsers")) == scTrue) {
- desktop = system.value(QLatin1String("Desktop")).toString();
- } else {
- desktop = user.value(QLatin1String("Desktop")).toString();
- }
- m_variables.insert(QLatin1String("DesktopDir"), replaceWindowsEnvironmentVariables(desktop));
- m_variables.insert(QLatin1String("UserStartMenuProgramsPath"), replaceWindowsEnvironmentVariables(programs));
- m_variables.insert(QLatin1String("AllUsersStartMenuProgramsPath"), replaceWindowsEnvironmentVariables(allPrograms));
-#endif
-
m_settings = Settings::fromFileAndPrefix(QLatin1String(":/metadata/installer-config/config.xml"),
QLatin1String(":/metadata/installer-config/"), Settings::RelaxedParseMode);
@@ -127,12 +94,81 @@ void PackageManagerCoreData::clear()
m_settings = Settings();
}
+/*!
+ Set some common variables that may be used e.g. as placeholder in some of the settings
+ variables or in a script or...
+*/
+void PackageManagerCoreData::setDynamicPredefinedVariables()
+{
+ m_variables.insert(QLatin1String("rootDir"), QDir::rootPath());
+ m_variables.insert(QLatin1String("homeDir"), QDir::homePath());
+ m_variables.insert(QLatin1String("RootDir"), QDir::rootPath());
+ m_variables.insert(QLatin1String("HomeDir"), QDir::homePath());
+
+ QString dir = QLatin1String("/opt");
+#ifdef Q_OS_WIN
+ TCHAR buffer[MAX_PATH + 1] = { 0 };
+ SHGetFolderPath(0, CSIDL_PROGRAM_FILES, 0, 0, buffer);
+ dir = QString::fromWCharArray(buffer);
+#elif defined (Q_OS_OSX)
+ dir = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).value(0);
+#endif
+ m_variables.insert(QLatin1String("ApplicationsDir"), dir);
+
+ QString dirX86 = dir;
+ QString dirX64 = dir;
+#ifdef Q_OS_WIN
+ QSettingsWrapper current(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion")
+ , QSettingsWrapper::NativeFormat);
+ BOOL onWow64Or64bit = TRUE;
+#ifndef Q_OS_WIN64
+ IsWow64Process(GetCurrentProcess(), &onWow64Or64bit);
+#endif
+ QString programfilesX86;
+ QString programfilesX64;
+ if (onWow64Or64bit == TRUE) {
+ programfilesX86 = current.value(QLatin1String("ProgramFilesDir (x86)"), QString()).toString();
+ programfilesX64 = current.value(QLatin1String("ProgramW6432Dir"), QString()).toString();
+ } else {
+ programfilesX86 = current.value(QLatin1String("ProgramFilesDir"), QString()).toString();
+ programfilesX64 = programfilesX86;
+ }
+ dirX86 = replaceWindowsEnvironmentVariables(programfilesX86);
+ dirX64 = replaceWindowsEnvironmentVariables(programfilesX64);
+#endif
+ m_variables.insert(QLatin1String("ApplicationsDirX86"), dirX86);
+ m_variables.insert(QLatin1String("ApplicationsDirX64"), dirX64);
+
+#ifdef Q_OS_WIN
+ QSettingsWrapper user(QLatin1String("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\"
+ "CurrentVersion\\Explorer\\User Shell Folders"), QSettingsWrapper::NativeFormat);
+ QSettingsWrapper system(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\"
+ "CurrentVersion\\Explorer\\Shell Folders"), QSettingsWrapper::NativeFormat);
+
+ const QString programs = user.value(QLatin1String("Programs"), QString()).toString();
+ const QString allPrograms = system.value(QLatin1String("Common Programs"), QString())
+ .toString();
+
+ QString desktop;
+ if (m_variables.value(QLatin1String("AllUsers")) == scTrue) {
+ desktop = system.value(QLatin1String("Desktop")).toString();
+ } else {
+ desktop = user.value(QLatin1String("Desktop")).toString();
+ }
+ m_variables.insert(QLatin1String("DesktopDir"), replaceWindowsEnvironmentVariables(desktop));
+ m_variables.insert(QLatin1String("UserStartMenuProgramsPath"),
+ replaceWindowsEnvironmentVariables(programs));
+ m_variables.insert(QLatin1String("AllUsersStartMenuProgramsPath"),
+ replaceWindowsEnvironmentVariables(allPrograms));
+#endif
+}
+
Settings &PackageManagerCoreData::settings() const
{
return m_settings;
}
-QList<QString> PackageManagerCoreData::keys() const
+QStringList PackageManagerCoreData::keys() const
{
return m_variables.keys();
}
@@ -144,7 +180,7 @@ bool PackageManagerCoreData::contains(const QString &key) const
bool PackageManagerCoreData::setValue(const QString &key, const QString &normalizedValue)
{
- if (m_variables.value(key) == normalizedValue)
+ if (m_variables.contains(key) && m_variables.value(key) == normalizedValue)
return false;
m_variables.insert(key, normalizedValue);
return true;
diff --git a/src/libs/installer/packagemanagercoredata.h b/src/libs/installer/packagemanagercoredata.h
index 59b0c9808..ec0d4c302 100644
--- a/src/libs/installer/packagemanagercoredata.h
+++ b/src/libs/installer/packagemanagercoredata.h
@@ -40,9 +40,10 @@ public:
explicit PackageManagerCoreData(const QHash<QString, QString> &variables);
void clear();
+ void setDynamicPredefinedVariables();
Settings &settings() const;
- QList<QString> keys() const;
+ QStringList keys() const;
bool contains(const QString &key) const;
bool setValue(const QString &key, const QString &normalizedValue);
diff --git a/src/libs/installer/packagemanagergui.cpp b/src/libs/installer/packagemanagergui.cpp
index 31d733599..5ee3d14fc 100644
--- a/src/libs/installer/packagemanagergui.cpp
+++ b/src/libs/installer/packagemanagergui.cpp
@@ -40,7 +40,7 @@
#include "scriptengine.h"
#include "productkeycheck.h"
-#include "kdsysinfo.h"
+#include "sysinfo.h"
#include <QApplication>
@@ -49,7 +49,9 @@
#include <QtCore/QProcess>
#include <QtCore/QTimer>
+#include <QAbstractItemView>
#include <QCheckBox>
+#include <QComboBox>
#include <QDesktopServices>
#include <QFileDialog>
#include <QGridLayout>
@@ -63,10 +65,12 @@
#include <QProgressBar>
#include <QPushButton>
#include <QRadioButton>
+#include <QStringListModel>
#include <QTextBrowser>
#include <QTreeView>
#include <QVBoxLayout>
#include <QShowEvent>
+#include <QFileDialog>
#ifdef Q_OS_WIN
# include <qt_windows.h>
@@ -105,7 +109,6 @@ public:
setLayout(new QVBoxLayout);
layout()->addWidget(widget);
layout()->setContentsMargins(0, 0, 0, 0);
- layout()->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));
addPageAndProperties(packageManagerCore()->controlScriptEngine());
addPageAndProperties(packageManagerCore()->componentScriptEngine());
@@ -202,6 +205,7 @@ public:
, m_modified(false)
, m_autoSwitchPage(true)
, m_showSettingsButton(false)
+ , m_silent(false)
{
m_wizardButtonTypes.insert(QWizard::BackButton, QLatin1String("QWizard::BackButton"));
m_wizardButtonTypes.insert(QWizard::NextButton, QLatin1String("QWizard::NextButton"));
@@ -225,6 +229,7 @@ public:
bool m_modified;
bool m_autoSwitchPage;
bool m_showSettingsButton;
+ bool m_silent;
QHash<int, QWizardPage*> m_defaultPages;
QHash<int, QString> m_defaultButtonText;
@@ -310,48 +315,66 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
if (!m_core->settings().wizardStyle().isEmpty())
setWizardStyle(getStyle(m_core->settings().wizardStyle()));
+ // set custom stylesheet
+ const QString styleSheetFile = m_core->settings().styleSheet();
+ if (!styleSheetFile.isEmpty()) {
+ QFile sheet(styleSheetFile);
+ if (sheet.exists()) {
+ if (sheet.open(QIODevice::ReadOnly))
+ setStyleSheet(QString::fromLatin1(sheet.readAll()));
+ else
+ qWarning() << "The specified style sheet file can not be opened.";
+ } else {
+ qWarning() << "A style sheet file is specified, but it does not exist.";
+ }
+ }
+
setOption(QWizard::NoBackButtonOnStartPage);
setOption(QWizard::NoBackButtonOnLastPage);
- connect(this, SIGNAL(rejected()), m_core, SLOT(setCanceled()));
- connect(this, SIGNAL(interrupted()), m_core, SLOT(interrupt()));
+ connect(this, &QDialog::rejected, m_core, &PackageManagerCore::setCanceled);
+ connect(this, &PackageManagerGui::interrupted, m_core, &PackageManagerCore::interrupt);
// both queued to show the finished page once everything is done
- connect(m_core, SIGNAL(installationFinished()), this, SLOT(showFinishedPage()),
+ connect(m_core, &PackageManagerCore::installationFinished,
+ this, &PackageManagerGui::showFinishedPage,
Qt::QueuedConnection);
- connect(m_core, SIGNAL(uninstallationFinished()), this, SLOT(showFinishedPage()),
+ connect(m_core, &PackageManagerCore::uninstallationFinished,
+ this, &PackageManagerGui::showFinishedPage,
Qt::QueuedConnection);
- connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(currentPageChanged(int)));
- connect(this, SIGNAL(currentIdChanged(int)), m_core, SIGNAL(currentPageChanged(int)));
- connect(button(QWizard::FinishButton), SIGNAL(clicked()), this, SIGNAL(finishButtonClicked()));
- connect(button(QWizard::FinishButton), SIGNAL(clicked()), m_core, SIGNAL(finishButtonClicked()));
+ connect(this, &QWizard::currentIdChanged, this, &PackageManagerGui::currentPageChanged);
+ connect(this, &QWizard::currentIdChanged, m_core, &PackageManagerCore::currentPageChanged);
+ connect(button(QWizard::FinishButton), &QAbstractButton::clicked,
+ this, &PackageManagerGui::finishButtonClicked);
+ connect(button(QWizard::FinishButton), &QAbstractButton::clicked,
+ m_core, &PackageManagerCore::finishButtonClicked);
// make sure the QUiLoader's retranslateUi is executed first, then the script
- connect(this, SIGNAL(languageChanged()), m_core, SLOT(languageChanged()), Qt::QueuedConnection);
- connect(this, SIGNAL(languageChanged()), this, SLOT(onLanguageChanged()), Qt::QueuedConnection);
+ connect(this, &PackageManagerGui::languageChanged,
+ m_core, &PackageManagerCore::languageChanged, Qt::QueuedConnection);
+ connect(this, &PackageManagerGui::languageChanged,
+ this, &PackageManagerGui::onLanguageChanged, Qt::QueuedConnection);
connect(m_core,
- SIGNAL(wizardPageInsertionRequested(QWidget*,QInstaller::PackageManagerCore::WizardPage)),
- this, SLOT(wizardPageInsertionRequested(QWidget*,QInstaller::PackageManagerCore::WizardPage)));
- connect(m_core, SIGNAL(wizardPageRemovalRequested(QWidget*)), this,
- SLOT(wizardPageRemovalRequested(QWidget*)));
- connect(m_core,
- SIGNAL(wizardWidgetInsertionRequested(QWidget*,QInstaller::PackageManagerCore::WizardPage)),
- this, SLOT(wizardWidgetInsertionRequested(QWidget*,QInstaller::PackageManagerCore::WizardPage)));
- connect(m_core, SIGNAL(wizardWidgetRemovalRequested(QWidget*)), this,
- SLOT(wizardWidgetRemovalRequested(QWidget*)));
- connect(m_core, SIGNAL(wizardPageVisibilityChangeRequested(bool,int)), this,
- SLOT(wizardPageVisibilityChangeRequested(bool,int)), Qt::QueuedConnection);
+ &PackageManagerCore::wizardPageInsertionRequested,
+ this, &PackageManagerGui::wizardPageInsertionRequested);
+ connect(m_core, &PackageManagerCore::wizardPageRemovalRequested,
+ this, &PackageManagerGui::wizardPageRemovalRequested);
+ connect(m_core, &PackageManagerCore::wizardWidgetInsertionRequested,
+ this, &PackageManagerGui::wizardWidgetInsertionRequested);
+ connect(m_core, &PackageManagerCore::wizardWidgetRemovalRequested,
+ this, &PackageManagerGui::wizardWidgetRemovalRequested);
+ connect(m_core, &PackageManagerCore::wizardPageVisibilityChangeRequested,
+ this, &PackageManagerGui::wizardPageVisibilityChangeRequested, Qt::QueuedConnection);
- connect(m_core,
- SIGNAL(setValidatorForCustomPageRequested(QInstaller::Component*,QString,QString)), this,
- SLOT(setValidatorForCustomPageRequested(QInstaller::Component*,QString,QString)));
+ connect(m_core, &PackageManagerCore::setValidatorForCustomPageRequested,
+ this, &PackageManagerGui::setValidatorForCustomPageRequested);
- connect(m_core, SIGNAL(setAutomatedPageSwitchEnabled(bool)), this,
- SLOT(setAutomatedPageSwitchEnabled(bool)));
+ connect(m_core, &PackageManagerCore::setAutomatedPageSwitchEnabled,
+ this, &PackageManagerGui::setAutomatedPageSwitchEnabled);
- connect(this, SIGNAL(customButtonClicked(int)), this, SLOT(customButtonClicked(int)));
+ connect(this, &QWizard::customButtonClicked, this, &PackageManagerGui::customButtonClicked);
for (int i = QWizard::BackButton; i < QWizard::CustomButton1; ++i)
d->m_defaultButtonText.insert(i, buttonText(QWizard::WizardButton(i)));
@@ -395,6 +418,43 @@ QWizard::WizardStyle PackageManagerGui::getStyle(const QString &name)
}
/*!
+ Hides the GUI when \a silent is \c true.
+*/
+void PackageManagerGui::setSilent(bool silent)
+{
+ d->m_silent = silent;
+ setVisible(!silent);
+}
+
+/*!
+ Returns the current silent state.
+*/
+bool PackageManagerGui::isSilent() const
+{
+ return d->m_silent;
+}
+
+/*!
+ Updates the model of \a object (which must be a QComboBox or
+ QAbstractItemView) such that it contains the given \a items.
+*/
+void PackageManagerGui::setTextItems(QObject *object, const QStringList &items)
+{
+ if (QComboBox *comboBox = qobject_cast<QComboBox*>(object)) {
+ comboBox->setModel(new QStringListModel(items));
+ return;
+ }
+
+ if (QAbstractItemView *view = qobject_cast<QAbstractItemView*>(object)) {
+ view->setModel(new QStringListModel(items));
+ return;
+ }
+
+ qDebug() << "Cannot set text items on object of type"
+ << object->metaObject()->className() << ".";
+}
+
+/*!
Enables automatic page switching when \a request is \c true.
*/
void PackageManagerGui::setAutomatedPageSwitchEnabled(bool request)
@@ -445,7 +505,7 @@ void PackageManagerGui::clickButton(int wb, int delay)
wb = QWizard::CancelButton;
if (QAbstractButton *b = button(static_cast<QWizard::WizardButton>(wb)))
- QTimer::singleShot(delay, b, SLOT(click()));
+ QTimer::singleShot(delay, b, &QAbstractButton::click);
else
qWarning() << "Button with type: " << d->buttonType(wb) << "not found!";
}
@@ -738,13 +798,13 @@ void PackageManagerGui::cancelButtonClicked()
question = tr("Do you want to quit the installer application?");
if (m_core->isUninstaller())
question = tr("Do you want to quit the uninstaller application?");
- if (m_core->isUpdater() || m_core->isPackageManager())
+ if (m_core->isMaintainer())
question = tr("Do you want to quit the maintenance application?");
}
const QMessageBox::StandardButton button =
MessageBoxHandler::question(MessageBoxHandler::currentBestSuitParent(),
- QLatin1String("cancelInstallation"), tr("Question"), question,
+ QLatin1String("cancelInstallation"), tr("%1 Question").arg(m_core->value(scTitle)), question,
QMessageBox::Yes | QMessageBox::No);
if (button == QMessageBox::Yes) {
@@ -784,7 +844,6 @@ void PackageManagerGui::setModified(bool value)
*/
void PackageManagerGui::showFinishedPage()
{
- qDebug() << "SHOW FINISHED PAGE";
if (d->m_autoSwitchPage)
next();
else
@@ -1023,7 +1082,17 @@ QPixmap PackageManagerPage::watermarkPixmap() const
*/
QPixmap PackageManagerPage::bannerPixmap() const
{
- return QPixmap(m_core->value(QLatin1String("BannerPixmap")));
+ QPixmap banner(m_core->value(QLatin1String("BannerPixmap")));
+
+ if (!banner.isNull()) {
+ int width;
+ if (m_core->settings().containsValue(QLatin1String("WizardDefaultWidth")) )
+ width = m_core->settings().wizardDefaultWidth();
+ else
+ width = size().width();
+ banner = banner.scaledToWidth(width, Qt::SmoothTransformation);
+ }
+ return banner;
}
/*!
@@ -1149,7 +1218,7 @@ int PackageManagerPage::nextId() const
core->calculateComponentsToInstall();
foreach (Component* component, core->orderedComponentsToInstall()) {
- if ((core->isPackageManager() || core->isUpdater()) && component->isInstalled())
+ if (core->isMaintainer() && component->isInstalled())
continue; // package manager or updater, hide as long as the component is installed
// The component is about to be installed and provides a license, so the page needs to
@@ -1210,20 +1279,22 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
m_packageManager->setObjectName(QLatin1String("PackageManagerRadioButton"));
boxLayout->addWidget(m_packageManager);
m_packageManager->setChecked(core->isPackageManager());
- connect(m_packageManager, SIGNAL(toggled(bool)), this, SLOT(setPackageManager(bool)));
+ connect(m_packageManager, &QAbstractButton::toggled, this, &IntroductionPage::setPackageManager);
m_updateComponents = new QRadioButton(tr("Update components"), this);
m_updateComponents->setObjectName(QLatin1String("UpdaterRadioButton"));
boxLayout->addWidget(m_updateComponents);
m_updateComponents->setChecked(core->isUpdater());
- connect(m_updateComponents, SIGNAL(toggled(bool)), this, SLOT(setUpdater(bool)));
+ connect(m_updateComponents, &QAbstractButton::toggled, this, &IntroductionPage::setUpdater);
m_removeAllComponents = new QRadioButton(tr("Remove all components"), this);
m_removeAllComponents->setObjectName(QLatin1String("UninstallerRadioButton"));
boxLayout->addWidget(m_removeAllComponents);
m_removeAllComponents->setChecked(core->isUninstaller());
- connect(m_removeAllComponents, SIGNAL(toggled(bool)), this, SLOT(setUninstaller(bool)));
- connect(m_removeAllComponents, SIGNAL(toggled(bool)), core, SLOT(setCompleteUninstallation(bool)));
+ connect(m_removeAllComponents, &QAbstractButton::toggled,
+ this, &IntroductionPage::setUninstaller);
+ connect(m_removeAllComponents, &QAbstractButton::toggled,
+ core, &PackageManagerCore::setCompleteUninstallation);
boxLayout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding));
@@ -1251,16 +1322,19 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
core->setCompleteUninstallation(core->isUninstaller());
- connect(core, SIGNAL(metaJobProgress(int)), this, SLOT(onProgressChanged(int)));
- connect(core, SIGNAL(metaJobInfoMessage(QString)), this, SLOT(setMessage(QString)));
- connect(core, SIGNAL(coreNetworkSettingsChanged()), this, SLOT(onCoreNetworkSettingsChanged()));
+ connect(core, &PackageManagerCore::metaJobProgress, this, &IntroductionPage::onProgressChanged);
+ connect(core, &PackageManagerCore::metaJobTotalProgress, this, &IntroductionPage::setTotalProgress);
+ connect(core, &PackageManagerCore::metaJobInfoMessage, this, &IntroductionPage::setMessage);
+ connect(core, &PackageManagerCore::coreNetworkSettingsChanged,
+ this, &IntroductionPage::onCoreNetworkSettingsChanged);
m_updateComponents->setEnabled(ProductKeyCheck::instance()->hasValidKey());
#ifdef Q_OS_WIN
if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) {
m_taskButton = new QWinTaskbarButton(this);
- connect(core, SIGNAL(metaJobProgress(int)), m_taskButton->progress(), SLOT(setValue(int)));
+ connect(core, &PackageManagerCore::metaJobProgress,
+ m_taskButton->progress(), &QWinTaskbarProgress::setValue);
} else {
m_taskButton = 0;
}
@@ -1276,7 +1350,7 @@ int IntroductionPage::nextId() const
if (packageManagerCore()->isUninstaller())
return PackageManagerCore::ReadyForInstallation;
- if (packageManagerCore()->isUpdater() || packageManagerCore()->isPackageManager())
+ if (packageManagerCore()->isMaintainer())
return PackageManagerCore::ComponentSelection;
return PackageManagerPage::nextId();
@@ -1301,8 +1375,7 @@ bool IntroductionPage::validatePage()
}
gui()->setSettingsButtonEnabled(false);
- const bool maintenance = core->isUpdater() || core->isPackageManager();
- if (maintenance) {
+ if (core->isMaintainer()) {
showAll();
setMaintenanceToolsEnabled(false);
} else {
@@ -1363,7 +1436,7 @@ bool IntroductionPage::validatePage()
setComplete(true);
}
- if (maintenance) {
+ if (core->isMaintainer()) {
showMaintenanceTools();
setMaintenanceToolsEnabled(true);
} else {
@@ -1440,11 +1513,19 @@ void IntroductionPage::setMessage(const QString &msg)
*/
void IntroductionPage::onProgressChanged(int progress)
{
- m_progressBar->setRange(0, 100);
m_progressBar->setValue(progress);
}
/*!
+ Sets total \a progress value to progress bar.
+*/
+void IntroductionPage::setTotalProgress(int totalProgress)
+{
+ if (m_progressBar)
+ m_progressBar->setRange(0, totalProgress);
+}
+
+/*!
Displays the error message \a error on the page.
*/
void IntroductionPage::setErrorMessage(const QString &error)
@@ -1545,7 +1626,7 @@ void IntroductionPage::entering()
m_progressBar->setValue(0);
m_progressBar->setRange(0, 0);
PackageManagerCore *core = packageManagerCore();
- if (core->isUninstaller() || core->isUpdater() || core->isPackageManager()) {
+ if (core->isUninstaller() || core->isMaintainer()) {
showMaintenanceTools();
setMaintenanceToolsEnabled(true);
}
@@ -1635,19 +1716,19 @@ LicenseAgreementPage::LicenseAgreementPage(PackageManagerCore *core)
m_licenseListWidget = new QListWidget(this);
m_licenseListWidget->setObjectName(QLatin1String("LicenseListWidget"));
- m_licenseListWidget->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
- connect(m_licenseListWidget, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
- this, SLOT(currentItemChanged(QListWidgetItem*)));
+ m_licenseListWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ connect(m_licenseListWidget, &QListWidget::currentItemChanged,
+ this, &LicenseAgreementPage::currentItemChanged);
m_textBrowser = new QTextBrowser(this);
m_textBrowser->setReadOnly(true);
m_textBrowser->setOpenLinks(false);
m_textBrowser->setOpenExternalLinks(true);
m_textBrowser->setObjectName(QLatin1String("LicenseTextBrowser"));
- m_textBrowser->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
- connect(m_textBrowser, SIGNAL(anchorClicked(QUrl)), this, SLOT(openLicenseUrl(QUrl)));
+ m_textBrowser->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ connect(m_textBrowser, &QTextBrowser::anchorClicked, this, &LicenseAgreementPage::openLicenseUrl);
- QHBoxLayout *licenseBoxLayout = new QHBoxLayout();
+ QVBoxLayout *licenseBoxLayout = new QVBoxLayout();
licenseBoxLayout->addWidget(m_licenseListWidget);
licenseBoxLayout->addWidget(m_textBrowser);
@@ -1684,8 +1765,8 @@ LicenseAgreementPage::LicenseAgreementPage(PackageManagerCore *core)
gridLayout->addWidget(m_rejectLabel, 1, 1);
layout->addLayout(gridLayout);
- connect(m_acceptRadioButton, SIGNAL(toggled(bool)), this, SIGNAL(completeChanged()));
- connect(m_rejectRadioButton, SIGNAL(toggled(bool)), this, SIGNAL(completeChanged()));
+ connect(m_acceptRadioButton, &QAbstractButton::toggled, this, &QWizardPage::completeChanged);
+ connect(m_rejectRadioButton, &QAbstractButton::toggled, this, &QWizardPage::completeChanged);
m_rejectRadioButton->setChecked(true);
}
@@ -1758,7 +1839,7 @@ void LicenseAgreementPage::updateUi()
acceptButtonText = tr("I accept the licenses.");
rejectButtonText = tr("I do not accept the licenses.");
}
-
+ m_licenseListWidget->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
setColoredSubTitle(subTitleText);
m_acceptLabel->setText(acceptButtonText);
@@ -1781,6 +1862,7 @@ public:
, m_allModel(m_core->defaultComponentModel())
, m_updaterModel(m_core->updaterComponentModel())
, m_currentModel(m_allModel)
+ , m_compressedButtonVisible(false)
{
m_treeView->setObjectName(QLatin1String("ComponentsTreeView"));
@@ -1796,23 +1878,28 @@ public:
m_descriptionLabel->setWordWrap(true);
m_descriptionLabel->setObjectName(QLatin1String("ComponentDescriptionLabel"));
- QVBoxLayout *vlayout = new QVBoxLayout;
- vlayout->addWidget(m_descriptionLabel);
+ m_vlayout = new QVBoxLayout;
+ m_vlayout->setObjectName(QLatin1String("VerticalLayout"));
+ m_vlayout->addWidget(m_descriptionLabel);
m_sizeLabel = new QLabel(q);
m_sizeLabel->setWordWrap(true);
- vlayout->addWidget(m_sizeLabel);
+ m_vlayout->addWidget(m_sizeLabel);
m_sizeLabel->setObjectName(QLatin1String("ComponentSizeLabel"));
- vlayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::MinimumExpanding,
+#ifdef INSTALLCOMPRESSED
+ allowCompressedRepositoryInstall();
+#endif
+ m_vlayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::MinimumExpanding,
QSizePolicy::MinimumExpanding));
- hlayout->addLayout(vlayout, 2);
+ hlayout->addLayout(m_vlayout, 2);
QVBoxLayout *layout = new QVBoxLayout(q);
layout->addLayout(hlayout, 1);
m_checkDefault = new QPushButton;
- connect(m_checkDefault, SIGNAL(clicked()), this, SLOT(selectDefault()));
+ connect(m_checkDefault, &QAbstractButton::clicked,
+ this, &ComponentSelectionPage::Private::selectDefault);
if (m_core->isInstaller()) {
m_checkDefault->setObjectName(QLatin1String("SelectDefaultComponentsButton"));
m_checkDefault->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+A",
@@ -1830,7 +1917,8 @@ public:
m_checkAll = new QPushButton;
hlayout->addWidget(m_checkAll);
- connect(m_checkAll, SIGNAL(clicked()), this, SLOT(selectAll()));
+ connect(m_checkAll, &QAbstractButton::clicked,
+ this, &ComponentSelectionPage::Private::selectAll);
m_checkAll->setObjectName(QLatin1String("SelectAllComponentsButton"));
m_checkAll->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+S",
"select all components")));
@@ -1838,7 +1926,8 @@ public:
m_uncheckAll = new QPushButton;
hlayout->addWidget(m_uncheckAll);
- connect(m_uncheckAll, SIGNAL(clicked()), this, SLOT(deselectAll()));
+ connect(m_uncheckAll, &QAbstractButton::clicked,
+ this, &ComponentSelectionPage::Private::deselectAll);
m_uncheckAll->setObjectName(QLatin1String("DeselectAllComponentsButton"));
m_uncheckAll->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+D",
"deselect all components")));
@@ -1849,22 +1938,56 @@ public:
layout->addLayout(hlayout);
}
+ void allowCompressedRepositoryInstall()
+ {
+ if (m_compressedButtonVisible) {
+ return;
+ }
+
+ connect(m_core, SIGNAL(metaJobProgress(int)), this, SLOT(onProgressChanged(int)));
+ connect(m_core, SIGNAL(metaJobInfoMessage(QString)), this, SLOT(setMessage(QString)));
+
+ m_bspLabel = new QLabel(ComponentSelectionPage::tr("To install new "\
+ "compressed repository, browse the repositories from your computer"),q);
+ m_bspLabel->setWordWrap(true);
+ m_bspLabel->setObjectName(QLatin1String("CompressedButtonLabel"));
+
+ m_vlayout->addSpacing(50);
+ m_vlayout->addWidget(m_bspLabel);
+
+ m_progressBar = new QProgressBar();
+ m_progressBar->setRange(0, 0);
+ m_progressBar->hide();
+ m_vlayout->addWidget(m_progressBar);
+ m_progressBar->setObjectName(QLatin1String("CompressedInstallProgressBar"));
+
+ m_installCompressButton = new QPushButton;
+ connect(m_installCompressButton, &QAbstractButton::clicked,
+ this, &ComponentSelectionPage::Private::selectCompressedPackage);
+ m_installCompressButton->setObjectName(QLatin1String("InstallCompressedPackageButton"));
+ m_installCompressButton->setText(ComponentSelectionPage::tr("&Browse QBSP files"));
+ m_vlayout->addWidget(m_installCompressButton);
+ m_compressedButtonVisible = true;
+ }
+
void updateTreeView()
{
m_checkDefault->setVisible(m_core->isInstaller() || m_core->isPackageManager());
if (m_treeView->selectionModel()) {
- disconnect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
- this, SLOT(currentSelectedChanged(QModelIndex)));
+ disconnect(m_treeView->selectionModel(), &QItemSelectionModel::currentChanged,
+ this, &ComponentSelectionPage::Private::currentSelectedChanged);
}
m_currentModel = m_core->isUpdater() ? m_updaterModel : m_allModel;
m_treeView->setModel(m_currentModel);
m_treeView->setExpanded(m_currentModel->index(0, 0), true);
- const bool installActionColumnVisible = false;
+ const bool installActionColumnVisible = m_core->settings().installActionColumnVisible();
if (!installActionColumnVisible)
m_treeView->hideColumn(ComponentModelHelper::ActionColumn);
+ m_treeView->header()->setSectionResizeMode(
+ ComponentModelHelper::NameColumn, QHeaderView::ResizeToContents);
if (m_core->isInstaller()) {
m_treeView->setHeaderHidden(true);
for (int i = ComponentModelHelper::InstalledVersionColumn; i < m_currentModel->columnCount(); ++i)
@@ -1895,8 +2018,8 @@ public:
hasChildren = m_currentModel->hasChildren(m_currentModel->index(row, 0));
m_treeView->setRootIsDecorated(hasChildren);
- connect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
- this, SLOT(currentSelectedChanged(QModelIndex)));
+ connect(m_treeView->selectionModel(), &QItemSelectionModel::currentChanged,
+ this, &ComponentSelectionPage::Private::currentSelectedChanged);
m_treeView->setCurrentIndex(m_currentModel->index(0, 0));
}
@@ -1932,6 +2055,59 @@ public slots:
m_currentModel->setCheckedState(ComponentModel::AllUnchecked);
}
+ void selectCompressedPackage()
+ {
+ QString defaultDownloadDirectory =
+ QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
+ QStringList fileNames = QFileDialog::getOpenFileNames(NULL,
+ ComponentSelectionPage::tr("Open File"),defaultDownloadDirectory,
+ QLatin1String("QBSP or 7z Files (*.qbsp *.7z)"));
+
+ QSet<Repository> set;
+ foreach (QString fileName, fileNames) {
+ Repository repository = Repository::fromUserInput(fileName, true);
+ repository.setEnabled(true);
+ set.insert(repository);
+ }
+ if (set.count() > 0) {
+ m_progressBar->show();
+ m_installCompressButton->hide();
+ QPushButton *const b = qobject_cast<QPushButton *>(q->gui()->button(QWizard::NextButton));
+ b->setEnabled(false);
+ m_core->settings().addTemporaryRepositories(set, false);
+ if (!m_core->fetchCompressedPackagesTree()) {
+ setMessage(m_core->error());
+ }
+ else {
+ updateTreeView();
+ setMessage(ComponentSelectionPage::tr("To install new "\
+ "compressed repository, browse the repositories from your computer"));
+ }
+
+ m_progressBar->hide();
+ m_installCompressButton->show();
+ b->setEnabled(true);
+ }
+ }
+
+ /*!
+ Updates the value of \a progress on the progress bar.
+ */
+ void onProgressChanged(int progress)
+ {
+ m_progressBar->setValue(progress);
+ }
+
+ /*!
+ Displays the message \a msg on the page.
+ */
+ void setMessage(const QString &msg)
+ {
+ QWizardPage *page = q->gui()->currentPage();
+ if (m_bspLabel && page && page->objectName() == QLatin1String("ComponentSelectionPage"))
+ m_bspLabel->setText(msg);
+ }
+
void selectDefault()
{
m_currentModel->setCheckedState(ComponentModel::DefaultChecked);
@@ -1969,6 +2145,11 @@ public:
QPushButton *m_checkAll;
QPushButton *m_uncheckAll;
QPushButton *m_checkDefault;
+ QPushButton *m_installCompressButton;
+ QLabel *m_bspLabel;
+ QProgressBar *m_progressBar;
+ QVBoxLayout *m_vlayout;
+ bool m_compressedButtonVisible;
};
@@ -2012,7 +2193,7 @@ void ComponentSelectionPage::entering()
QT_TR_NOOP("Please select the components you want to update."),
QT_TR_NOOP("Please select the components you want to install."),
QT_TR_NOOP("Please select the components you want to uninstall."),
- QT_TR_NOOP("Select the components to install. Deselect installed components to uninstall them.")
+ QT_TR_NOOP("Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.")
};
int index = 0;
@@ -2087,6 +2268,11 @@ void ComponentSelectionPage::deselectComponent(const QString &id)
d->m_currentModel->setData(idx, Qt::Unchecked, Qt::CheckStateRole);
}
+void ComponentSelectionPage::allowCompressedRepositoryInstall()
+{
+ d->allowCompressedRepositoryInstall();
+}
+
void ComponentSelectionPage::setModified(bool modified)
{
setComplete(modified);
@@ -2143,19 +2329,24 @@ TargetDirectoryPage::TargetDirectoryPage(PackageManagerCore *core)
QLabel *msgLabel = new QLabel(this);
msgLabel->setWordWrap(true);
msgLabel->setObjectName(QLatin1String("MessageLabel"));
- msgLabel->setText(tr("Please specify the folder where %1 will be installed.").arg(productName()));
+ msgLabel->setText(tr("Please specify the directory where %1 will be installed.").arg(productName()));
layout->addWidget(msgLabel);
QHBoxLayout *hlayout = new QHBoxLayout;
+ m_textChangeTimer.setSingleShot(true);
+ m_textChangeTimer.setInterval(200);
+ connect(&m_textChangeTimer, &QTimer::timeout, this, &QWizardPage::completeChanged);
+
m_lineEdit = new QLineEdit(this);
m_lineEdit->setObjectName(QLatin1String("TargetDirectoryLineEdit"));
- connect(m_lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(completeChanged()));
+ connect(m_lineEdit, &QLineEdit::textChanged,
+ &m_textChangeTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
hlayout->addWidget(m_lineEdit);
QPushButton *browseButton = new QPushButton(this);
browseButton->setObjectName(QLatin1String("BrowseDirectoryButton"));
- connect(browseButton, SIGNAL(clicked()), this, SLOT(dirRequested()));
+ connect(browseButton, &QAbstractButton::clicked, this, &TargetDirectoryPage::dirRequested);
browseButton->setShortcut(QKeySequence(tr("Alt+R", "browse file system to choose a file")));
browseButton->setText(tr("B&rowse..."));
hlayout->addWidget(browseButton);
@@ -2226,6 +2417,11 @@ void TargetDirectoryPage::initializePage()
*/
bool TargetDirectoryPage::validatePage()
{
+ m_textChangeTimer.stop();
+
+ if (!isComplete())
+ return false;
+
if (!isVisible())
return true;
@@ -2251,14 +2447,14 @@ bool TargetDirectoryPage::validatePage()
QFileInfo fi2(targetDir + QDir::separator() + fileName);
if (fi2.exists()) {
- return failWithError(QLatin1String("TargetDirectoryInUse"), tr("The folder you selected already "
+ return failWithError(QLatin1String("TargetDirectoryInUse"), tr("The directory you selected already "
"exists and contains an installation. Choose a different target for installation."));
}
return askQuestion(QLatin1String("OverwriteTargetDirectory"),
- tr("You have selected an existing, non-empty folder for installation.\nNote that it will be "
+ tr("You have selected an existing, non-empty directory for installation.\nNote that it will be "
"completely wiped on uninstallation of this application.\nIt is not advisable to install into "
- "this folder as installation might fail.\nDo you want to continue?"));
+ "this directory as installation might fail.\nDo you want to continue?"));
} else if (fi.isFile() || fi.isSymLink()) {
return failWithError(QLatin1String("WrongTargetDirectory"), tr("You have selected an existing file "
"or symlink, please choose a different target for installation."));
@@ -2313,7 +2509,7 @@ bool TargetDirectoryPage::isComplete() const
QString TargetDirectoryPage::targetDirWarning() const
{
if (targetDir().isEmpty())
- return tr("The installation path cannot be empty, please specify a valid folder.");
+ return tr("The installation path cannot be empty, please specify a valid directory.");
QDir target(targetDir());
if (target.isRelative())
@@ -2376,7 +2572,7 @@ QString TargetDirectoryPage::targetDirWarning() const
}
if (nativeTargetDir.endsWith(QLatin1Char('.')))
- return tr("The installation path must not end with '.', please specify a valid folder.");
+ return tr("The installation path must not end with '.', please specify a valid directory.");
QString ambiguousChars = QLatin1String("[\"~<>|?*!@#$%^&:,; ]"
"|(\\\\CON)(\\\\|$)|(\\\\PRN)(\\\\|$)|(\\\\AUX)(\\\\|$)|(\\\\NUL)(\\\\|$)|(\\\\COM\\d)(\\\\|$)|(\\\\LPT\\d)(\\\\|$)");
@@ -2391,8 +2587,8 @@ QString TargetDirectoryPage::targetDirWarning() const
// check if there are not allowed characters in the target path
QRegularExpressionMatch match = ambCharRegEx.match(nativeTargetDir);
if (match.hasMatch()) {
- return tr("The installation path must not contain '%1', "
- "please specify a valid folder.").arg(match.captured(0));
+ return tr("The installation path must not contain \"%1\", "
+ "please specify a valid directory.").arg(match.captured(0));
}
return QString();
@@ -2437,7 +2633,7 @@ StartMenuDirectoryPage::StartMenuDirectoryPage(PackageManagerCore *core)
setObjectName(QLatin1String("StartMenuDirectoryPage"));
setColoredTitle(tr("Start Menu shortcuts"));
setColoredSubTitle(tr("Select the Start Menu in which you would like to create the program's "
- "shortcuts. You can also enter a name to create a new folder."));
+ "shortcuts. You can also enter a name to create a new directory."));
m_lineEdit = new QLineEdit(this);
m_lineEdit->setText(core->value(scStartMenuDir, productName()));
@@ -2445,7 +2641,7 @@ StartMenuDirectoryPage::StartMenuDirectoryPage(PackageManagerCore *core)
startMenuPath = core->value(QLatin1String("UserStartMenuProgramsPath"));
QStringList dirs = QDir(startMenuPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
- if (core->value(QLatin1String("AllUsers")) == scTrue) {
+ if (core->value(scAllUsers, scFalse) == scTrue) {
startMenuPath = core->value(QLatin1String("AllUsersStartMenuProgramsPath"));
dirs += QDir(startMenuPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
}
@@ -2461,8 +2657,8 @@ StartMenuDirectoryPage::StartMenuDirectoryPage(PackageManagerCore *core)
setLayout(layout);
- connect(m_listWidget, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), this,
- SLOT(currentItemChanged(QListWidgetItem*)));
+ connect(m_listWidget, &QListWidget::currentItemChanged, this,
+ &StartMenuDirectoryPage::currentItemChanged);
}
/*!
@@ -2568,7 +2764,7 @@ void ReadyForInstallationPage::entering()
.absolutePath())));
setComplete(true);
return;
- } else if (packageManagerCore()->isPackageManager() || packageManagerCore()->isUpdater()) {
+ } else if (packageManagerCore()->isMaintainer()) {
setButtonText(QWizard::CommitButton, tr("U&pdate"));
setColoredTitle(tr("Ready to Update Packages"));
m_msgLabel->setText(tr("Setup is now ready to begin updating your installation."));
@@ -2581,7 +2777,7 @@ void ReadyForInstallationPage::entering()
}
QString htmlOutput;
- bool componentsOk = calculateComponents(&htmlOutput);
+ bool componentsOk = packageManagerCore()->calculateComponents(&htmlOutput);
m_taskDetailsBrowser->setHtml(htmlOutput);
m_taskDetailsBrowser->setVisible(!componentsOk || isVerbose());
setComplete(componentsOk);
@@ -2594,19 +2790,19 @@ void ReadyForInstallationPage::entering()
// at the moment there is no better way to check this
if (targetVolume.size() == 0 && installVolumeAvailableSize == 0) {
- qDebug() << QString::fromLatin1("Could not determine available space on device. Volume "
- "descriptor: %1, Mount path: %2. Continue silently.").arg(targetVolume
- .volumeDescriptor(), targetVolume.mountPath());
+ qDebug().nospace() << "Cannot determine available space on device. "
+ "Volume descriptor: " << targetVolume.volumeDescriptor()
+ << ", Mount path: " << targetVolume.mountPath() << ". Continue silently.";
return; // TODO: Shouldn't this also disable the "Next" button?
}
const bool tempOnSameVolume = (targetVolume == tempVolume);
if (tempOnSameVolume) {
- qDebug() << "Tmp and install folder are on the same volume. Volume mount point:"
+ qDebug() << "Tmp and install directories are on the same volume. Volume mount point:"
<< targetVolume.mountPath() << "Free space available:"
<< humanReadableSize(installVolumeAvailableSize);
} else {
- qDebug() << "Tmp is on a different volume than the install folder. Tmp volume mount point:"
+ qDebug() << "Tmp is on a different volume than the installation directory. Tmp volume mount point:"
<< tempVolume.mountPath() << "Free space available:"
<< humanReadableSize(tempVolumeAvailableSize) << "Install volume mount point:"
<< targetVolume.mountPath() << "Free space available:"
@@ -2638,7 +2834,7 @@ void ReadyForInstallationPage::entering()
if (tempOnSameVolume && (installVolumeAvailableSize <= (required + tempRequired))) {
m_msgLabel->setText(tr("Not enough disk space to store temporary files and the "
- "installation! Available space: %1, at least required %2.")
+ "installation. %1 are available, while %2 are at least required.")
.arg(humanReadableSize(installVolumeAvailableSize),
humanReadableSize(required + tempRequired)));
setComplete(false);
@@ -2646,16 +2842,16 @@ void ReadyForInstallationPage::entering()
}
if (installVolumeAvailableSize < required) {
- m_msgLabel->setText(tr("Not enough disk space to store all selected components! Available "
- "space: %1, at least required: %2.").arg(humanReadableSize(installVolumeAvailableSize),
+ m_msgLabel->setText(tr("Not enough disk space to store all selected components! %1 are available "
+ "while %2 are at least required.").arg(humanReadableSize(installVolumeAvailableSize),
humanReadableSize(required)));
setComplete(false);
return;
}
if (tempVolumeAvailableSize < tempRequired) {
- m_msgLabel->setText(tr("Not enough disk space to store temporary files! Available space: "
- "%1, at least required: %2.").arg(humanReadableSize(tempVolumeAvailableSize),
+ m_msgLabel->setText(tr("Not enough disk space to store temporary files! %1 are available "
+ "while %2 are at least required.").arg(humanReadableSize(tempVolumeAvailableSize),
humanReadableSize(tempRequired)));
setComplete(false);
return;
@@ -2678,51 +2874,7 @@ void ReadyForInstallationPage::entering()
.arg(humanReadableSize(packageManagerCore()->requiredDiskSpace()))));
}
-bool ReadyForInstallationPage::calculateComponents(QString *displayString)
-{
- QString htmlOutput;
- QString lastInstallReason;
- if (!packageManagerCore()->calculateComponentsToUninstall() ||
- !packageManagerCore()->calculateComponentsToInstall()) {
- htmlOutput.append(QString::fromLatin1("<h2><font color=\"red\">%1</font></h2><ul>")
- .arg(tr("Cannot resolve all dependencies.")));
- //if we have a missing dependency or a recursion we can display it
- if (!packageManagerCore()->componentsToInstallError().isEmpty()) {
- htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(
- packageManagerCore()->componentsToInstallError()));
- }
- htmlOutput.append(QLatin1String("</ul>"));
- if (displayString)
- *displayString = htmlOutput;
- return false;
- }
- // In case of updater mode we don't uninstall components.
- if (!packageManagerCore()->isUpdater()) {
- QList<Component*> componentsToRemove = packageManagerCore()->componentsToUninstall();
- if (!componentsToRemove.isEmpty()) {
- htmlOutput.append(QString::fromLatin1("<h3>%1</h3><ul>").arg(tr("Components about to "
- "be removed.")));
- foreach (Component *component, componentsToRemove)
- htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(component->name()));
- htmlOutput.append(QLatin1String("</ul>"));
- }
- }
-
- foreach (Component *component, packageManagerCore()->orderedComponentsToInstall()) {
- const QString installReason = packageManagerCore()->installReason(component);
- if (lastInstallReason != installReason) {
- if (!lastInstallReason.isEmpty()) // means we had to close the previous list
- htmlOutput.append(QLatin1String("</ul>"));
- htmlOutput.append(QString::fromLatin1("<h3>%1</h3><ul>").arg(installReason));
- lastInstallReason = installReason;
- }
- htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(component->name()));
- }
- if (displayString)
- *displayString = htmlOutput;
- return true;
-}
/*!
Called when end users leave the page and the PackageManagerGui:currentPageChanged()
@@ -2769,22 +2921,27 @@ PerformInstallationPage::PerformInstallationPage(PackageManagerCore *core)
m_performInstallationForm->setupUi(this);
- connect(ProgressCoordinator::instance(), SIGNAL(detailTextChanged(QString)),
- m_performInstallationForm, SLOT(appendProgressDetails(QString)));
- connect(ProgressCoordinator::instance(), SIGNAL(detailTextResetNeeded()),
- m_performInstallationForm, SLOT(clearDetailsBrowser()));
- connect(m_performInstallationForm, SIGNAL(showDetailsChanged()), this,
- SLOT(toggleDetailsWereChanged()));
+ connect(ProgressCoordinator::instance(), &ProgressCoordinator::detailTextChanged,
+ m_performInstallationForm, &PerformInstallationForm::appendProgressDetails);
+ connect(ProgressCoordinator::instance(), &ProgressCoordinator::detailTextResetNeeded,
+ m_performInstallationForm, &PerformInstallationForm::clearDetailsBrowser);
+ connect(m_performInstallationForm, &PerformInstallationForm::showDetailsChanged,
+ this, &PerformInstallationPage::toggleDetailsWereChanged);
- connect(core, SIGNAL(installationStarted()), this, SLOT(installationStarted()));
- connect(core, SIGNAL(installationFinished()), this, SLOT(installationFinished()));
+ connect(core, &PackageManagerCore::installationStarted,
+ this, &PerformInstallationPage::installationStarted);
+ connect(core, &PackageManagerCore::installationFinished,
+ this, &PerformInstallationPage::installationFinished);
- connect(core, SIGNAL(uninstallationStarted()), this, SLOT(uninstallationStarted()));
- connect(core, SIGNAL(uninstallationFinished()), this, SLOT(uninstallationFinished()));
+ connect(core, &PackageManagerCore::uninstallationStarted,
+ this, &PerformInstallationPage::uninstallationStarted);
+ connect(core, &PackageManagerCore::uninstallationFinished,
+ this, &PerformInstallationPage::uninstallationFinished);
- connect(core, SIGNAL(titleMessageChanged(QString)), this, SLOT(setTitleMessage(QString)));
- connect(this, SIGNAL(setAutomatedPageSwitchEnabled(bool)), core,
- SIGNAL(setAutomatedPageSwitchEnabled(bool)));
+ connect(core, &PackageManagerCore::titleMessageChanged,
+ this, &PerformInstallationPage::setTitleMessage);
+ connect(this, &PerformInstallationPage::setAutomatedPageSwitchEnabled,
+ core, &PackageManagerCore::setAutomatedPageSwitchEnabled);
m_performInstallationForm->setDetailsWidgetVisible(true);
@@ -2823,7 +2980,7 @@ void PerformInstallationPage::entering()
setColoredTitle(tr("Uninstalling %1").arg(productName()));
QTimer::singleShot(30, packageManagerCore(), SLOT(runUninstaller()));
- } else if (packageManagerCore()->isPackageManager() || packageManagerCore()->isUpdater()) {
+ } else if (packageManagerCore()->isMaintainer()) {
setButtonText(QWizard::CommitButton, tr("&Update"));
setColoredTitle(tr("Updating components of %1").arg(productName()));
@@ -2924,12 +3081,6 @@ FinishedPage::FinishedPage(PackageManagerCore *core)
m_msgLabel->setWordWrap(true);
m_msgLabel->setObjectName(QLatin1String("MessageLabel"));
-#ifdef Q_OS_OSX
- m_msgLabel->setText(tr("Click Done to exit the %1 Wizard.").arg(productName()));
-#else
- m_msgLabel->setText(tr("Click Finish to exit the %1 Wizard.").arg(productName()));
-#endif
-
m_runItCheckBox = new QCheckBox(this);
m_runItCheckBox->setObjectName(QLatin1String("RunItCheckBox"));
m_runItCheckBox->setChecked(true);
@@ -2948,12 +3099,16 @@ FinishedPage::FinishedPage(PackageManagerCore *core)
*/
void FinishedPage::entering()
{
+ m_msgLabel->setText(tr("Click %1 to exit the %2 Wizard.")
+ .arg(gui()->defaultButtonText(QWizard::FinishButton).remove(QLatin1Char('&')))
+ .arg(productName()));
+
if (m_commitButton) {
- disconnect(m_commitButton, SIGNAL(clicked()), this, SLOT(handleFinishClicked()));
+ disconnect(m_commitButton, &QAbstractButton::clicked, this, &FinishedPage::handleFinishClicked);
m_commitButton = 0;
}
- if (packageManagerCore()->isUpdater() || packageManagerCore()->isPackageManager()) {
+ if (packageManagerCore()->isMaintainer()) {
#ifdef Q_OS_OSX
gui()->setOption(QWizard::NoCancelButton, false);
#endif
@@ -2962,13 +3117,13 @@ void FinishedPage::entering()
cancel->setEnabled(true);
cancel->setVisible(true);
// we don't use the usual FinishButton so we need to connect the misused CancelButton
- connect(cancel, SIGNAL(clicked()), gui(), SIGNAL(finishButtonClicked()));
- connect(cancel, SIGNAL(clicked()), packageManagerCore(), SIGNAL(finishButtonClicked()));
+ connect(cancel, &QAbstractButton::clicked, gui(), &PackageManagerGui::finishButtonClicked);
+ connect(cancel, &QAbstractButton::clicked, packageManagerCore(), &PackageManagerCore::finishButtonClicked);
// for the moment we don't want the rejected signal connected
- disconnect(gui(), SIGNAL(rejected()), packageManagerCore(), SLOT(setCanceled()));
+ disconnect(gui(), &QDialog::rejected, packageManagerCore(), &PackageManagerCore::setCanceled);
- connect(gui()->button(QWizard::CommitButton), SIGNAL(clicked()), this,
- SLOT(cleanupChangedConnects()));
+ connect(gui()->button(QWizard::CommitButton), &QAbstractButton::clicked,
+ this, &FinishedPage::cleanupChangedConnects);
}
setButtonText(QWizard::CommitButton, tr("Restart"));
setButtonText(QWizard::CancelButton, gui()->defaultButtonText(QWizard::FinishButton));
@@ -2987,8 +3142,8 @@ void FinishedPage::entering()
gui()->updateButtonLayout();
if (m_commitButton) {
- disconnect(m_commitButton, SIGNAL(clicked()), this, SLOT(handleFinishClicked()));
- connect(m_commitButton, SIGNAL(clicked()), this, SLOT(handleFinishClicked()));
+ disconnect(m_commitButton, &QAbstractButton::clicked, this, &FinishedPage::handleFinishClicked);
+ connect(m_commitButton, &QAbstractButton::clicked, this, &FinishedPage::handleFinishClicked);
}
if (packageManagerCore()->status() == PackageManagerCore::Success) {
@@ -3055,12 +3210,12 @@ void FinishedPage::cleanupChangedConnects()
{
if (QAbstractButton *cancel = gui()->button(QWizard::CancelButton)) {
// remove the workaround connect from entering page
- disconnect(cancel, SIGNAL(clicked()), gui(), SIGNAL(finishButtonClicked()));
- disconnect(cancel, SIGNAL(clicked()), packageManagerCore(), SIGNAL(finishButtonClicked()));
- connect(gui(), SIGNAL(rejected()), packageManagerCore(), SLOT(setCanceled()));
+ disconnect(cancel, &QAbstractButton::clicked, gui(), &PackageManagerGui::finishButtonClicked);
+ disconnect(cancel, &QAbstractButton::clicked, packageManagerCore(), &PackageManagerCore::finishButtonClicked);
+ connect(gui(), &QDialog::rejected, packageManagerCore(), &PackageManagerCore::setCanceled);
- disconnect(gui()->button(QWizard::CommitButton), SIGNAL(clicked()), this,
- SLOT(cleanupChangedConnects()));
+ disconnect(gui()->button(QWizard::CommitButton), &QAbstractButton::clicked,
+ this, &FinishedPage::cleanupChangedConnects);
}
}
diff --git a/src/libs/installer/packagemanagergui.h b/src/libs/installer/packagemanagergui.h
index 94dd0a9d4..238e22a62 100644
--- a/src/libs/installer/packagemanagergui.h
+++ b/src/libs/installer/packagemanagergui.h
@@ -33,6 +33,7 @@
#include <QtCore/QEvent>
#include <QtCore/QMetaType>
+#include <QtCore/QTimer>
#include <QWizard>
#include <QWizardPage>
@@ -87,6 +88,11 @@ public:
void updateButtonLayout();
static QWizard::WizardStyle getStyle(const QString &name);
+ void setSilent(bool silent);
+ bool isSilent() const;
+
+ void setTextItems(QObject *object, const QStringList &items);
+
Q_SIGNALS:
void interrupted();
void languageChanged();
@@ -218,6 +224,7 @@ public Q_SLOTS:
void onCoreNetworkSettingsChanged();
void setMessage(const QString &msg);
void onProgressChanged(int progress);
+ void setTotalProgress(int totalProgress);
void setErrorMessage(const QString &error);
Q_SIGNALS:
@@ -303,6 +310,7 @@ public:
Q_INVOKABLE void selectDefault();
Q_INVOKABLE void selectComponent(const QString &id);
Q_INVOKABLE void deselectComponent(const QString &id);
+ Q_INVOKABLE void allowCompressedRepositoryInstall();
protected:
void entering();
@@ -347,6 +355,7 @@ private:
private:
QLineEdit *m_lineEdit;
QLabel *m_warningLabel;
+ QTimer m_textChangeTimer;
};
@@ -389,9 +398,6 @@ protected:
void leaving();
private:
- bool calculateComponents(QString *displayString);
-
-private:
QLabel *m_msgLabel;
QTextBrowser* m_taskDetailsBrowser;
};
diff --git a/src/libs/installer/packagemanagerpagefactory.cpp b/src/libs/installer/packagemanagerpagefactory.cpp
index f891bfbb3..808dec263 100644
--- a/src/libs/installer/packagemanagerpagefactory.cpp
+++ b/src/libs/installer/packagemanagerpagefactory.cpp
@@ -36,9 +36,4 @@ PackageManagerPageFactory &PackageManagerPageFactory::instance()
return factory;
}
-PackageManagerPage *PackageManagerPageFactory::create(int id, PackageManagerCore *core) const
-{
- return KDGenericFactory<PackageManagerPage, int, PackageManagerCore*>::createWithArg(id, core);
-}
-
}
diff --git a/src/libs/installer/packagemanagerpagefactory.h b/src/libs/installer/packagemanagerpagefactory.h
index 87a08fd34..4cb7cf5d4 100644
--- a/src/libs/installer/packagemanagerpagefactory.h
+++ b/src/libs/installer/packagemanagerpagefactory.h
@@ -29,16 +29,16 @@
#ifndef PACKAGEMANAGERPAGEFACTORY_H
#define PACKAGEMANAGERPAGEFACTORY_H
-#include <kdgenericfactory.h>
-#include <packagemanagergui.h>
+#include "genericfactory.h"
+#include "qinstallerglobal.h"
namespace QInstaller {
class PackageManagerCore;
class PackageManagerPage;
-class INSTALLER_EXPORT PackageManagerPageFactory : public KDGenericFactory<PackageManagerPage,
- int, QInstaller::PackageManagerCore*>
+class INSTALLER_EXPORT PackageManagerPageFactory : public GenericFactory<PackageManagerPage, int,
+ PackageManagerCore*>
{
Q_DISABLE_COPY(PackageManagerPageFactory)
@@ -46,12 +46,11 @@ public:
static PackageManagerPageFactory &instance();
template<typename T> void registerPackageManagerPage(int id)
{
- registerProductWithArg<T>(id);
+ registerProduct<T>(id);
}
- PackageManagerPage *create(int id, QInstaller::PackageManagerCore *core) const;
private:
- PackageManagerPageFactory() {}
+ PackageManagerPageFactory() = default;
};
} // namespace QInstaller
diff --git a/src/libs/installer/packagemanagerproxyfactory.cpp b/src/libs/installer/packagemanagerproxyfactory.cpp
index 734e1ba34..98aef7d9a 100644
--- a/src/libs/installer/packagemanagerproxyfactory.cpp
+++ b/src/libs/installer/packagemanagerproxyfactory.cpp
@@ -115,7 +115,7 @@ void PackageManagerProxyFactory::setProxyCredentials(const QNetworkProxy &proxy,
auto p = std::find_if(m_proxyCredentials.begin(), m_proxyCredentials.end(),
FindProxyCredential(proxy.hostName(), proxy.port()));
- if (p == m_proxyCredentials.constEnd()) {
+ if (p == m_proxyCredentials.end()) {
ProxyCredential proxyCredential;
proxyCredential.host = proxy.hostName();
proxyCredential.port = proxy.port();
diff --git a/src/libs/installer/packagemanagerproxyfactory.h b/src/libs/installer/packagemanagerproxyfactory.h
index f2d64ae96..31f1ffeba 100644
--- a/src/libs/installer/packagemanagerproxyfactory.h
+++ b/src/libs/installer/packagemanagerproxyfactory.h
@@ -29,7 +29,7 @@
#ifndef PACKAGEMANAGERPROXYFACTORY_H
#define PACKAGEMANAGERPROXYFACTORY_H
-#include "kdupdaterfiledownloaderfactory.h"
+#include "filedownloaderfactory.h"
namespace QInstaller {
diff --git a/src/libs/installer/packagesource.cpp b/src/libs/installer/packagesource.cpp
new file mode 100644
index 000000000..f60c5c8e1
--- /dev/null
+++ b/src/libs/installer/packagesource.cpp
@@ -0,0 +1,91 @@
+/**************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "packagesource.h"
+
+namespace QInstaller {
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::PackageSource
+ \brief The PackageSource class specifies a single package source.
+
+ An package source represents a link to an repository that contains packages applicable by
+ the installer or package maintenance application. This structure describes a single package
+ source in terms of url and priority. While different repositories can host the same packages,
+ packages coming from a higher priority source take precedence over lower priority packages
+ during applicable package computation.
+*/
+
+/*!
+ \fn PackageSource::PackageSource()
+
+ Constructs an empty package source info object. The object's priority is set to -1. The url is
+ initialized using a \l{default-constructed value}.
+*/
+
+/*!
+ \fn PackageSource::PackageSource(const QUrl &u, int p)
+
+ Constructs an package source info object. The object's url is set to \a u, while the priority
+ is set to \a p.
+*/
+
+/*!
+ \variable PackageSource::url
+ \brief The URL of the package source.
+*/
+
+/*!
+ \variable PackageSource::priority
+ \brief The priority of the package source.
+*/
+
+/*!
+ Returns the hash value for the \a key, using \a seed to seed the calculation.
+*/
+uint qHash(const PackageSource &key, uint seed)
+{
+ return qHash(key.url, seed) ^ key.priority;
+}
+
+/*!
+ Returns \c true if \a lhs and \a rhs are equal; otherwise returns \c false.
+*/
+bool operator==(const PackageSource &lhs, const PackageSource &rhs)
+{
+ return lhs.url == rhs.url && lhs.priority == rhs.priority;
+}
+
+} // namespace QInstaller
diff --git a/src/libs/installer/packagesource.h b/src/libs/installer/packagesource.h
new file mode 100644
index 000000000..6bc565c15
--- /dev/null
+++ b/src/libs/installer/packagesource.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#ifndef PACKAGESOURCE_H
+#define PACKAGESOURCE_H
+
+#include "installer_global.h"
+
+#include <QUrl>
+
+namespace QInstaller {
+
+struct INSTALLER_EXPORT PackageSource
+{
+ PackageSource()
+ : priority(-1)
+ {}
+ PackageSource(const QUrl &u, int p)
+ : url(u)
+ , priority(p)
+ {}
+
+ QUrl url;
+ int priority;
+};
+
+INSTALLER_EXPORT uint qHash(const PackageSource &key, uint seed);
+INSTALLER_EXPORT bool operator==(const PackageSource &lhs, const PackageSource &rhs);
+
+} // namespace QInstaller
+
+#endif // PACKAGESOURCE_H
diff --git a/src/libs/installer/performinstallationform.cpp b/src/libs/installer/performinstallationform.cpp
index bf5a74985..b66cbb5bd 100644
--- a/src/libs/installer/performinstallationform.cpp
+++ b/src/libs/installer/performinstallationform.cpp
@@ -117,13 +117,13 @@ void PerformInstallationForm::setupUi(QWidget *widget)
m_downloadStatus->setObjectName(QLatin1String("DownloadStatus"));
m_downloadStatus->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
topLayout->addWidget(m_downloadStatus);
- connect(ProgressCoordinator::instance(), SIGNAL(downloadStatusChanged(QString)), this,
- SLOT(onDownloadStatusChanged(QString)));
+ connect(ProgressCoordinator::instance(), &ProgressCoordinator::downloadStatusChanged, this,
+ &PerformInstallationForm::onDownloadStatusChanged);
m_detailsButton = new QPushButton(tr("&Show Details"), widget);
m_detailsButton->setObjectName(QLatin1String("DetailsButton"));
m_detailsButton->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
- connect(m_detailsButton, SIGNAL(clicked()), this, SLOT(toggleDetails()));
+ connect(m_detailsButton, &QAbstractButton::clicked, this, &PerformInstallationForm::toggleDetails);
topLayout->addWidget(m_detailsButton);
QVBoxLayout *bottomLayout = new QVBoxLayout();
@@ -142,7 +142,8 @@ void PerformInstallationForm::setupUi(QWidget *widget)
baseLayout->addLayout(bottomLayout);
m_updateTimer = new QTimer(widget);
- connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(updateProgress())); //updateProgress includes label
+ connect(m_updateTimer, &QTimer::timeout,
+ this, &PerformInstallationForm::updateProgress); //updateProgress includes label
m_updateTimer->setInterval(30);
m_progressBar->setRange(0, 100);
@@ -176,7 +177,7 @@ void PerformInstallationForm::updateProgress()
m_progressBar->setValue(progressPercentage);
#ifdef Q_OS_WIN
if (m_taskButton) {
- if (!m_taskButton->window())
+ if (!m_taskButton->window() && QApplication::activeWindow())
m_taskButton->setWindow(QApplication::activeWindow()->windowHandle());
m_taskButton->progress()->setValue(progressPercentage);
}
diff --git a/src/libs/installer/productkeycheck.cpp b/src/libs/installer/productkeycheck.cpp
index 4a8ce4677..c1dfe83d6 100644
--- a/src/libs/installer/productkeycheck.cpp
+++ b/src/libs/installer/productkeycheck.cpp
@@ -101,3 +101,8 @@ QList<int> ProductKeyCheck::registeredPages() const
{
return QList<int>();
}
+
+bool ProductKeyCheck::hasValidLicense() const
+{
+ return true;
+}
diff --git a/src/libs/installer/productkeycheck.h b/src/libs/installer/productkeycheck.h
index 221fdc7ef..b7e8c6d52 100644
--- a/src/libs/installer/productkeycheck.h
+++ b/src/libs/installer/productkeycheck.h
@@ -66,6 +66,7 @@ public:
bool isValidPackage(const QString &packageName) const;
QList<int> registeredPages() const;
+ bool hasValidLicense() const;
private:
ProductKeyCheck();
diff --git a/src/libs/installer/progresscoordinator.cpp b/src/libs/installer/progresscoordinator.cpp
index f94142de6..1a3f4e33f 100644
--- a/src/libs/installer/progresscoordinator.cpp
+++ b/src/libs/installer/progresscoordinator.cpp
@@ -101,7 +101,7 @@ void ProgressCoordinator::registerPartProgress(QObject *sender, const char *sign
void ProgressCoordinator::partProgressChanged(double fraction)
{
if (fraction < 0 || fraction > 1) {
- qWarning() << "The fraction is outside from possible value:" << QString::number(fraction);
+ qWarning() << "The fraction is outside from possible value:" << fraction;
return;
}
diff --git a/src/libs/installer/proxycredentialsdialog.h b/src/libs/installer/proxycredentialsdialog.h
index eaac3cacf..99dfd942c 100644
--- a/src/libs/installer/proxycredentialsdialog.h
+++ b/src/libs/installer/proxycredentialsdialog.h
@@ -30,9 +30,7 @@
#include <QDialog>
-QT_BEGIN_NAMESPACE
-class QNetworkProxy;
-QT_END_NAMESPACE
+QT_FORWARD_DECLARE_CLASS(QNetworkProxy)
namespace QInstaller {
diff --git a/src/libs/installer/qinstallerglobal.h b/src/libs/installer/qinstallerglobal.h
index 2dc1f92b3..884044db9 100644
--- a/src/libs/installer/qinstallerglobal.h
+++ b/src/libs/installer/qinstallerglobal.h
@@ -31,9 +31,9 @@
#include <installer_global.h>
-#include <kdupdaterupdate.h>
-#include <kdupdaterupdateoperation.h>
-#include <kdupdaterpackagesinfo.h>
+#include "update.h"
+#include "updateoperation.h"
+#include "localpackagehub.h"
namespace QInstaller {
@@ -55,8 +55,7 @@ typedef QList<QInstaller::Operation*> OperationList;
typedef KDUpdater::Update Package;
typedef QList<QInstaller::Package*> PackagesList;
-typedef KDUpdater::PackageInfo LocalPackage;
-typedef QHash<QString, LocalPackage> LocalPackagesHash;
+typedef QHash<QString, KDUpdater::LocalPackage> LocalPackagesHash;
} // namespace QInstaller
diff --git a/src/libs/installer/qprocesswrapper.cpp b/src/libs/installer/qprocesswrapper.cpp
index 9396a3b56..1bf60ead2 100644
--- a/src/libs/installer/qprocesswrapper.cpp
+++ b/src/libs/installer/qprocesswrapper.cpp
@@ -43,20 +43,17 @@ QProcessWrapper::QProcessWrapper(QObject *parent)
qRegisterMetaType<QProcess::ProcessState>();
m_timer.start(250);
- connect(&m_timer, SIGNAL(timeout()), this, SLOT(processSignals()));
- connect(&process, SIGNAL(bytesWritten(qint64)), SIGNAL(bytesWritten(qint64)));
- connect(&process, SIGNAL(aboutToClose()), SIGNAL(aboutToClose()));
- connect(&process, SIGNAL(readChannelFinished()), SIGNAL(readChannelFinished()));
+ connect(&m_timer, &QTimer::timeout, this, &QProcessWrapper::processSignals);
+ connect(&process, &QIODevice::bytesWritten, this, &QProcessWrapper::bytesWritten);
+ connect(&process, &QIODevice::aboutToClose, this, &QProcessWrapper::aboutToClose);
+ connect(&process, &QIODevice::readChannelFinished, this, &QProcessWrapper::readChannelFinished);
connect(&process, SIGNAL(error(QProcess::ProcessError)), SIGNAL(error(QProcess::ProcessError)));
- connect(&process, SIGNAL(readyReadStandardOutput()), SIGNAL(readyReadStandardOutput()));
- connect(&process, SIGNAL(readyReadStandardError()), SIGNAL(readyReadStandardError()));
- connect(&process, SIGNAL(finished(int)), SIGNAL(finished(int)));
- connect(&process, SIGNAL(finished(int,QProcess::ExitStatus)),
- SIGNAL(finished(int,QProcess::ExitStatus)));
- connect(&process, SIGNAL(readyRead()), SIGNAL(readyRead()));
- connect(&process, SIGNAL(started()), SIGNAL(started()));
- connect(&process, SIGNAL(stateChanged(QProcess::ProcessState)),
- SIGNAL(stateChanged(QProcess::ProcessState)));
+ connect(&process, &QProcess::readyReadStandardOutput, this, &QProcessWrapper::readyReadStandardOutput);
+ connect(&process, &QProcess::readyReadStandardError, this, &QProcessWrapper::readyReadStandardError);
+ connect(&process, SIGNAL(finished(int,QProcess::ExitStatus)), SIGNAL(finished(int,QProcess::ExitStatus)));
+ connect(&process, &QIODevice::readyRead, this, &QProcessWrapper::readyRead);
+ connect(&process, &QProcess::started, this, &QProcessWrapper::started);
+ connect(&process, &QProcess::stateChanged, this, &QProcessWrapper::stateChanged);
}
QProcessWrapper::~QProcessWrapper()
@@ -97,7 +94,6 @@ void QProcessWrapper::processSignals()
emit stateChanged(static_cast<QProcess::ProcessState> (receivedSignals.takeFirst()
.toInt()));
} else if (name == QLatin1String(Protocol::QProcessSignalFinished)) {
- emit finished(receivedSignals.first().toInt());
emit finished(receivedSignals.takeFirst().toInt(),
static_cast<QProcess::ExitStatus> (receivedSignals.takeFirst().toInt()));
}
diff --git a/src/libs/installer/qprocesswrapper.h b/src/libs/installer/qprocesswrapper.h
index 95c7fadb7..e76217eda 100644
--- a/src/libs/installer/qprocesswrapper.h
+++ b/src/libs/installer/qprocesswrapper.h
@@ -117,7 +117,6 @@ Q_SIGNALS:
void error(QProcess::ProcessError);
void readyReadStandardOutput();
void readyReadStandardError();
- void finished(int exitCode);
void finished(int exitCode, QProcess::ExitStatus exitStatus);
void readyRead();
void started();
diff --git a/src/libs/installer/qtpatch.cpp b/src/libs/installer/qtpatch.cpp
index 6bd8ab853..23ac372fd 100644
--- a/src/libs/installer/qtpatch.cpp
+++ b/src/libs/installer/qtpatch.cpp
@@ -85,8 +85,8 @@ QHash<QString, QByteArray> QtPatch::qmakeValues(const QString &qmakePath, QByteA
if (process.exitStatus() == QProcess::CrashExit) {
qWarning() << qmake.absoluteFilePath() << args
<< "crashed with exit code" << process.exitCode()
- << "standard output: " << output
- << "error output: " << process.readAllStandardError();
+ << "standard output:" << output
+ << "error output:" << process.readAllStandardError();
return qmakeValueHash;
}
qmakeValueHash = readQmakeOutput(output);
@@ -120,7 +120,7 @@ bool QtPatch::patchBinaryFile(const QString &fileName,
openFileForPatching(&file);
if (!file.isOpen()) {
qDebug() << "qpatch: warning: file" << qPrintable(fileName) << "cannot open.";
- qDebug() << qPrintable(file.errorString());
+ qDebug().noquote() << file.errorString();
return false;
}
@@ -168,8 +168,7 @@ bool QtPatch::patchTextFile(const QString &fileName,
QFile file(fileName);
if (!file.open(QFile::ReadOnly)) {
- qDebug() << QString::fromLatin1("qpatch: warning: Open the file '%1' stopped: %2").arg(
- fileName, file.errorString());
+ qDebug() << "Cannot open file" << fileName << "for patching:" << file.errorString();
return false;
}
@@ -183,7 +182,7 @@ bool QtPatch::patchTextFile(const QString &fileName,
}
if (!file.open(QFile::WriteOnly | QFile::Truncate)) {
- qDebug() << QString::fromLatin1("qpatch: error: file '%1' not writable").arg(fileName);
+ qDebug() << "File" << fileName << "not writable.";
return false;
}
@@ -203,7 +202,6 @@ bool QtPatch::openFileForPatching(QFile *file)
}
return file->openMode() == QFile::ReadWrite;
}
- qDebug() << QString::fromLatin1("qpatch: error: File '%1 is open, so it cannot be opened again.").arg(
- file->fileName());
+ qDebug() << "File" << file->fileName() << "is open, so it cannot be opened again.";
return false;
}
diff --git a/src/libs/installer/registerfiletypeoperation.cpp b/src/libs/installer/registerfiletypeoperation.cpp
index a1f55a4b5..2cfd8f9c4 100644
--- a/src/libs/installer/registerfiletypeoperation.cpp
+++ b/src/libs/installer/registerfiletypeoperation.cpp
@@ -28,6 +28,7 @@
#include "registerfiletypeoperation.h"
+#include "constants.h"
#include "packagemanagercore.h"
#include "qsettingswrapper.h"
@@ -73,7 +74,9 @@ static QVariantHash readHive(QSettingsWrapper *const settings, const QString &hi
// -- RegisterFileTypeOperation
-RegisterFileTypeOperation::RegisterFileTypeOperation()
+RegisterFileTypeOperation::RegisterFileTypeOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
+ , m_optionalArgumentsRead(false)
{
setName(QLatin1String("RegisterFileType"));
}
@@ -85,37 +88,29 @@ void RegisterFileTypeOperation::backup()
bool RegisterFileTypeOperation::performOperation()
{
#ifdef Q_OS_WIN
- QStringList args = arguments();
- QString progId = takeProgIdArgument(args);
-
- if (args.count() < 2 || args.count() > 5) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("2 to 5"), QLatin1String("")));
+ ensureOptionalArgumentsRead();
+ if (!checkArgumentCount(2, 5, tr("<extension> <command> [description [contentType [icon]]]")))
return false;
- }
+ QStringList args = arguments();
bool allUsers = false;
- PackageManagerCore *const core = value(QLatin1String("installer")).value<PackageManagerCore*>();
- if (core && core->value(QLatin1String("AllUsers")) == QLatin1String("true"))
+ PackageManagerCore *const core = packageManager();
+ if (core && core->value(scAllUsers) == scTrue)
allUsers = true;
QSettingsWrapper settings(QLatin1String(allUsers ? "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER")
, QSettingsWrapper::NativeFormat);
- const QString extension = args.at(0);
- if (progId.isEmpty())
- progId = QString::fromLatin1("%1_auto_file").arg(extension);
- const QString classesProgId = QString::fromLatin1("Software/Classes/") + progId;
- const QString classesFileType = QString::fromLatin1("Software/Classes/.%2").arg(extension);
- const QString classesApplications = QString::fromLatin1("Software/Classes/Applications/") + progId;
+ const QString classesProgId = QString::fromLatin1("Software/Classes/") + m_progId;
+ const QString classesFileType = QString::fromLatin1("Software/Classes/.%2").arg(args.at(0));
+ const QString classesApplications = QString::fromLatin1("Software/Classes/Applications/") + m_progId;
// backup old value
setValue(QLatin1String("oldType"), readHive(&settings, classesFileType));
// register new values
- settings.setValue(QString::fromLatin1("%1/Default").arg(classesFileType), progId);
- settings.setValue(QString::fromLatin1("%1/OpenWithProgIds/%2").arg(classesFileType, progId), QString());
+ settings.setValue(QString::fromLatin1("%1/Default").arg(classesFileType), m_progId);
+ settings.setValue(QString::fromLatin1("%1/OpenWithProgIds/%2").arg(classesFileType, m_progId), QString());
settings.setValue(QString::fromLatin1("%1/shell/Open/Command/Default").arg(classesProgId), args.at(1));
settings.setValue(QString::fromLatin1("%1/shell/Open/Command/Default").arg(classesApplications), args.at(1));
@@ -151,28 +146,23 @@ bool RegisterFileTypeOperation::performOperation()
bool RegisterFileTypeOperation::undoOperation()
{
#ifdef Q_OS_WIN
+ ensureOptionalArgumentsRead();
QStringList args = arguments();
- QString progId = takeProgIdArgument(args);
- if (args.count() < 2 || args.count() > 5) {
- setErrorString(tr("Register File Type: Invalid arguments"));
+ if (!checkArgumentCount(2, 5, tr("Register File Type: Invalid arguments")))
return false;
- }
bool allUsers = false;
- PackageManagerCore *const core = value(QLatin1String("installer")).value<PackageManagerCore*>();
- if (core && core->value(QLatin1String("AllUsers")) == QLatin1String("true"))
+ PackageManagerCore *const core = packageManager();
+ if (core && core->value(scAllUsers) == scTrue)
allUsers = true;
QSettingsWrapper settings(QLatin1String(allUsers ? "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER")
, QSettingsWrapper::NativeFormat);
- const QString extension = args.at(0);
- if (progId.isEmpty())
- progId = QString::fromLatin1("%1_auto_file").arg(extension);
- const QString classesProgId = QString::fromLatin1("Software/Classes/") + progId;
- const QString classesFileType = QString::fromLatin1("Software/Classes/.%2").arg(extension);
- const QString classesApplications = QString::fromLatin1("Software/Classes/Applications/") + progId;
+ const QString classesProgId = QString::fromLatin1("Software/Classes/") + m_progId;
+ const QString classesFileType = QString::fromLatin1("Software/Classes/.%2").arg(args.at(0));
+ const QString classesApplications = QString::fromLatin1("Software/Classes/Applications/") + m_progId;
// Quoting MSDN here: When uninstalling an application, the ProgIDs and most other registry information
// associated with that application should be deleted as part of the uninstallation.However, applications
@@ -194,7 +184,7 @@ bool RegisterFileTypeOperation::undoOperation()
settings.endGroup();
} else {
// some changes happened, remove the only save value we know about
- settings.remove(QString::fromLatin1("%1/OpenWithProgIds/%2").arg(classesFileType, progId));
+ settings.remove(QString::fromLatin1("%1/OpenWithProgIds/%2").arg(classesFileType, m_progId));
}
// remove ProgId and Applications entry
@@ -216,7 +206,21 @@ bool RegisterFileTypeOperation::testOperation()
return true;
}
-Operation *RegisterFileTypeOperation::clone() const
+void RegisterFileTypeOperation::ensureOptionalArgumentsRead()
{
- return new RegisterFileTypeOperation();
+#ifdef Q_OS_WIN
+ if (m_optionalArgumentsRead)
+ return;
+
+ m_optionalArgumentsRead = true;
+
+ QStringList args = arguments();
+
+ m_progId = takeProgIdArgument(args);
+
+ if (m_progId.isEmpty() && args.count() > 0)
+ m_progId = QString::fromLatin1("%1_auto_file").arg(args.at(0));
+
+ setArguments(args);
+#endif
}
diff --git a/src/libs/installer/registerfiletypeoperation.h b/src/libs/installer/registerfiletypeoperation.h
index de82dedd5..8850ab44b 100644
--- a/src/libs/installer/registerfiletypeoperation.h
+++ b/src/libs/installer/registerfiletypeoperation.h
@@ -38,13 +38,18 @@ class INSTALLER_EXPORT RegisterFileTypeOperation : public QObject, public Operat
Q_OBJECT
public:
- RegisterFileTypeOperation();
+ explicit RegisterFileTypeOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
+
+private:
+ void ensureOptionalArgumentsRead();
+
+ bool m_optionalArgumentsRead;
+ QString m_progId;
};
}
diff --git a/src/libs/installer/remoteclient.cpp b/src/libs/installer/remoteclient.cpp
index 666cd813a..c6f5e535f 100644
--- a/src/libs/installer/remoteclient.cpp
+++ b/src/libs/installer/remoteclient.cpp
@@ -31,6 +31,8 @@
namespace QInstaller {
+RemoteClient *RemoteClient::s_instance = 0;
+
RemoteClient::RemoteClient()
: d_ptr(new RemoteClientPrivate(this))
{
@@ -42,8 +44,9 @@ RemoteClient::~RemoteClient()
RemoteClient &RemoteClient::instance()
{
- static RemoteClient instance;
- return instance;
+ if (!s_instance)
+ s_instance = new RemoteClient;
+ return *s_instance;
}
QString RemoteClient::socketName() const
@@ -69,6 +72,12 @@ void RemoteClient::init(const QString &socketName, const QString &key, Protocol:
d->init(socketName, key, mode, startAs);
}
+void RemoteClient::setAuthorizationFallbackDisabled(bool disabled)
+{
+ Q_D(RemoteClient);
+ d->setAuthorizationFallbackDisabled(disabled);
+}
+
void RemoteClient::shutdown()
{
Q_D(RemoteClient);
@@ -76,6 +85,12 @@ void RemoteClient::shutdown()
d_ptr.reset(new RemoteClientPrivate(this));
}
+void RemoteClient::destroy()
+{
+ delete s_instance;
+ s_instance = 0;
+}
+
bool RemoteClient::isActive() const
{
Q_D(const RemoteClient);
diff --git a/src/libs/installer/remoteclient.h b/src/libs/installer/remoteclient.h
index 4d435098c..c2090bf98 100644
--- a/src/libs/installer/remoteclient.h
+++ b/src/libs/installer/remoteclient.h
@@ -47,8 +47,10 @@ public:
static RemoteClient &instance();
void init(const QString &socketName, const QString &key, Protocol::Mode mode,
Protocol::StartAs startAs);
+ void setAuthorizationFallbackDisabled(bool disabled);
void shutdown();
+ void destroy();
QString socketName() const;
QString authorizationKey() const;
@@ -61,6 +63,7 @@ private:
~RemoteClient();
private:
+ static RemoteClient *s_instance;
QScopedPointer<RemoteClientPrivate> d_ptr;
};
diff --git a/src/libs/installer/remoteclient_p.h b/src/libs/installer/remoteclient_p.h
index 0afd9dc16..d1e873d43 100644
--- a/src/libs/installer/remoteclient_p.h
+++ b/src/libs/installer/remoteclient_p.h
@@ -59,6 +59,7 @@ public:
, m_active(false)
, m_key(QLatin1String(Protocol::DefaultAuthorizationKey))
, m_mode(Protocol::Mode::Debug)
+ , m_authorizationFallbackDisabled(false)
{
m_thread.setObjectName(QLatin1String("KeepAlive"));
}
@@ -101,6 +102,11 @@ public:
}
}
+ void setAuthorizationFallbackDisabled(bool disabled)
+ {
+ m_authorizationFallbackDisabled = disabled;
+ }
+
void maybeStartServer() {
if (m_mode == Protocol::Mode::Debug)
m_serverStarted = true; // we expect the server to be started by the developer
@@ -118,6 +124,16 @@ public:
started = AdminAuthorization::execute(0, m_serverCommand, m_serverArguments);
if (!started) {
+ if (m_authorizationFallbackDisabled) {
+ MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
+ QLatin1String("AuthorizationError"),
+ QCoreApplication::translate("RemoteClient", "Cannot get authorization."),
+ QCoreApplication::translate("RemoteClient",
+ "Cannot get authorization that is needed for continuing the installation.\n\n"
+ "Please start the setup program as a user with the appropriate rights.\n"
+ "Or accept the elevation of access rights if being asked."));
+ return;
+ }
// something went wrong with authorizing, either user pressed cancel or entered
// wrong password
const QString fallback = m_serverCommand + QLatin1String(" ") + m_serverArguments
@@ -126,11 +142,11 @@ public:
const QMessageBox::Button res =
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
QLatin1String("AuthorizationError"),
- QCoreApplication::translate("RemoteClient", "Could not get authorization."),
- QCoreApplication::translate("RemoteClient", "Could not get authorization that "
+ QCoreApplication::translate("RemoteClient", "Cannot get authorization."),
+ QCoreApplication::translate("RemoteClient", "Cannot get authorization that "
"is needed for continuing the installation.\n Either abort the "
- "installation or use the fallback solution by running\n\n%1\n\nas root "
- "and then clicking OK.").arg(fallback),
+ "installation or use the fallback solution by running\n\n%1\n\nas a user "
+ "with the appropriate rights and then clicking OK.").arg(fallback),
QMessageBox::Abort | QMessageBox::Ok, QMessageBox::Ok);
if (res == QMessageBox::Ok)
@@ -179,6 +195,7 @@ private:
QString m_key;
QThread m_thread;
Protocol::Mode m_mode;
+ bool m_authorizationFallbackDisabled;
};
} // namespace QInstaller
diff --git a/src/libs/installer/remoteobject.cpp b/src/libs/installer/remoteobject.cpp
index 69cc66e65..49c111610 100644
--- a/src/libs/installer/remoteobject.cpp
+++ b/src/libs/installer/remoteobject.cpp
@@ -30,7 +30,6 @@
#include "protocol.h"
#include "remoteclient.h"
-#include "localsocket.h"
#include <QCoreApplication>
#include <QElapsedTimer>
@@ -52,7 +51,8 @@ RemoteObject::~RemoteObject()
{
if (m_socket) {
if (QThread::currentThread() == m_socket->thread()) {
- writeData(QLatin1String(Protocol::Destroy), m_type, dummy, dummy);
+ if (m_type != QLatin1String("RemoteClientPrivate"))
+ writeData(QLatin1String(Protocol::Destroy), m_type, dummy, dummy);
} else {
Q_ASSERT_X(false, Q_FUNC_INFO, "Socket running in a different Thread than this object.");
}
@@ -68,7 +68,7 @@ bool RemoteObject::authorize()
if (m_socket)
delete m_socket;
- m_socket = new LocalSocket;
+ m_socket = new QLocalSocket;
m_socket->connectToServer(RemoteClient::instance().socketName());
if (m_socket->waitForConnected()) {
diff --git a/src/libs/installer/remoteobject.h b/src/libs/installer/remoteobject.h
index 832e3ccf3..ecd86c984 100644
--- a/src/libs/installer/remoteobject.h
+++ b/src/libs/installer/remoteobject.h
@@ -93,7 +93,7 @@ public:
QByteArray data;
while (!receivePacket(m_socket, &command, &data)) {
if (!m_socket->waitForReadyRead(-1)) {
- throw Error(tr("Could not read all data after sending command: %1. "
+ throw Error(tr("Cannot read all data after sending command: %1. "
"Bytes expected: %2, Bytes received: %3. Error: %4").arg(name).arg(0)
.arg(m_socket->bytesAvailable()).arg(m_socket->errorString()));
}
diff --git a/src/libs/installer/remoteserver.cpp b/src/libs/installer/remoteserver.cpp
index 3cd3d0248..9d178ca06 100644
--- a/src/libs/installer/remoteserver.cpp
+++ b/src/libs/installer/remoteserver.cpp
@@ -75,13 +75,13 @@ void RemoteServer::start()
d->m_localServer = new LocalServer(d->m_socketName, d->m_key);
d->m_localServer->moveToThread(&d->m_thread);
- connect(&d->m_thread, SIGNAL(finished()), d->m_localServer, SLOT(deleteLater()));
- connect(d->m_localServer, SIGNAL(newIncomingConnection()), this, SLOT(restartWatchdog()));
- connect(d->m_localServer, SIGNAL(shutdownRequested()), this, SLOT(deleteLater()));
+ connect(&d->m_thread, &QThread::finished, d->m_localServer, &QObject::deleteLater);
+ connect(d->m_localServer, &LocalServer::newIncomingConnection, this, &RemoteServer::restartWatchdog);
+ connect(d->m_localServer, &LocalServer::shutdownRequested, this, &QObject::deleteLater);
d->m_thread.start();
if (d->m_mode == Protocol::Mode::Production) {
- connect(d->m_watchdog.data(), SIGNAL(timeout()), this, SLOT(deleteLater()));
+ connect(d->m_watchdog.data(), &QTimer::timeout, this, &QObject::deleteLater);
d->m_watchdog->start();
}
}
diff --git a/src/libs/installer/remoteserver_p.h b/src/libs/installer/remoteserver_p.h
index 2660f1219..e39350f2f 100644
--- a/src/libs/installer/remoteserver_p.h
+++ b/src/libs/installer/remoteserver_p.h
@@ -79,9 +79,9 @@ private:
if (m_shutdown)
return;
- QThread *const thread = new RemoteServerConnection(socketDescriptor, m_key, this);
- connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
- connect(thread, SIGNAL(shutdownRequested()), this, SLOT(shutdown()));
+ RemoteServerConnection *thread = new RemoteServerConnection(socketDescriptor, m_key, this);
+ connect(thread, &QThread::finished, thread, &QObject::deleteLater);
+ connect(thread, &RemoteServerConnection::shutdownRequested, this, &LocalServer::shutdown);
thread->start();
emit newIncomingConnection();
}
diff --git a/src/libs/installer/remoteserverconnection.cpp b/src/libs/installer/remoteserverconnection.cpp
index 5236657e2..61bacc0c5 100644
--- a/src/libs/installer/remoteserverconnection.cpp
+++ b/src/libs/installer/remoteserverconnection.cpp
@@ -33,7 +33,6 @@
#include "remoteserverconnection_p.h"
#include "utils.h"
#include "permissionsettings.h"
-#include "localsocket.h"
#include <QCoreApplication>
#include <QDataStream>
@@ -66,7 +65,7 @@ private:
void RemoteServerConnection::run()
{
- LocalSocket socket;
+ QLocalSocket socket;
socket.setSocketDescriptor(m_socketDescriptor);
QScopedPointer<PermissionSettings> settings;
@@ -144,11 +143,11 @@ void RemoteServerConnection::run()
stream >> type;
if (type == QLatin1String(Protocol::QSettings)) {
settings.reset();
- } else if (command == QLatin1String(Protocol::QProcess)) {
+ } else if (type == QLatin1String(Protocol::QProcess)) {
m_signalReceiver->m_receivedSignals.clear();
m_process->deleteLater();
m_process = 0;
- } else if (command == QLatin1String(Protocol::QAbstractFileEngine)) {
+ } else if (type == QLatin1String(Protocol::QAbstractFileEngine)) {
delete m_engine;
m_engine = 0;
}
diff --git a/src/libs/installer/remoteserverconnection_p.h b/src/libs/installer/remoteserverconnection_p.h
index d8334d566..dad5f4133 100644
--- a/src/libs/installer/remoteserverconnection_p.h
+++ b/src/libs/installer/remoteserverconnection_p.h
@@ -46,19 +46,21 @@ private:
explicit QProcessSignalReceiver(QProcess *process)
: QObject(process)
{
- connect(process, SIGNAL(bytesWritten(qint64)), SLOT(onBytesWritten(qint64)));
- connect(process, SIGNAL(aboutToClose()), SLOT(onAboutToClose()));
- connect(process, SIGNAL(readChannelFinished()), SLOT(onReadChannelFinished()));
+ connect(process, &QIODevice::bytesWritten, this, &QProcessSignalReceiver::onBytesWritten);
+ connect(process, &QIODevice::aboutToClose, this, &QProcessSignalReceiver::onAboutToClose);
+ connect(process, &QIODevice::readChannelFinished, this, &QProcessSignalReceiver::onReadChannelFinished);
connect(process, SIGNAL(error(QProcess::ProcessError)),
SLOT(onError(QProcess::ProcessError)));
- connect(process, SIGNAL(readyReadStandardOutput()), SLOT(onReadyReadStandardOutput()));
- connect(process, SIGNAL(readyReadStandardError()), SLOT(onReadyReadStandardError()));
- connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
- SLOT(onFinished(int, QProcess::ExitStatus)));
- connect(process, SIGNAL(readyRead()), SLOT(onReadyRead()));
- connect(process, SIGNAL(started()), SLOT(onStarted()));
- connect(process, SIGNAL(stateChanged(QProcess::ProcessState)),
- SLOT(onStateChanged(QProcess::ProcessState)));
+ connect(process, &QProcess::readyReadStandardOutput,
+ this, &QProcessSignalReceiver::onReadyReadStandardOutput);
+ connect(process, &QProcess::readyReadStandardError,
+ this, &QProcessSignalReceiver::onReadyReadStandardError);
+ connect(process, SIGNAL(finished(int,QProcess::ExitStatus)),
+ SLOT(onFinished(int,QProcess::ExitStatus)));
+ connect(process, &QIODevice::readyRead, this, &QProcessSignalReceiver::onReadyRead);
+ connect(process, &QProcess::started, this, &QProcessSignalReceiver::onStarted);
+ connect(process, &QProcess::stateChanged,
+ this, &QProcessSignalReceiver::onStateChanged);
}
private Q_SLOTS:
diff --git a/src/libs/installer/replaceoperation.cpp b/src/libs/installer/replaceoperation.cpp
index 946711feb..8cc1e0315 100644
--- a/src/libs/installer/replaceoperation.cpp
+++ b/src/libs/installer/replaceoperation.cpp
@@ -34,7 +34,8 @@
using namespace QInstaller;
-ReplaceOperation::ReplaceOperation()
+ReplaceOperation::ReplaceOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("Replace"));
}
@@ -45,18 +46,14 @@ void ReplaceOperation::backup()
bool ReplaceOperation::performOperation()
{
- const QStringList args = arguments();
-
// Arguments:
// 1. filename
// 2. Source-String
// 3. Replace-String
- if (args.count() != 3) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("exactly 3"), QLatin1String("")));
+ if (!checkArgumentCount(3))
return false;
- }
+
+ const QStringList args = arguments();
const QString fileName = args.at(0);
const QString before = args.at(1);
const QString after = args.at(2);
@@ -64,7 +61,8 @@ bool ReplaceOperation::performOperation()
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
setError(UserDefinedError);
- setErrorString(tr("Failed to open %1 for reading").arg(fileName));
+ setErrorString(tr("Cannot open file \"%1\" for reading: %2").arg(
+ QDir::toNativeSeparators(fileName), file.errorString()));
return false;
}
@@ -74,7 +72,8 @@ bool ReplaceOperation::performOperation()
if (!file.open(QIODevice::WriteOnly)) {
setError(UserDefinedError);
- setErrorString(tr("Failed to open %1 for writing").arg(fileName));
+ setErrorString(tr("Cannot open file \"%1\" for writing: %2").arg(
+ QDir::toNativeSeparators(fileName), file.errorString()));
return false;
}
@@ -95,8 +94,3 @@ bool ReplaceOperation::testOperation()
{
return true;
}
-
-Operation *ReplaceOperation::clone() const
-{
- return new ReplaceOperation();
-}
diff --git a/src/libs/installer/replaceoperation.h b/src/libs/installer/replaceoperation.h
index 0ad614697..0d2783ab6 100644
--- a/src/libs/installer/replaceoperation.h
+++ b/src/libs/installer/replaceoperation.h
@@ -37,13 +37,12 @@ class INSTALLER_EXPORT ReplaceOperation : public Operation
{
Q_DECLARE_TR_FUNCTIONS(QInstaller::ReplaceOperation)
public:
- ReplaceOperation();
+ explicit ReplaceOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
};
} // namespace QInstaller
diff --git a/src/libs/installer/repository.cpp b/src/libs/installer/repository.cpp
index 0bfa23a96..eb45573a9 100644
--- a/src/libs/installer/repository.cpp
+++ b/src/libs/installer/repository.cpp
@@ -27,7 +27,7 @@
**************************************************************************/
#include "repository.h"
-#include "kdupdaterfiledownloaderfactory.h"
+#include "filedownloaderfactory.h"
#include <QDataStream>
#include <QFileInfo>
@@ -41,6 +41,7 @@ namespace QInstaller {
Repository::Repository()
: m_default(false)
, m_enabled(false)
+ , m_compressed(false)
{
registerMetaType();
}
@@ -55,28 +56,31 @@ Repository::Repository(const Repository &other)
, m_username(other.m_username)
, m_password(other.m_password)
, m_displayname(other.m_displayname)
+ , m_compressed(other.m_compressed)
{
registerMetaType();
}
/*!
- Constructs a new repository by setting its address to \a url and its default state.
+ Constructs a new repository by setting its address to \a url
+ and its default and \a compressed states.
*/
-Repository::Repository(const QUrl &url, bool isDefault)
+Repository::Repository(const QUrl &url, bool isDefault, bool compressed)
: m_url(url)
, m_default(isDefault)
, m_enabled(true)
+ , m_compressed(compressed)
{
registerMetaType();
}
/*!
- Constructs a new repository by setting its address to \a repositoryUrl as string and its
- default state.
+ Constructs a new repository by setting its address to \a repositoryUrl as
+ string and its \a compressed state.
Note: user and password can be inside the \a repositoryUrl string: http://user:password@repository.url
*/
-Repository Repository::fromUserInput(const QString &repositoryUrl)
+Repository Repository::fromUserInput(const QString &repositoryUrl, bool compressed)
{
QUrl url = QUrl::fromUserInput(repositoryUrl);
const QStringList supportedSchemes = KDUpdater::FileDownloaderFactory::supportedSchemes();
@@ -88,7 +92,7 @@ Repository Repository::fromUserInput(const QString &repositoryUrl)
url.setUserName(QString());
url.setPassword(QString());
- Repository repository(url, false);
+ Repository repository(url, false, compressed);
repository.setUsername(userName);
repository.setPassword(password);
return repository;
@@ -195,6 +199,22 @@ void Repository::setDisplayName(const QString &displayname)
}
/*!
+ Returns true if repository is compressed
+*/
+bool Repository::isCompressed() const
+{
+ return m_compressed;
+}
+
+/*!
+ Sets this repository to \a compressed state to know weather the repository
+ needs to be uncompressed before use.
+*/
+void Repository::setCompressed(bool compressed)
+{
+ m_compressed = compressed;
+}
+/*!
Compares the values of this repository to \a other and returns true if they are equal (same server,
default state, enabled state as well as username and password). \sa operator!=()
*/
@@ -227,6 +247,7 @@ const Repository &Repository::operator=(const Repository &other)
m_username = other.m_username;
m_password = other.m_password;
m_displayname = other.m_displayname;
+ m_compressed = other.m_compressed;
return *this;
}
@@ -239,7 +260,7 @@ void Repository::registerMetaType()
QDataStream &operator>>(QDataStream &istream, Repository &repository)
{
- QByteArray url, username, password, displayname;
+ QByteArray url, username, password, displayname, compressed;
istream >> url >> repository.m_default >> repository.m_enabled >> username >> password >> displayname;
repository.setUrl(QUrl::fromEncoded(QByteArray::fromBase64(url)));
repository.setUsername(QString::fromUtf8(QByteArray::fromBase64(username)));
diff --git a/src/libs/installer/repository.h b/src/libs/installer/repository.h
index 89b18f612..b73e7bd4c 100644
--- a/src/libs/installer/repository.h
+++ b/src/libs/installer/repository.h
@@ -41,10 +41,10 @@ class INSTALLER_EXPORT Repository
public:
explicit Repository();
Repository(const Repository &other);
- explicit Repository(const QUrl &url, bool isDefault);
+ explicit Repository(const QUrl &url, bool isDefault, bool compressed = false);
static void registerMetaType();
- static Repository fromUserInput(const QString &repositoryUrl);
+ static Repository fromUserInput(const QString &repositoryUrl, bool compressed = false);
bool isValid() const;
bool isDefault() const;
@@ -64,6 +64,8 @@ public:
QString displayname() const;
void setDisplayName(const QString &displayname);
+ bool isCompressed() const;
+ void setCompressed(bool compressed);
bool operator==(const Repository &other) const;
bool operator!=(const Repository &other) const;
@@ -80,6 +82,7 @@ private:
QString m_username;
QString m_password;
QString m_displayname;
+ bool m_compressed;
};
inline uint qHash(const Repository &repository)
diff --git a/src/libs/installer/resources/install.png b/src/libs/installer/resources/install.png
new file mode 100644
index 000000000..8e3309c9f
--- /dev/null
+++ b/src/libs/installer/resources/install.png
Binary files differ
diff --git a/src/libs/installer/resources/installer.qrc b/src/libs/installer/resources/installer.qrc
index 77bf00f65..48a7c65bd 100644
--- a/src/libs/installer/resources/installer.qrc
+++ b/src/libs/installer/resources/installer.qrc
@@ -3,5 +3,9 @@
<file>installer.png</file>
<file>installer.ico</file>
<file>installer.icns</file>
+ <file>install.png</file>
+ <file>uninstall.png</file>
+ <file>keepinstalled.png</file>
+ <file>keepuninstalled.png</file>
</qresource>
</RCC>
diff --git a/src/libs/installer/resources/keepinstalled.png b/src/libs/installer/resources/keepinstalled.png
new file mode 100644
index 000000000..7f8489e28
--- /dev/null
+++ b/src/libs/installer/resources/keepinstalled.png
Binary files differ
diff --git a/src/libs/installer/resources/keepuninstalled.png b/src/libs/installer/resources/keepuninstalled.png
new file mode 100644
index 000000000..2753092cc
--- /dev/null
+++ b/src/libs/installer/resources/keepuninstalled.png
Binary files differ
diff --git a/src/libs/installer/resources/uninstall.png b/src/libs/installer/resources/uninstall.png
new file mode 100644
index 000000000..5646770da
--- /dev/null
+++ b/src/libs/installer/resources/uninstall.png
Binary files differ
diff --git a/src/libs/installer/scriptengine.cpp b/src/libs/installer/scriptengine.cpp
index d099ba218..59f71a52c 100644
--- a/src/libs/installer/scriptengine.cpp
+++ b/src/libs/installer/scriptengine.cpp
@@ -198,6 +198,21 @@ QList<QJSValue> GuiProxy::findChildren(QObject *parent, const QString &objectNam
return children;
}
+/*!
+ Hides the GUI when \a silent is \c true.
+*/
+void GuiProxy::setSilent(bool silent)
+{
+ if (m_gui)
+ m_gui->setSilent(silent);
+}
+
+void GuiProxy::setTextItems(QObject *object, const QStringList &items)
+{
+ if (m_gui)
+ m_gui->setTextItems(object, items);
+}
+
void GuiProxy::cancelButtonClicked()
{
if (m_gui)
@@ -260,7 +275,7 @@ ScriptEngine::ScriptEngine(PackageManagerCore *core) :
setGuiQObject(core->guiObject());
QQmlEngine::setObjectOwnership(core, QQmlEngine::CppOwnership);
global.setProperty(QLatin1String("installer"), m_engine.newQObject(core));
- connect(core, SIGNAL(guiObjectChanged(QObject*)), this, SLOT(setGuiQObject(QObject*)));
+ connect(core, &PackageManagerCore::guiObjectChanged, this, &ScriptEngine::setGuiQObject);
} else {
global.setProperty(QLatin1String("installer"), m_engine.newQObject(new QObject));
}
@@ -366,7 +381,7 @@ QJSValue ScriptEngine::loadInContext(const QString &context, const QString &file
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
- throw Error(tr("Could not open the requested script file at %1: %2.")
+ throw Error(tr("Cannot open script file at %1: %2")
.arg(fileName, file.errorString()));
}
@@ -384,9 +399,10 @@ QJSValue ScriptEngine::loadInContext(const QString &context, const QString &file
QJSValue scriptContext = evaluate(scriptContent, fileName);
scriptContext.setProperty(QLatin1String("Uuid"), QUuid::createUuid().toString());
if (scriptContext.isError()) {
- throw Error(tr("Exception while loading the component script '%1'. (%2)").arg(
- QFileInfo(file).absoluteFilePath(), scriptContext.toString().isEmpty() ?
- QString::fromLatin1("Unknown error.") : scriptContext.toString()));
+ throw Error(tr("Exception while loading the component script \"%1\": %2").arg(
+ QDir::toNativeSeparators(QFileInfo(file).absoluteFilePath()),
+ scriptContext.toString().isEmpty() ?
+ tr("Unknown error.") : scriptContext.toString()));
}
return scriptContext;
}
diff --git a/src/libs/installer/scriptengine_p.h b/src/libs/installer/scriptengine_p.h
index 2d76912d4..7af5cbab8 100644
--- a/src/libs/installer/scriptengine_p.h
+++ b/src/libs/installer/scriptengine_p.h
@@ -49,7 +49,7 @@ public:
ConsoleProxy() {}
public slots :
- void log(const QString &log) { qDebug() << log; }
+ void log(const QString &log) { qDebug().noquote() << log; }
};
class InstallerProxy : public QObject
@@ -153,6 +153,10 @@ public:
Q_INVOKABLE QJSValue findChild(QObject *parent, const QString &objectName);
Q_INVOKABLE QList<QJSValue> findChildren(QObject *parent, const QString &objectName);
+ Q_INVOKABLE void setSilent(bool silent);
+
+ Q_INVOKABLE void setTextItems(QObject *object, const QStringList &items);
+
signals:
void interrupted();
void languageChanged();
diff --git a/src/libs/installer/selfrestartoperation.cpp b/src/libs/installer/selfrestartoperation.cpp
index 1d7c16f23..586e5bb0b 100644
--- a/src/libs/installer/selfrestartoperation.cpp
+++ b/src/libs/installer/selfrestartoperation.cpp
@@ -29,30 +29,31 @@
#include "selfrestartoperation.h"
#include "packagemanagercore.h"
-#include <kdselfrestarter.h>
+#include "selfrestarter.h"
using namespace QInstaller;
-SelfRestartOperation::SelfRestartOperation()
+SelfRestartOperation::SelfRestartOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("SelfRestart"));
}
void SelfRestartOperation::backup()
{
- setValue(QLatin1String("PreviousSelfRestart"), KDSelfRestarter::restartOnQuit());
+ setValue(QLatin1String("PreviousSelfRestart"), SelfRestarter::restartOnQuit());
}
bool SelfRestartOperation::performOperation()
{
- PackageManagerCore *const core = value(QLatin1String("installer")).value<PackageManagerCore*>();
+ PackageManagerCore *const core = packageManager();
if (!core) {
setError(UserDefinedError);
- setErrorString(tr("Installer object needed in '%1' operation is empty.").arg(name()));
+ setErrorString(tr("Installer object needed in operation %1 is empty.").arg(name()));
return false;
}
- if (!core->isUpdater() && !core->isPackageManager()) {
+ if (!core->isMaintainer()) {
setError(UserDefinedError);
setErrorString(tr("Self Restart: Only valid within updater or packagemanager mode."));
return false;
@@ -63,13 +64,13 @@ bool SelfRestartOperation::performOperation()
setErrorString(tr("Self Restart: Invalid arguments"));
return false;
}
- KDSelfRestarter::setRestartOnQuit(true);
- return KDSelfRestarter::restartOnQuit();
+ SelfRestarter::setRestartOnQuit(true);
+ return SelfRestarter::restartOnQuit();
}
bool SelfRestartOperation::undoOperation()
{
- KDSelfRestarter::setRestartOnQuit(value(QLatin1String("PreviousSelfRestart")).toBool());
+ SelfRestarter::setRestartOnQuit(value(QLatin1String("PreviousSelfRestart")).toBool());
return true;
}
@@ -77,8 +78,3 @@ bool SelfRestartOperation::testOperation()
{
return true;
}
-
-Operation *SelfRestartOperation::clone() const
-{
- return new SelfRestartOperation();
-}
diff --git a/src/libs/installer/selfrestartoperation.h b/src/libs/installer/selfrestartoperation.h
index 54a05f3d1..7adccd183 100644
--- a/src/libs/installer/selfrestartoperation.h
+++ b/src/libs/installer/selfrestartoperation.h
@@ -37,13 +37,12 @@ class INSTALLER_EXPORT SelfRestartOperation : public Operation
{
Q_DECLARE_TR_FUNCTIONS(QInstaller::SelfRestartOperation)
public:
- SelfRestartOperation();
+ explicit SelfRestartOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
};
}
diff --git a/src/libs/installer/settings.cpp b/src/libs/installer/settings.cpp
index 95f32afbf..79d4bcddc 100644
--- a/src/libs/installer/settings.cpp
+++ b/src/libs/installer/settings.cpp
@@ -33,6 +33,8 @@
#include <QtCore/QFileInfo>
#include <QtCore/QStringList>
+#include <QtGui/QFontMetrics>
+#include <QtWidgets/QApplication>
#include <QRegularExpression>
#include <QXmlStreamReader>
@@ -56,6 +58,7 @@ static const QLatin1String scRemoteRepositories("RemoteRepositories");
static const QLatin1String scDependsOnLocalInstallerBinary("DependsOnLocalInstallerBinary");
static const QLatin1String scTranslations("Translations");
static const QLatin1String scCreateLocalRepository("CreateLocalRepository");
+static const QLatin1String scInstallActionColumnVisible("InstallActionColumnVisible");
static const QLatin1String scFtpProxy("FtpProxy");
static const QLatin1String scHttpProxy("HttpProxy");
@@ -79,9 +82,10 @@ static void raiseError(QXmlStreamReader &reader, const QString &error, Settings:
} else {
QFile *xmlFile = qobject_cast<QFile*>(reader.device());
if (xmlFile) {
- qWarning() << QString::fromLatin1("Ignoring following settings reader error in %1, line %2, "
- "column %3: %4").arg(xmlFile->fileName()).arg(reader.lineNumber()).arg(reader.columnNumber())
- .arg(error);
+ qWarning().noquote().nospace()
+ << "Ignoring following settings reader error in " << xmlFile->fileName()
+ << ", line " << reader.lineNumber() << ", column " << reader.columnNumber()
+ << ": " << error;
} else {
qWarning("Ignoring following settings reader error: %s", qPrintable(error));
}
@@ -97,7 +101,7 @@ static QStringList readArgumentAttributes(QXmlStreamReader &reader, Settings::Pa
switch (token) {
case QXmlStreamReader::StartElement: {
if (!reader.attributes().isEmpty()) {
- raiseError(reader, QString::fromLatin1("Unexpected attribute for element '%1'.")
+ raiseError(reader, QString::fromLatin1("Unexpected attribute for element \"%1\".")
.arg(reader.name().toString()), parseMode);
return arguments;
} else {
@@ -105,7 +109,7 @@ static QStringList readArgumentAttributes(QXmlStreamReader &reader, Settings::Pa
(lc) ? arguments.append(reader.readElementText().toLower()) :
arguments.append(reader.readElementText());
} else {
- raiseError(reader, QString::fromLatin1("Unexpected element '%1'.").arg(reader.name()
+ raiseError(reader, QString::fromLatin1("Unexpected element \"%1\".").arg(reader.name()
.toString()), parseMode);
return arguments;
}
@@ -147,23 +151,23 @@ static QSet<Repository> readRepositories(QXmlStreamReader &reader, bool isDefaul
} else if (reader.name() == QLatin1String("Enabled")) {
repo.setEnabled(bool(reader.readElementText().toInt()));
} else {
- raiseError(reader, QString::fromLatin1("Unexpected element '%1'.").arg(reader.name()
+ raiseError(reader, QString::fromLatin1("Unexpected element \"%1\".").arg(reader.name()
.toString()), parseMode);
}
if (!reader.attributes().isEmpty()) {
- raiseError(reader, QString::fromLatin1("Unexpected attribute for element '%1'.")
+ raiseError(reader, QString::fromLatin1("Unexpected attribute for element \"%1\".")
.arg(reader.name().toString()), parseMode);
}
}
set.insert(repo);
} else {
- raiseError(reader, QString::fromLatin1("Unexpected element '%1'.").arg(reader.name().toString()),
+ raiseError(reader, QString::fromLatin1("Unexpected element \"%1\".").arg(reader.name().toString()),
parseMode);
}
if (!reader.attributes().isEmpty()) {
- raiseError(reader, QString::fromLatin1("Unexpected attribute for element '%1'.").arg(reader
+ raiseError(reader, QString::fromLatin1("Unexpected attribute for element \"%1\".").arg(reader
.name().toString()), parseMode);
}
}
@@ -230,12 +234,12 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix,
file.setFileName(overrideConfig.fileName());
if (!file.open(QIODevice::ReadOnly))
- throw Error(tr("Could not open settings file %1 for reading: %2").arg(path, file.errorString()));
+ throw Error(tr("Cannot open settings file %1 for reading: %2").arg(path, file.errorString()));
QXmlStreamReader reader(&file);
if (reader.readNextStartElement()) {
if (reader.name() != QLatin1String("Installer")) {
- reader.raiseError(QString::fromLatin1("Unexpected element '%1' as root element.").arg(reader
+ reader.raiseError(QString::fromLatin1("Unexpected element \"%1\" as root element.").arg(reader
.name().toString()));
}
}
@@ -247,26 +251,27 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix,
<< scStartMenuDir << scMaintenanceToolName << scMaintenanceToolIniFile << scRemoveTargetDir
<< scRunProgram << scRunProgramArguments << scRunProgramDescription
<< scDependsOnLocalInstallerBinary
- << scAllowSpaceInPath << scAllowNonAsciiCharacters << scWizardStyle << scTitleColor
+ << scAllowSpaceInPath << scAllowNonAsciiCharacters << scDisableAuthorizationFallback
+ << scWizardStyle << scStyleSheet << scTitleColor
<< scWizardDefaultWidth << scWizardDefaultHeight
<< scRepositorySettingsPageVisible << scTargetConfigurationFile
- << scRemoteRepositories << scTranslations << QLatin1String(scControlScript)
- << scCreateLocalRepository;
+ << scRemoteRepositories << scTranslations << scUrlQueryString << QLatin1String(scControlScript)
+ << scCreateLocalRepository << scInstallActionColumnVisible << scSupportsModify;
Settings s;
s.d->m_data.insert(scPrefix, prefix);
while (reader.readNextStartElement()) {
const QString name = reader.name().toString();
if (!elementList.contains(name))
- raiseError(reader, QString::fromLatin1("Unexpected element '%1'.").arg(name), parseMode);
+ raiseError(reader, QString::fromLatin1("Unexpected element \"%1\".").arg(name), parseMode);
if (!reader.attributes().isEmpty()) {
- raiseError(reader, QString::fromLatin1("Unexpected attribute for element '%1'.").arg(name),
+ raiseError(reader, QString::fromLatin1("Unexpected attribute for element \"%1\".").arg(name),
parseMode);
}
if (s.d->m_data.contains(name))
- reader.raiseError(QString::fromLatin1("Element '%1' has been defined before.").arg(name));
+ reader.raiseError(QString::fromLatin1("Element \"%1\" has been defined before.").arg(name));
if (name == scTranslations) {
s.setTranslations(readArgumentAttributes(reader, parseMode, QLatin1String("Translation"), true));
@@ -318,6 +323,8 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix,
s.d->m_data.insert(scRepositorySettingsPageVisible, true);
if (!s.d->m_data.contains(scCreateLocalRepository))
s.d->m_data.insert(scCreateLocalRepository, false);
+ if (!s.d->m_data.contains(scInstallActionColumnVisible))
+ s.d->m_data.insert(scInstallActionColumnVisible, false);
return s;
}
@@ -372,19 +379,41 @@ QString Settings::wizardStyle() const
return d->m_data.value(scWizardStyle).toString();
}
+QString Settings::styleSheet() const
+{
+ return d->absolutePathFromKey(scStyleSheet);
+}
+
QString Settings::titleColor() const
{
return d->m_data.value(scTitleColor).toString();
}
+static int lengthToInt(const QVariant &variant)
+{
+ QString length = variant.toString().trimmed();
+ if (length.endsWith(QLatin1String("em"), Qt::CaseInsensitive)) {
+ length.chop(2);
+ return qRound(length.toDouble() * QApplication::fontMetrics().height());
+ }
+ if (length.endsWith(QLatin1String("ex"), Qt::CaseInsensitive)) {
+ length.chop(2);
+ return qRound(length.toDouble() * QApplication::fontMetrics().xHeight());
+ }
+ if (length.endsWith(QLatin1String("px"), Qt::CaseInsensitive)) {
+ length.chop(2);
+ }
+ return length.toInt();
+}
+
int Settings::wizardDefaultWidth() const
{
- return d->m_data.value(scWizardDefaultWidth).toInt();
+ return lengthToInt(d->m_data.value(scWizardDefaultWidth));
}
int Settings::wizardDefaultHeight() const
{
- return d->m_data.value(scWizardDefaultHeight).toInt();
+ return lengthToInt(d->m_data.value(scWizardDefaultHeight));
}
QString Settings::installerApplicationIcon() const
@@ -472,6 +501,11 @@ bool Settings::createLocalRepository() const
return d->m_data.value(scCreateLocalRepository).toBool();
}
+bool Settings::installActionColumnVisible() const
+{
+ return d->m_data.value(scInstallActionColumnVisible, false).toBool();
+}
+
bool Settings::allowSpaceInPath() const
{
return d->m_data.value(scAllowSpaceInPath, true).toBool();
@@ -482,6 +516,11 @@ bool Settings::allowNonAsciiCharacters() const
return d->m_data.value(scAllowNonAsciiCharacters, false).toBool();
}
+bool Settings::disableAuthorizationFallback() const
+{
+ return d->m_data.value(scDisableAuthorizationFallback, false).toBool();
+}
+
bool Settings::dependsOnLocalInstallerBinary() const
{
return d->m_data.value(scDependsOnLocalInstallerBinary).toBool();
@@ -699,3 +738,8 @@ QString Settings::controlScript() const
{
return d->m_data.value(QLatin1String(scControlScript)).toString();
}
+
+bool Settings::supportsModify() const
+{
+ return d->m_data.value(scSupportsModify, true).toBool();
+}
diff --git a/src/libs/installer/settings.h b/src/libs/installer/settings.h
index 0fa938167..3dc1c99c3 100644
--- a/src/libs/installer/settings.h
+++ b/src/libs/installer/settings.h
@@ -83,6 +83,7 @@ public:
QString installerWindowIcon() const;
QString systemIconSuffix() const;
QString wizardStyle() const;
+ QString styleSheet() const;
QString titleColor() const;
int wizardDefaultWidth() const;
int wizardDefaultHeight() const;
@@ -106,6 +107,7 @@ public:
QString configurationFileName() const;
bool createLocalRepository() const;
+ bool installActionColumnVisible() const;
bool dependsOnLocalInstallerBinary() const;
bool hasReplacementRepos() const;
@@ -127,6 +129,7 @@ public:
bool allowSpaceInPath() const;
bool allowNonAsciiCharacters() const;
+ bool disableAuthorizationFallback() const;
bool containsValue(const QString &key) const;
QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
@@ -149,6 +152,8 @@ public:
QString controlScript() const;
+ bool supportsModify() const;
+
private:
class Private;
QSharedDataPointer<Private> d;
diff --git a/src/libs/installer/settingsoperation.cpp b/src/libs/installer/settingsoperation.cpp
index 53a5e8c8a..e6d88b71e 100644
--- a/src/libs/installer/settingsoperation.cpp
+++ b/src/libs/installer/settingsoperation.cpp
@@ -27,7 +27,7 @@
**************************************************************************/
#include "settingsoperation.h"
#include "packagemanagercore.h"
-#include "kdupdaterupdateoperations.h"
+#include "updateoperations.h"
#include "qsettingswrapper.h"
#include <QDir>
@@ -35,7 +35,8 @@
using namespace QInstaller;
-SettingsOperation::SettingsOperation()
+SettingsOperation::SettingsOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("Settings"));
}
@@ -63,7 +64,7 @@ bool SettingsOperation::checkArguments()
if (!missingArguments.isEmpty()) {
setError(InvalidArguments);
- setErrorString(tr("Missing argument(s) '%1' calling '%2' with arguments '%3'.").arg(
+ setErrorString(tr("Missing argument(s) \"%1\" calling %2 with arguments \"%3\".").arg(
missingArguments.join(QLatin1String("; ")), name(), arguments().join(QLatin1String("; "))));
return false;
}
@@ -73,7 +74,7 @@ bool SettingsOperation::checkArguments()
if (!possibleMethodValues.contains(method)) {
setError(InvalidArguments);
- setErrorString(tr("Current method argument calling '%1' with arguments '%2' is not "
+ setErrorString(tr("Current method argument calling \"%1\" with arguments \"%2\" is not "
"supported. Please use set, remove, add_array_value or remove_array_value.").arg(name(),
arguments().join(QLatin1String("; "))));
return false;
@@ -177,14 +178,14 @@ bool SettingsOperation::undoOperation()
if (cleanUp) {
QFile settingsFile(path);
if (!settingsFile.remove())
- qWarning() << settingsFile.errorString();
+ qWarning().noquote() << settingsFile.errorString();
if (!value(QLatin1String("createddir")).toString().isEmpty()) {
KDUpdater::MkdirOperation mkDirOperation;
mkDirOperation.setArguments(QStringList() << QFileInfo(path).absolutePath());
mkDirOperation.setValue(QLatin1String("createddir"), value(QLatin1String("createddir")));
if (!mkDirOperation.undoOperation()) {
- qWarning() << mkDirOperation.errorString();
+ qWarning().noquote() << mkDirOperation.errorString();
}
}
}
@@ -195,9 +196,3 @@ bool SettingsOperation::testOperation()
{
return true;
}
-
-Operation *SettingsOperation::clone() const
-{
- return new SettingsOperation();
-}
-
diff --git a/src/libs/installer/settingsoperation.h b/src/libs/installer/settingsoperation.h
index 14b0eb169..0b94ea015 100644
--- a/src/libs/installer/settingsoperation.h
+++ b/src/libs/installer/settingsoperation.h
@@ -37,13 +37,12 @@ class INSTALLER_EXPORT SettingsOperation : public Operation
{
Q_DECLARE_TR_FUNCTIONS(QInstaller::SettingsOperation)
public:
- SettingsOperation();
+ explicit SettingsOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
private:
bool checkArguments();
diff --git a/src/libs/installer/simplemovefileoperation.cpp b/src/libs/installer/simplemovefileoperation.cpp
index 5f6ea4ff3..d5cbde2ee 100644
--- a/src/libs/installer/simplemovefileoperation.cpp
+++ b/src/libs/installer/simplemovefileoperation.cpp
@@ -28,11 +28,13 @@
#include "simplemovefileoperation.h"
+#include <QDir>
#include <QtCore/QFileInfo>
namespace QInstaller {
-SimpleMoveFileOperation::SimpleMoveFileOperation()
+SimpleMoveFileOperation::SimpleMoveFileOperation(PackageManagerCore *core)
+ : UpdateOperation(core)
{
setName(QLatin1String("SimpleMoveFile"));
}
@@ -43,21 +45,17 @@ void SimpleMoveFileOperation::backup()
bool SimpleMoveFileOperation::performOperation()
{
- const QStringList args = arguments();
- if (args.count() != 2) {
- setError(InvalidArguments);
- setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("exactly 2"), QLatin1String("")));
+ if (!checkArgumentCount(2))
return false;
- }
+ const QStringList args = arguments();
const QString source = args.at(0);
const QString target = args.at(1);
if (source.isEmpty() || target.isEmpty()) {
setError(UserDefinedError);
- setErrorString(tr("None of the arguments can be empty: source '%1', target '%2'.")
- .arg(source, target));
+ setErrorString(tr("None of the arguments can be empty: source \"%1\", target \"%2\".")
+ .arg(QDir::toNativeSeparators(source), QDir::toNativeSeparators(target)));
return false;
}
@@ -67,8 +65,8 @@ bool SimpleMoveFileOperation::performOperation()
if (file.exists()) {
if (!file.remove()) {
setError(UserDefinedError);
- setErrorString(tr("Cannot move source '%1' to target '%2', because target exists and is "
- "not removable.").arg(source, target));
+ setErrorString(tr("Cannot move file from \"%1\" to \"%2\", because the target path exists and is "
+ "not removable.").arg(QDir::toNativeSeparators(source), QDir::toNativeSeparators(target)));
return false;
}
}
@@ -76,12 +74,14 @@ bool SimpleMoveFileOperation::performOperation()
file.setFileName(source);
if (!file.rename(target)) {
setError(UserDefinedError);
- setErrorString(tr("Cannot move source '%1' to target '%2': %3").arg(source, target,
- file.errorString()));
+ setErrorString(tr("Cannot move file \"%1\" to \"%2\": %3").arg(
+ QDir::toNativeSeparators(source), QDir::toNativeSeparators(target),
+ file.errorString()));
return false;
}
- emit outputTextChanged(tr("Move '%1' to '%2'.").arg(source, target));
+ emit outputTextChanged(tr("Moving file \"%1\" to \"%2\".").arg(QDir::toNativeSeparators(source),
+ QDir::toNativeSeparators(target)));
return true;
}
@@ -91,7 +91,8 @@ bool SimpleMoveFileOperation::undoOperation()
const QString target = arguments().at(1);
QFile(target).rename(source);
- emit outputTextChanged(tr("Move '%1' to '%2'.").arg(target, source));
+ emit outputTextChanged(tr("Moving file \"%1\" to \"%2\".").arg(QDir::toNativeSeparators(target),
+ QDir::toNativeSeparators(source)));
return true;
}
@@ -101,9 +102,4 @@ bool SimpleMoveFileOperation::testOperation()
return true;
}
-Operation *SimpleMoveFileOperation::clone() const
-{
- return new SimpleMoveFileOperation();
-}
-
} // namespace QInstaller
diff --git a/src/libs/installer/simplemovefileoperation.h b/src/libs/installer/simplemovefileoperation.h
index 9b2ea2603..26cb5c462 100644
--- a/src/libs/installer/simplemovefileoperation.h
+++ b/src/libs/installer/simplemovefileoperation.h
@@ -40,13 +40,12 @@ class INSTALLER_EXPORT SimpleMoveFileOperation : public QObject, public Operatio
Q_OBJECT
public:
- SimpleMoveFileOperation();
+ explicit SimpleMoveFileOperation(PackageManagerCore *core);
void backup();
bool performOperation();
bool undoOperation();
bool testOperation();
- Operation *clone() const;
Q_SIGNALS:
void outputTextChanged(const QString &progress);
diff --git a/src/libs/installer/sysinfo_win.cpp b/src/libs/installer/sysinfo_win.cpp
index de1318295..69c1744ca 100644
--- a/src/libs/installer/sysinfo_win.cpp
+++ b/src/libs/installer/sysinfo_win.cpp
@@ -26,7 +26,7 @@
**
**************************************************************************/
-#include "kdsysinfo.h"
+#include "sysinfo.h"
#include "link.h"
#ifdef Q_CC_MINGW
diff --git a/src/libs/installer/testrepository.cpp b/src/libs/installer/testrepository.cpp
index a3e8ce9c3..4ee2d41ae 100644
--- a/src/libs/installer/testrepository.cpp
+++ b/src/libs/installer/testrepository.cpp
@@ -27,26 +27,29 @@
**************************************************************************/
#include "testrepository.h"
-#include <kdupdaterfiledownloader.h>
-#include <kdupdaterfiledownloaderfactory.h>
+#include "packagemanagercore.h"
+#include "packagemanagerproxyfactory.h"
+#include "proxycredentialsdialog.h"
+#include "serverauthenticationdialog.h"
-#include <QtCore/QFile>
+#include <QFile>
-using namespace QInstaller;
+namespace QInstaller {
-TestRepository::TestRepository(QObject *parent)
- : KDJob(parent)
- , m_downloader(0)
+TestRepository::TestRepository(PackageManagerCore *parent)
+ : Job(parent)
+ , m_core(parent)
{
- setTimeout(10000);
setAutoDelete(false);
setCapabilities(Cancelable);
+
+ connect(&m_timer, &QTimer::timeout, this, &TestRepository::onTimeout);
+ connect(&m_xmlTask, &QFutureWatcherBase::finished, this, &TestRepository::downloadCompleted);
}
TestRepository::~TestRepository()
{
- if (m_downloader)
- m_downloader->deleteLater();
+ reset();
}
Repository TestRepository::repository() const
@@ -56,100 +59,127 @@ Repository TestRepository::repository() const
void TestRepository::setRepository(const Repository &repository)
{
- cancel();
-
- setError(NoError);
- setErrorString(QString());
+ reset();
m_repository = repository;
}
void TestRepository::doStart()
{
- if (m_downloader)
- m_downloader->deleteLater();
+ reset();
+ if (!m_core) {
+ emitFinishedWithError(Job::Canceled, tr("Missing package manager core engine."));
+ return; // We can't do anything here without core, so avoid tons of !m_core checks.
+ }
const QUrl url = m_repository.url();
if (url.isEmpty()) {
- emitFinishedWithError(InvalidUrl, tr("Empty repository URL."));
- return;
- }
-
- m_downloader = KDUpdater::FileDownloaderFactory::instance().create(url.scheme(), this);
- if (!m_downloader) {
- emitFinishedWithError(InvalidUrl, tr("URL scheme not supported: %1 (%2).")
- .arg(url.scheme(), url.toString()));
+ emitFinishedWithError(QInstaller::InvalidUrl, tr("Empty repository URL."));
return;
}
QAuthenticator auth;
auth.setUser(m_repository.username());
auth.setPassword(m_repository.password());
- m_downloader->setAuthenticator(auth);
-
- connect(m_downloader, SIGNAL(downloadCompleted()), this, SLOT(downloadCompleted()));
- connect(m_downloader, SIGNAL(downloadAborted(QString)), this, SLOT(downloadAborted(QString)),
- Qt::QueuedConnection);
- connect(m_downloader, SIGNAL(authenticatorChanged(QAuthenticator)), this,
- SLOT(onAuthenticatorChanged(QAuthenticator)));
- m_downloader->setAutoRemoveDownloadedFile(true);
- m_downloader->setUrl(QUrl(url.toString() + QString::fromLatin1("/Updates.xml")));
+ FileTaskItem item(m_repository.url().toString() + QLatin1String("/Updates.xml?") +
+ QString::number(qrand() * qrand()));
+ item.insert(TaskRole::Authenticator, QVariant::fromValue(auth));
- m_downloader->download();
+ m_timer.start(10000);
+ DownloadFileTask *const xmlTask = new DownloadFileTask(item);
+ if (m_core)
+ xmlTask->setProxyFactory(m_core->proxyFactory());
+ m_xmlTask.setFuture(QtConcurrent::run(&DownloadFileTask::doTask, xmlTask));
}
void TestRepository::doCancel()
{
- if (m_downloader) {
- QString errorString = m_downloader->errorString();
- if (errorString.isEmpty())
- errorString = tr("Got a timeout while testing: '%1'").arg(m_repository.displayname());
- // at the moment the download sends downloadCompleted() if we cancel it, so just
- disconnect(m_downloader, 0, this, 0);
- m_downloader->cancelDownload();
- emitFinishedWithError(KDJob::Canceled, errorString);
- }
+ reset();
+ emitFinishedWithError(Job::Canceled, tr("Download canceled."));
+}
+
+void TestRepository::onTimeout()
+{
+ reset();
+ emitFinishedWithError(Job::Canceled, tr("Timeout while testing repository \"%1\".")
+ .arg(m_repository.displayname()));
}
void TestRepository::downloadCompleted()
{
- QString errorMsg;
- int error = DownloadError;
+ if (error() != Job::NoError)
+ return;
- if (m_downloader->isDownloaded()) {
- QFile file(m_downloader->downloadedFileName());
- if (file.exists() && file.open(QIODevice::ReadOnly)) {
+ try {
+ m_xmlTask.waitForFinished();
+
+ m_timer.stop();
+ QFile file(m_xmlTask.future().results().value(0).target());
+ if (file.open(QIODevice::ReadOnly)) {
QDomDocument doc;
QString errorMsg;
if (!doc.setContent(&file, &errorMsg)) {
- error = InvalidUpdatesXml;
- errorMsg = tr("Could not parse Updates.xml! Error: %1.").arg(errorMsg);
+ emitFinishedWithError(QInstaller::InvalidUpdatesXml,
+ tr("Cannot parse Updates.xml: %1").arg(errorMsg));
} else {
- error = NoError;
+ emitFinishedWithError(Job::NoError, QString(/*Success*/)); // OPK
}
} else {
- errorMsg = tr("Updates.xml could not be opened for reading!");
+ emitFinishedWithError(QInstaller::DownloadError,
+ tr("Cannot open Updates.xml for reading: %1").arg(file.errorString()));
}
- } else {
- errorMsg = tr("Updates.xml could not be found on server!");
+ } catch (const AuthenticationRequiredException &e) {
+ m_timer.stop();
+ if (e.type() == AuthenticationRequiredException::Type::Server) {
+ ServerAuthenticationDialog dlg(e.message(), e.taskItem());
+ if (dlg.exec() == QDialog::Accepted) {
+ m_repository.setUsername(dlg.user());
+ m_repository.setPassword(dlg.password());
+ QMetaObject::invokeMethod(this, "doStart", Qt::QueuedConnection);
+ } else {
+ QMetaObject::invokeMethod(this, "doCancel", Qt::QueuedConnection);
+ }
+ return;
+ } else if (e.type() == AuthenticationRequiredException::Type::Proxy) {
+ const QNetworkProxy proxy = e.proxy();
+ ProxyCredentialsDialog proxyCredentials(proxy);
+ if (proxyCredentials.exec() == QDialog::Accepted) {
+ PackageManagerProxyFactory *factory = m_core->proxyFactory();
+ factory->setProxyCredentials(proxy, proxyCredentials.userName(),
+ proxyCredentials.password());
+ m_core->setProxyFactory(factory);
+ }
+ QMetaObject::invokeMethod(this, "doStart", Qt::QueuedConnection);
+ return;
+ } else {
+ emitFinishedWithError(QInstaller::DownloadError, tr("Authentication failed."));
+ }
+ } catch (const TaskException &e) {
+ m_timer.stop();
+ emitFinishedWithError(QInstaller::DownloadError, e.message());
+ } catch (const QUnhandledException &e) {
+ m_timer.stop();
+ emitFinishedWithError(QInstaller::DownloadError, QLatin1String(e.what()));
+ } catch (...) {
+ m_timer.stop();
+ emitFinishedWithError(QInstaller::DownloadError,
+ tr("Unknown error while testing repository \"%1\".").arg(m_repository.displayname()));
}
+}
- if (error > NoError)
- emitFinishedWithError(error, errorMsg);
- else
- emitFinished();
- m_downloader->deleteLater();
- m_downloader = 0;
-}
+// -- private
-void TestRepository::downloadAborted(const QString &reason)
+void TestRepository::reset()
{
- emitFinishedWithError(DownloadError, reason);
-}
+ m_timer.stop();
+ setError(NoError);
+ setErrorString(QString());
-void TestRepository::onAuthenticatorChanged(const QAuthenticator &authenticator)
-{
- m_repository.setUsername(authenticator.user());
- m_repository.setPassword(authenticator.password());
+ try {
+ if (m_xmlTask.isRunning())
+ m_xmlTask.cancel();
+ } catch (...) {}
}
+
+} // namespace QInstaller
diff --git a/src/libs/installer/testrepository.h b/src/libs/installer/testrepository.h
index 43165560d..80d964692 100644
--- a/src/libs/installer/testrepository.h
+++ b/src/libs/installer/testrepository.h
@@ -28,55 +28,47 @@
#ifndef TESTREPOSITORY_H
#define TESTREPOSITORY_H
-#include "qinstallerglobal.h"
+#include "downloadfiletask.h"
+#include "job.h"
+#include "repository.h"
-#include <repository.h>
-#include <settings.h>
-
-#include <kdjob.h>
-
-QT_BEGIN_NAMESPACE
-class QAuthenticator;
-class QLocale;
-class QVariant;
-QT_END_NAMESPACE
-
-namespace KDUpdater {
- class FileDownloader;
-}
+#include <QFutureWatcher>
+#include <QTimer>
namespace QInstaller {
- class PackageManagerCore;
-}
-namespace QInstaller {
+class PackageManagerCore;
-class INSTALLER_EXPORT TestRepository : public KDJob
+class INSTALLER_EXPORT TestRepository : public Job
{
Q_OBJECT
+ Q_DISABLE_COPY(TestRepository)
public:
-
- explicit TestRepository(QObject *parent = 0);
+ explicit TestRepository(PackageManagerCore *parent = 0);
~TestRepository();
- QInstaller::Repository repository() const;
- void setRepository(const QInstaller::Repository &repository);
+ Repository repository() const;
+ void setRepository(const Repository &repository);
-private:
+private slots:
void doStart();
void doCancel();
-private Q_SLOTS:
+ void onTimeout();
void downloadCompleted();
- void downloadAborted(const QString &reason);
- void onAuthenticatorChanged(const QAuthenticator &authenticator);
private:
- QInstaller::Repository m_repository;
- KDUpdater::FileDownloader *m_downloader;
+ void reset();
+
+private:
+ PackageManagerCore *m_core;
+
+ QTimer m_timer;
+ Repository m_repository;
+ QFutureWatcher<FileTaskResult> m_xmlTask;
};
-} //namespace QInstaller
+} // namespace QInstaller
#endif // TESTREPOSITORY_H
diff --git a/src/libs/installer/unziptask.cpp b/src/libs/installer/unziptask.cpp
index 4b78b6d6e..f1f0dd0a1 100644
--- a/src/libs/installer/unziptask.cpp
+++ b/src/libs/installer/unziptask.cpp
@@ -25,7 +25,9 @@
** $QT_END_LICENSE$
**
**************************************************************************/
+
#include "unziptask.h"
+#include "lib7z_facade.h"
#ifdef Q_OS_UNIX
# include "StdAfx.h"
@@ -34,21 +36,15 @@
// TODO: include once we switch from lib7z_fascade.h
//#include "Common/MyInitGuid.h"
-#include "7zip/IPassword.h"
+#include "7zip/Archive/IArchive.h"
#include "7zip/Common/FileStreams.h"
#include "7zip/UI/Common/OpenArchive.h"
#include "Windows/FileDir.h"
#include "Windows/PropVariant.h"
-#include "7zCrc.h"
-
#include <QDir>
-void registerArc7z();
-void registerCodecLZMA();
-void registerCodecLZMA2();
-
namespace QInstaller {
class ArchiveExtractCallback : public IArchiveExtractCallback, public CMyUnknownImp
@@ -99,11 +95,11 @@ public:
return E_FAIL;
bool isDir = false;
- if (IsArchiveItemFolder(m_arc.Archive, m_currentIndex, isDir) != S_OK)
+ if (Archive_IsItem_Folder(m_arc.Archive, m_currentIndex, isDir) != S_OK)
return E_FAIL;
bool isEncrypted = false;
- if (GetArchiveItemBoolProp(m_arc.Archive, m_currentIndex, kpidEncrypted, isEncrypted) != S_OK)
+ if (Archive_GetItemBoolProp(m_arc.Archive, m_currentIndex, kpidEncrypted, isEncrypted) != S_OK)
return E_FAIL;
if (isDir || isEncrypted)
@@ -149,7 +145,7 @@ public:
default: // fall through and bail
case NArchive::NExtract::NOperationResult::kCRCError:
case NArchive::NExtract::NOperationResult::kDataError:
- case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
+ case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
m_outFileStream->Close();
m_outFileStreamComPtr.Release();
return E_FAIL;
@@ -157,7 +153,7 @@ public:
UInt32 attributes;
if (GetAttributes(&attributes))
- NWindows::NFile::NDirectory::MySetFileAttributes((wchar_t*)(m_currentTarget.utf16()), attributes);
+ NWindows::NFile::NDir::SetFileAttrib((wchar_t*)(m_currentTarget.utf16()), attributes);
FILETIME accessTime, creationTime, modificationTime;
const bool writeAccessTime = GetTime(kpidATime, &accessTime);
@@ -234,13 +230,7 @@ UnzipTask::UnzipTask(const QString &source, const QString &target)
: m_source(source)
, m_target(target)
{
- {
- CrcGenerateTable();
-
- registerArc7z();
- registerCodecLZMA();
- registerCodecLZMA2();
- }
+ Lib7z::initSevenZ();
}
void UnzipTask::doTask(QFutureInterface<QString> &fi)
@@ -251,19 +241,29 @@ void UnzipTask::doTask(QFutureInterface<QString> &fi)
if (codecs.Load() != S_OK)
return;
- CIntVector formatIndices;
- if (!codecs.FindFormatForArchiveType(L"", formatIndices))
- return;
- CInFileStream *fileStream = new CInFileStream;
+ COpenOptions op;
+ op.codecs = &codecs;
+
+ CObjectVector<COpenType> types;
+ op.types = &types; // Empty, because we use a stream.
+
+ CIntVector excluded;
+ op.excludedFormats = &excluded;
+
+ const CMyComPtr<CInFileStream> fileStream = new CInFileStream;
fileStream->Open((wchar_t*) (m_source.utf16()));
+ op.stream = fileStream; // CMyComPtr is needed, otherwise it crashes in OpenStream().
+
+ CObjectVector<CProperty> properties;
+ op.props = &properties;
CArchiveLink archiveLink;
- if (archiveLink.Open2(&codecs, formatIndices, false, fileStream, UString(), 0) != S_OK)
+ if (archiveLink.Open2(op, nullptr) != S_OK)
return;
UINT32 count = 0;
- for (int i = 0; i < archiveLink.Arcs.Size(); ++i) {
+ for (unsigned i = 0; i < archiveLink.Arcs.Size(); ++i) {
const CArc& arc = archiveLink.Arcs[i];
UInt32 numItems = 0;
if (arc.Archive->GetNumberOfItems(&numItems) != S_OK)
@@ -272,7 +272,7 @@ void UnzipTask::doTask(QFutureInterface<QString> &fi)
}
fi.setExpectedResultCount(count);
- for (int i = 0; i < archiveLink.Arcs.Size(); ++i) {
+ for (unsigned i = 0; i < archiveLink.Arcs.Size(); ++i) {
if (fi.isCanceled())
break;
if (fi.isPaused())
diff --git a/src/libs/installer/utils.cpp b/src/libs/installer/utils.cpp
index d76eab696..a11ac774e 100644
--- a/src/libs/installer/utils.cpp
+++ b/src/libs/installer/utils.cpp
@@ -214,24 +214,40 @@ QInstaller::VerboseWriter::VerboseWriter()
QInstaller::VerboseWriter::~VerboseWriter()
{
+ if (preFileBuffer.isOpen()) {
+ PlainVerboseWriterOutput output;
+ (void)flush(&output);
+ }
+}
+
+bool QInstaller::VerboseWriter::flush(VerboseWriterOutput *output)
+{
stream.flush();
if (logFileName.isEmpty()) // binarycreator
- return;
+ return true;
+ if (!preFileBuffer.isOpen())
+ return true;
//if the installer installed nothing - there is no target directory - where the logfile can be saved
if (!QFileInfo(logFileName).absoluteDir().exists())
- return;
-
- QFile output(logFileName);
- if (output.open(QIODevice::ReadWrite | QIODevice::Append | QIODevice::Text)) {
- QString logInfo;
- logInfo += QLatin1String("************************************* Invoked: ");
- logInfo += currentDateTimeAsString;
- logInfo += QLatin1String("\n");
- output.write(logInfo.toLocal8Bit());
- output.write(preFileBuffer.data());
- output.close();
+ return true;
+
+ QString logInfo;
+ logInfo += QLatin1String("************************************* Invoked: ");
+ logInfo += currentDateTimeAsString;
+ logInfo += QLatin1String("\n");
+
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ buffer.write(logInfo.toLocal8Bit());
+ buffer.write(preFileBuffer.data());
+ buffer.close();
+
+ if (output->write(logFileName, QIODevice::ReadWrite | QIODevice::Append | QIODevice::Text, buffer.data())) {
+ preFileBuffer.close();
+ stream.setDevice(0);
+ return true;
}
- stream.setDevice(0);
+ return false;
}
void QInstaller::VerboseWriter::setFileName(const QString &fileName)
@@ -252,6 +268,20 @@ void QInstaller::VerboseWriter::appendLine(const QString &msg)
stream << msg << endl;
}
+QInstaller::VerboseWriterOutput::~VerboseWriterOutput()
+{
+}
+
+bool QInstaller::PlainVerboseWriterOutput::write(const QString &fileName, QIODevice::OpenMode openMode, const QByteArray &data)
+{
+ QFile output(fileName);
+ if (output.open(openMode)) {
+ output.write(data);
+ return true;
+ }
+ return false;
+}
+
#ifdef Q_OS_WIN
// taken from qcoreapplication_p.h
template<typename Char>
diff --git a/src/libs/installer/utils.h b/src/libs/installer/utils.h
index cfaeaa67d..7cd237dcc 100644
--- a/src/libs/installer/utils.h
+++ b/src/libs/installer/utils.h
@@ -67,6 +67,20 @@ namespace QInstaller {
INSTALLER_EXPORT std::ostream& operator<<(std::ostream &os, const QString &string);
+ class INSTALLER_EXPORT VerboseWriterOutput
+ {
+ public:
+ virtual bool write(const QString &fileName, QIODevice::OpenMode openMode, const QByteArray &data) = 0;
+
+ protected:
+ ~VerboseWriterOutput();
+ };
+
+ class INSTALLER_EXPORT PlainVerboseWriterOutput : public VerboseWriterOutput
+ {
+ public:
+ virtual bool write(const QString &fileName, QIODevice::OpenMode openMode, const QByteArray &data);
+ };
class INSTALLER_EXPORT VerboseWriter
{
@@ -76,6 +90,8 @@ namespace QInstaller {
static VerboseWriter *instance();
+ bool flush(VerboseWriterOutput *output);
+
void appendLine(const QString &msg);
void setFileName(const QString &fileName);