summaryrefslogtreecommitdiffstats
path: root/src/libs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs')
-rw-r--r--src/libs/ifwtools/binarycreator.cpp10
-rw-r--r--src/libs/ifwtools/rcc/rcc.cpp22
-rw-r--r--src/libs/ifwtools/repositorygen.cpp122
-rw-r--r--src/libs/ifwtools/repositorygen.h16
-rw-r--r--src/libs/installer/adminauthorization_x11.cpp234
-rw-r--r--src/libs/installer/binarycontent.h9
-rw-r--r--src/libs/installer/commandlineparser.cpp9
-rw-r--r--src/libs/installer/component.cpp7
-rw-r--r--src/libs/installer/component_p.cpp1
-rw-r--r--src/libs/installer/componentmodel.cpp6
-rw-r--r--src/libs/installer/componentselectionpage_p.cpp54
-rw-r--r--src/libs/installer/componentselectionpage_p.h6
-rw-r--r--src/libs/installer/constants.h5
-rw-r--r--src/libs/installer/installiconsoperation.cpp10
-rw-r--r--src/libs/installer/keepaliveobject.cpp7
-rw-r--r--src/libs/installer/loggingutils.cpp2
-rw-r--r--src/libs/installer/packagemanagercore.cpp95
-rw-r--r--src/libs/installer/packagemanagercore.h9
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp29
-rw-r--r--src/libs/installer/packagemanagercore_p.h8
-rw-r--r--src/libs/installer/packagemanagergui.cpp2
-rw-r--r--src/libs/installer/performinstallationform.cpp1
-rw-r--r--src/libs/installer/qsettingswrapper.cpp4
-rw-r--r--src/libs/installer/utils.cpp8
-rw-r--r--src/libs/kdtools/filedownloader.cpp2
-rw-r--r--src/libs/kdtools/localpackagehub.cpp8
-rw-r--r--src/libs/kdtools/localpackagehub.h4
-rw-r--r--src/libs/kdtools/selfrestarter.cpp14
-rw-r--r--src/libs/kdtools/updatefinder.cpp7
-rw-r--r--src/libs/kdtools/updateoperation.cpp2
-rw-r--r--src/libs/kdtools/updatesinfo.cpp8
31 files changed, 395 insertions, 326 deletions
diff --git a/src/libs/ifwtools/binarycreator.cpp b/src/libs/ifwtools/binarycreator.cpp
index deea01ed7..a813c7f50 100644
--- a/src/libs/ifwtools/binarycreator.cpp
+++ b/src/libs/ifwtools/binarycreator.cpp
@@ -410,9 +410,9 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
collection.setName(info.name.toUtf8());
qDebug() << "Creating resource archive for" << info.name;
- foreach (const QString &file, info.copiedFiles) {
- const QSharedPointer<Resource> resource(new Resource(file));
- qDebug().nospace() << "Appending " << file << " (" << humanReadableSize(resource->size()) << ")";
+ foreach (const QString &copiedFile, info.copiedFiles) {
+ const QSharedPointer<Resource> resource(new Resource(copiedFile));
+ qDebug().nospace() << "Appending " << copiedFile << " (" << humanReadableSize(resource->size()) << ")";
collection.appendResource(resource);
}
input.manager.insertCollection(collection);
@@ -610,8 +610,8 @@ void QInstallerTools::copyConfigData(const QString &configFile, const QString &t
if (tagName == QLatin1String("ProductImages")) {
const QDomNodeList childNodes = domElement.childNodes();
- for (int i = 0; i < childNodes.count(); ++i) {
- const QDomElement childElement = childNodes.at(i).toElement();
+ for (int index = 0; index < childNodes.count(); ++index) {
+ const QDomElement childElement = childNodes.at(index).toElement();
const QString childName = childElement.tagName();
if (childName != QLatin1String("Image"))
continue;
diff --git a/src/libs/ifwtools/rcc/rcc.cpp b/src/libs/ifwtools/rcc/rcc.cpp
index 10b7cbc4f..12f399937 100644
--- a/src/libs/ifwtools/rcc/rcc.cpp
+++ b/src/libs/ifwtools/rcc/rcc.cpp
@@ -120,18 +120,18 @@ public:
RCCFileInfo::RCCFileInfo(const QString &name, const QFileInfo &fileInfo,
QLocale::Language language, QLocale::Country country, uint flags,
int compressLevel, int compressThreshold)
+ : m_flags(flags)
+ , m_name(name)
+ , m_language(language)
+ , m_country(country)
+ , m_fileInfo(fileInfo)
+ , m_parent(nullptr)
+ , m_compressLevel(compressLevel)
+ , m_compressThreshold(compressThreshold)
+ , m_nameOffset(0)
+ , m_dataOffset(0)
+ , m_childOffset(0)
{
- m_name = name;
- m_fileInfo = fileInfo;
- m_language = language;
- m_country = country;
- m_flags = flags;
- m_parent = nullptr;
- m_nameOffset = 0;
- m_dataOffset = 0;
- m_childOffset = 0;
- m_compressLevel = compressLevel;
- m_compressThreshold = compressThreshold;
}
RCCFileInfo::~RCCFileInfo()
diff --git a/src/libs/ifwtools/repositorygen.cpp b/src/libs/ifwtools/repositorygen.cpp
index fbcf7b9f3..d8339b063 100644
--- a/src/libs/ifwtools/repositorygen.cpp
+++ b/src/libs/ifwtools/repositorygen.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -52,6 +52,9 @@
#include <iostream>
+#define QUOTE_(x) #x
+#define QUOTE(x) QUOTE_(x)
+
using namespace QInstaller;
using namespace QInstallerTools;
@@ -69,6 +72,8 @@ void QInstallerTools::printRepositoryGenOptions()
std::cout << " --ignore-translations Do not use any translation" << std::endl;
std::cout << " --ignore-invalid-packages Ignore all invalid packages instead of aborting." << std::endl;
std::cout << " --ignore-invalid-repositories Ignore all invalid repositories instead of aborting." << std::endl;
+ std::cout << " -s|--sha-update p1,...,pn List of packages which are updated using" <<std::endl;
+ std::cout << " content sha1 instead of version number." << std::endl;
}
QString QInstallerTools::makePathAbsolute(const QString &path)
@@ -289,6 +294,11 @@ void QInstallerTools::copyMetaData(const QString &_targetDir, const QString &met
fileElement.setAttribute(QLatin1String("OS"), QLatin1String("Any"));
update.appendChild(fileElement);
+ if (info.createContentSha1Node) {
+ QDomNode contentSha1Element = update.appendChild(doc.createElement(QLatin1String("ContentSha1")));
+ contentSha1Element.appendChild(doc.createTextNode(info.contentSha1));
+ }
+
root.appendChild(update);
// copy script file
@@ -414,7 +424,7 @@ void QInstallerTools::copyMetaData(const QString &_targetDir, const QString &met
}
PackageInfoVector QInstallerTools::createListOfPackages(const QStringList &packagesDirectories,
- QStringList *packagesToFilter, FilterType filterType)
+ QStringList *packagesToFilter, FilterType filterType, QStringList packagesUpdatedWithSha)
{
qDebug() << "Collecting information about available packages...";
@@ -508,6 +518,13 @@ PackageInfoVector QInstallerTools::createListOfPackages(const QStringList &packa
info.dependencies = packageElement.firstChildElement(QLatin1String("Dependencies")).text()
.split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
info.directory = it->filePath();
+ if (packagesUpdatedWithSha.contains(info.name)) {
+ info.createContentSha1Node = true;
+ packagesUpdatedWithSha.removeOne(info.name);
+ } else {
+ info.createContentSha1Node = false;
+ }
+
dict.push_back(info);
qDebug() << "- it provides the package" << info.name << " - " << info.version;
@@ -521,6 +538,11 @@ PackageInfoVector QInstallerTools::createListOfPackages(const QStringList &packa
if (dict.isEmpty())
qDebug() << "No available packages found at the specified location.";
+ if (!packagesUpdatedWithSha.isEmpty()) {
+ throw QInstaller::Error(QString::fromLatin1("The following packages could not be found in "
+ "package directory: %1").arg(packagesUpdatedWithSha.join(QLatin1String(", "))));
+ }
+
return dict;
}
@@ -650,8 +672,33 @@ PackageInfoVector QInstallerTools::createListOfRepositoryPackages(const QStringL
el.save(metaStream, 0);
}
info.metaNode = metaString;
- dict.push_back(info);
- qDebug() << "- it provides the package" << info.name << " - " << info.version;
+
+ bool pushToDict = true;
+ bool replacement = false;
+ // Check whether this package already exists in vector:
+ for (int i = 0; i < dict.size(); ++i) {
+ const QInstallerTools::PackageInfo oldInfo = dict.at(i);
+ if (oldInfo.name != info.name)
+ continue;
+
+ if (KDUpdater::compareVersion(info.version, oldInfo.version) > 0) {
+ // A package with newer version, it will replace the existing one.
+ dict.remove(i);
+ replacement = true;
+ } else {
+ // A package with older or same version, do not add it again.
+ pushToDict = false;
+ }
+ break;
+ }
+
+ if (pushToDict) {
+ replacement ? qDebug() << "- it provides a new version of the package" << info.name << " - " << info.version << "- replaced"
+ : qDebug() << "- it provides the package" << info.name << " - " << info.version;
+ dict.push_back(info);
+ } else {
+ qDebug() << "- it provides an old version of the package" << info.name << " - " << info.version << "- ignored";
+ }
}
}
}
@@ -755,14 +802,14 @@ QStringList QInstallerTools::unifyMetadata(const QString &repoDir, const QString
QFile archiveFile(existingRepoDir);
QInstaller::openForRead(&archiveFile);
Lib7z::extractArchive(&archiveFile, existingRepoTemp);
- QDir dir(existingRepoTemp);
- QStringList existingRepoEntries = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
+ QDir dir2(existingRepoTemp);
+ QStringList existingRepoEntries = dir2.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
foreach (const QString existingRepoEntry, existingRepoEntries) {
if (entryList.contains(existingRepoEntry)) {
continue;
} else {
- dir.cd(existingRepoEntry);
- const QString absPath = dir.absolutePath();
+ dir2.cd(existingRepoEntry);
+ const QString absPath = dir2.absolutePath();
absPaths.append(absPath);
}
}
@@ -902,6 +949,8 @@ void QInstallerTools::copyComponentData(const QStringList &packageDirs, const QS
archiveHashFile.write(hashOfArchiveData);
qDebug() << "Generated sha1 hash:" << hashOfArchiveData;
(*infos)[i].copiedFiles.append(archiveHashFile.fileName());
+ if ((*infos)[i].createContentSha1Node)
+ (*infos)[i].contentSha1 = QLatin1String(hashOfArchiveData);
archiveHashFile.close();
} catch (const QInstaller::Error &/*e*/) {
archiveFile.close();
@@ -987,3 +1036,60 @@ QString QInstallerTools::existingUniteMeta7z(const QString &repositoryDir)
}
return uniteMeta7z;
}
+
+PackageInfoVector QInstallerTools::collectPackages(RepositoryInfo info, QStringList *filteredPackages, FilterType filterType, bool updateNewComponents, QStringList packagesUpdatedWithSha)
+{
+ PackageInfoVector packages;
+ PackageInfoVector precompressedPackages = QInstallerTools::createListOfRepositoryPackages(info.repositoryPackages,
+ filteredPackages, filterType);
+ packages.append(precompressedPackages);
+
+ PackageInfoVector preparedPackages = QInstallerTools::createListOfPackages(info.packages,
+ filteredPackages, filterType, packagesUpdatedWithSha);
+ packages.append(preparedPackages);
+ if (updateNewComponents) {
+ filterNewComponents(info.repositoryDir, packages);
+ }
+ foreach (const QInstallerTools::PackageInfo &package, packages) {
+ const QFileInfo fi(info.repositoryDir, package.name);
+ if (fi.exists())
+ removeDirectory(fi.absoluteFilePath());
+ }
+ return packages;
+}
+
+void QInstallerTools::createRepository(RepositoryInfo info, PackageInfoVector *packages,
+ const QString &tmpMetaDir, bool createComponentMetadata, bool createUnifiedMetadata)
+{
+ QHash<QString, QString> pathToVersionMapping = QInstallerTools::buildPathToVersionMapping(*packages);
+
+ QStringList directories;
+ directories.append(info.packages);
+ directories.append(info.repositoryPackages);
+ QStringList unite7zFiles;
+ foreach (const QString &repositoryDirectory, info.repositoryPackages) {
+ QDirIterator it(repositoryDirectory, QStringList(QLatin1String("*_meta.7z"))
+ , QDir::Files | QDir::CaseSensitive);
+ while (it.hasNext()) {
+ it.next();
+ unite7zFiles.append(it.fileInfo().absoluteFilePath());
+ }
+ }
+ QInstallerTools::copyComponentData(directories, info.repositoryDir, packages);
+ QInstallerTools::copyMetaData(tmpMetaDir, info.repositoryDir, *packages, QLatin1String("{AnyApplication}"),
+ QLatin1String(QUOTE(IFW_REPOSITORY_FORMAT_VERSION)), unite7zFiles);
+
+ QString existing7z = QInstallerTools::existingUniteMeta7z(info.repositoryDir);
+ if (!existing7z.isEmpty())
+ existing7z = info.repositoryDir + QDir::separator() + existing7z;
+ QInstallerTools::compressMetaDirectories(tmpMetaDir, existing7z, pathToVersionMapping,
+ createComponentMetadata, createUnifiedMetadata);
+
+ QDirIterator it(info.repositoryDir, QStringList(QLatin1String("Updates*.xml"))
+ << QLatin1String("*_meta.7z"), QDir::Files | QDir::CaseSensitive);
+ while (it.hasNext()) {
+ it.next();
+ QFile::remove(it.fileInfo().absoluteFilePath());
+ }
+ QInstaller::moveDirectoryContents(tmpMetaDir, info.repositoryDir);
+}
diff --git a/src/libs/ifwtools/repositorygen.h b/src/libs/ifwtools/repositorygen.h
index 49d0a51dd..0da81db67 100644
--- a/src/libs/ifwtools/repositorygen.h
+++ b/src/libs/ifwtools/repositorygen.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -48,6 +48,8 @@ struct IFWTOOLS_EXPORT PackageInfo
QStringList copiedFiles;
QString metaFile;
QString metaNode;
+ QString contentSha1;
+ bool createContentSha1Node;
};
typedef QVector<PackageInfo> PackageInfoVector;
@@ -56,12 +58,19 @@ enum IFWTOOLS_EXPORT FilterType {
Exclude
};
+struct IFWTOOLS_EXPORT RepositoryInfo
+{
+ QStringList packages;
+ QStringList repositoryPackages;
+ QString repositoryDir;
+};
+
void IFWTOOLS_EXPORT printRepositoryGenOptions();
QString IFWTOOLS_EXPORT makePathAbsolute(const QString &path);
void IFWTOOLS_EXPORT copyWithException(const QString &source, const QString &target, const QString &kind = QString());
PackageInfoVector IFWTOOLS_EXPORT createListOfPackages(const QStringList &packagesDirectories, QStringList *packagesToFilter,
- FilterType ftype);
+ FilterType ftype, QStringList packagesUpdatedWithSha = QStringList());
PackageInfoVector IFWTOOLS_EXPORT createListOfRepositoryPackages(const QStringList &repositoryDirectories, QStringList *packagesToFilter,
FilterType filterType);
@@ -82,7 +91,8 @@ void IFWTOOLS_EXPORT copyComponentData(const QStringList &packageDir, const QStr
void IFWTOOLS_EXPORT filterNewComponents(const QString &repositoryDir, QInstallerTools::PackageInfoVector &packages);
QString IFWTOOLS_EXPORT existingUniteMeta7z(const QString &repositoryDir);
-
+PackageInfoVector IFWTOOLS_EXPORT collectPackages(RepositoryInfo info, QStringList *filteredPackages, FilterType filterType, bool updateNewComponents, QStringList packagesUpdatedWithSha);
+void IFWTOOLS_EXPORT createRepository(RepositoryInfo info, PackageInfoVector *packages, const QString &tmpMetaDir, bool createComponentMetadata, bool createUnifiedMetadata);
} // namespace QInstallerTools
#endif // REPOSITORYGEN_H
diff --git a/src/libs/installer/adminauthorization_x11.cpp b/src/libs/installer/adminauthorization_x11.cpp
index 14691c9de..f4951d523 100644
--- a/src/libs/installer/adminauthorization_x11.cpp
+++ b/src/libs/installer/adminauthorization_x11.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -28,41 +28,18 @@
#include "adminauthorization.h"
-#include <QtCore/QFile>
-#include <QtCore/QRegExp>
-#include <QDebug>
+#include "globals.h"
+#include <QDebug>
#include <QApplication>
-#include <QInputDialog>
#include <QMessageBox>
+#include <QProcess>
-#include <cstdlib>
-#include <sys/resource.h>
#include <unistd.h>
-#include <fcntl.h>
-
-#ifdef Q_OS_LINUX
-#include <linux/limits.h>
-#include <pty.h>
-#else
-#ifdef Q_OS_FREEBSD
-#include <libutil.h>
-#include <signal.h>
-#else
-#include <util.h>
-#endif
-#endif
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <errno.h>
#include <iostream>
-#include "globals.h"
-
-#define SU_COMMAND "/usr/bin/sudo"
-//#define SU_COMMAND "/bin/echo"
+#define PKEXEC_COMMAND "/usr/bin/pkexec"
namespace QInstaller {
@@ -72,24 +49,6 @@ namespace QInstaller {
\internal
*/
-static QString getPassword(QWidget *parent)
-{
- if (qobject_cast<QApplication*> (qApp) != 0) {
- bool ok = false;
- const QString result = QInputDialog::getText(parent, QObject::tr("Authorization required"),
- QObject::tr("Enter your password to authorize for sudo:"),
- QLineEdit::Password, QString(), &ok);
- return ok ? result : QString();
- } else {
- std::cout << QObject::tr("Authorization required").toStdString() << std::endl;
- std::cout << QObject::tr("Enter your password to authorize for sudo:").toStdString()
- << std::endl;
- std::string password;
- std::cin >> password;
- return QString::fromStdString(password);
- }
-}
-
static void printError(QWidget *parent, const QString &value)
{
if (qobject_cast<QApplication*> (qApp) != 0) {
@@ -105,184 +64,21 @@ bool AdminAuthorization::execute(QWidget *parent, const QString &program, const
const QString fallback = program + QLatin1String(" ") + arguments.join(QLatin1String(" "));
qCDebug(QInstaller::lcServer) << "Fallback:" << fallback;
- // as we cannot pipe the password to su in QProcess, we need to setup a pseudo-terminal for it
- int masterFD = -1;
- int slaveFD = -1;
- char ptsn[ PATH_MAX ];
+ QProcess process;
+ process.setProcessChannelMode(QProcess::MergedChannels);
+ process.start(QLatin1String(PKEXEC_COMMAND), QStringList() << program << arguments, QIODevice::ReadOnly);
- if (::openpty(&masterFD, &slaveFD, ptsn, 0, 0))
- return false;
-
- masterFD = ::posix_openpt(O_RDWR | O_NOCTTY);
- if (masterFD < 0)
- return false;
-
- const QByteArray ttyName = ::ptsname(masterFD);
-
- if (::grantpt(masterFD)) {
- ::close(masterFD);
- return false;
- }
-
- ::revoke(ttyName);
- ::unlockpt(masterFD);
-
- slaveFD = ::open(ttyName, O_RDWR | O_NOCTTY);
- if (slaveFD < 0) {
- ::close(masterFD);
+ if (!process.waitForStarted() || !process.waitForFinished(-1)) {
+ printError(parent, process.errorString());
+ if (process.state() > QProcess::NotRunning)
+ process.kill();
return false;
}
-
- ::fcntl(masterFD, F_SETFD, FD_CLOEXEC);
- ::fcntl(slaveFD, F_SETFD, FD_CLOEXEC);
- int pipedData[2];
- if (pipe(pipedData) != 0)
- return false;
-
- 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) {
- ::close(masterFD);
- ::close(slaveFD);
- ::close(pipedData[0]);
- ::close(pipedData[1]);
- return false;
- }
-
- // parent process
- else if (child > 0) {
- ::close(slaveFD);
- //close writing end of pipe
- ::close(pipedData[1]);
-
- QRegExp re(QLatin1String("[Pp]assword.*:"));
- QByteArray data;
- QByteArray errData;
- int bytes = 0;
- int errBytes = 0;
- char buf[1024];
- char errBuf[1024];
- int status;
- bool statusValid = false;
- while (bytes >= 0) {
- 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(errBuf, errBytes);
- errBytes=0;
- }
- if (bytes > 0) {
- const QString line = QString::fromLatin1(data);
- if (re.indexIn(line) != -1) {
- const QString password = getPassword(parent);
- if (password.isEmpty()) {
- QByteArray pwd = password.toLatin1();
- for (int i = 0; i < 3; ++i) {
- ::write(masterFD, pwd.data(), pwd.length());
- ::write(masterFD, "\n", 1);
- }
- return false;
- }
- QByteArray pwd = password.toLatin1();
- ::write(masterFD, pwd.data(), pwd.length());
- ::write(masterFD, "\n", 1);
- ::read(masterFD, buf, pwd.length() + 1);
- }
- }
- if (bytes == 0)
- ::usleep(100000);
- }
-
- while (true) {
- errBytes = ::read(pipedData[0], errBuf, 1023);
- if (errBytes == -1 && errno == EAGAIN) {
- ::usleep(100000);
- continue;
- }
-
- if (errBytes <= 0)
- break;
-
- errData.append(errBuf, errBytes);
- }
-
- const bool success = statusValid && WIFEXITED(status) && WEXITSTATUS(status) == 0;
-
- if (!success && !errData.isEmpty()) {
- printError(parent, QString::fromLocal8Bit(errData.constData()));
- }
-
- ::close(pipedData[0]);
- return success;
- }
-
- // child process
- else {
- ::close(pipedData[0]);
- // Reset signal handlers
- for (int sig = 1; sig < NSIG; ++sig)
- signal(sig, SIG_DFL);
- signal(SIGHUP, SIG_IGN);
-
- ::setsid();
-
- ::ioctl(slaveFD, TIOCSCTTY, 1);
- int pgrp = ::getpid();
- ::tcsetpgrp(slaveFD, pgrp);
-
- ::dup2(slaveFD, 0);
- ::dup2(slaveFD, 1);
- ::dup2(pipedData[1], 2);
-
- // close all file descriptors
- struct rlimit rlp;
- getrlimit(RLIMIT_NOFILE, &rlp);
- for (int i = 3; i < static_cast<int>(rlp.rlim_cur); ++i)
- ::close(i);
-
- char **argp = (char **) ::malloc((arguments.count() + 4) * sizeof(char *));
- QList<QByteArray> args;
- args.push_back(SU_COMMAND);
- args.push_back("-b");
- args.push_back(program.toLocal8Bit());
- for (QStringList::const_iterator it = arguments.begin(); it != arguments.end(); ++it)
- args.push_back(it->toLocal8Bit());
-
- int i = 0;
- for (QList<QByteArray>::iterator it = args.begin(); it != args.end(); ++it, ++i)
- argp[i] = it->data();
- argp[i] = 0;
-
- ::unsetenv("LANG");
- ::unsetenv("LC_ALL");
-
- int exitStatus = 0;
- if (::execv(SU_COMMAND, argp) == -1)
- exitStatus = -errno;
- _exit(exitStatus);
+ if (process.exitCode() != EXIT_SUCCESS) {
+ printError(parent, QLatin1String(process.readAll()));
return false;
}
+ return true;
}
// has no guarantee to work
diff --git a/src/libs/installer/binarycontent.h b/src/libs/installer/binarycontent.h
index a21cd69e7..7d50c0e28 100644
--- a/src/libs/installer/binarycontent.h
+++ b/src/libs/installer/binarycontent.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -48,6 +48,13 @@ public:
static const qint64 MagicUpdaterMarker = 0x12023235UL;
static const qint64 MagicPackageManagerMarker = 0x12023236UL;
+ // additional distinguishers only used at runtime, not written to the binary itself
+ enum MagicMarkerSupplement {
+ Default = 0x0,
+ OfflineGenerator = 0x1,
+ PackageViewer = 0x2
+ };
+
// the cookie put at the end of the file
static const quint64 MagicCookie = 0xc2630a1c99d668f8LL; // binary
static const quint64 MagicCookieDat = 0xc2630a1c99d668f9LL; // data
diff --git a/src/libs/installer/commandlineparser.cpp b/src/libs/installer/commandlineparser.cpp
index 59d42eefc..4bfc4ad3a 100644
--- a/src/libs/installer/commandlineparser.cpp
+++ b/src/libs/installer/commandlineparser.cpp
@@ -59,6 +59,9 @@ CommandLineParser::CommandLineParser()
.arg(CommandLineOptions::scListShort, CommandLineOptions::scListLong)
+ indent + QString::fromLatin1("%1, %2 - search available packages - <regexp>\n")
.arg(CommandLineOptions::scSearchShort, CommandLineOptions::scSearchLong)
+ + indent + indent + QString::fromLatin1("Note: The --%1 option can be used to specify\n")
+ .arg(CommandLineOptions::scFilterPackagesLong)
+ + indent + indent + QLatin1String("additional filters for the search operation\n")
+ indent + QString::fromLatin1("%1, %2 - create offline installer from selected packages - <pkg ...>\n")
.arg(CommandLineOptions::scCreateOfflineShort, CommandLineOptions::scCreateOfflineLong)
+ indent + QString::fromLatin1("%1, %2 - uninstall all packages and remove entire program directory")
@@ -161,6 +164,12 @@ CommandLineParser::CommandLineParser()
<< CommandLineOptions::scCreateLocalRepositoryShort << CommandLineOptions::scCreateLocalRepositoryLong,
QLatin1String("Create a local repository inside the installation directory. This option "
"has no effect on online installers.")));
+ addOptionWithContext(QCommandLineOption(QStringList()
+ << CommandLineOptions::scFilterPackagesShort << CommandLineOptions::scFilterPackagesLong,
+ QLatin1String("[CLI] Comma separated list of additional key-value pair filters used to query packages with the "
+ "search command. The keys can be any of the possible package information elements, like "
+ "\"DisplayName\" and \"Description\"."),
+ QLatin1String("element=regex,...")), CommandLineOnly);
// Message query options
addOptionWithContext(QCommandLineOption(QStringList() << CommandLineOptions::scAcceptMessageQueryShort
diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp
index cb9959ba3..b4b96eb08 100644
--- a/src/libs/installer/component.cpp
+++ b/src/libs/installer/component.cpp
@@ -300,11 +300,14 @@ void Component::loadDataFromPackage(const KDUpdater::LocalPackage &package)
setValue(scCurrentState, scInstalled);
setValue(scCheckable, package.checkable ? scTrue : scFalse);
setValue(scExpandedByDefault, package.expandedByDefault ? scTrue : scFalse);
+ setValue(scContentSha1, package.contentSha1);
}
/*!
Sets variables according to the values set in the package.xml file of \a package.
Also loads UI files, licenses and translations if they are referenced in the package.xml.
+ If the \c PackageManagerCore object of this component is run as package viewer, then
+ only sets the variables without loading referenced files.
*/
void Component::loadDataFromPackage(const Package &package)
{
@@ -341,6 +344,10 @@ void Component::loadDataFromPackage(const Package &package)
if (PackageManagerCore::noForceInstallation())
forced = scFalse;
setValue(scForcedInstallation, forced);
+ setValue(scContentSha1, package.data(scContentSha1).toString());
+
+ if (d->m_core->isPackageViewer())
+ return;
setLocalTempPath(QInstaller::pathFromUrl(package.packageSource().url));
const QStringList uis = package.data(QLatin1String("UserInterfaces")).toString()
diff --git a/src/libs/installer/component_p.cpp b/src/libs/installer/component_p.cpp
index 8533d8e4c..0f74e423c 100644
--- a/src/libs/installer/component_p.cpp
+++ b/src/libs/installer/component_p.cpp
@@ -54,6 +54,7 @@ ComponentPrivate::ComponentPrivate(PackageManagerCore *core, Component *qq)
, m_autoCreateOperations(true)
, m_operationsCreatedSuccessfully(true)
, m_updateIsAvailable(false)
+ , m_unstable(false)
{
}
diff --git a/src/libs/installer/componentmodel.cpp b/src/libs/installer/componentmodel.cpp
index aab487b45..642828ad7 100644
--- a/src/libs/installer/componentmodel.cpp
+++ b/src/libs/installer/componentmodel.cpp
@@ -260,9 +260,9 @@ bool ComponentModel::setData(const QModelIndex &index, const QVariant &value, in
newValue = (oldValue == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
}
QSet<QModelIndex> changed = updateCheckedState(nodes << component, newValue);
- foreach (const QModelIndex &index, changed) {
- emit dataChanged(index, index);
- emit checkStateChanged(index);
+ foreach (const QModelIndex &changedIndex, changed) {
+ emit dataChanged(changedIndex, changedIndex);
+ emit checkStateChanged(changedIndex);
}
updateAndEmitModelState(); // update the internal state
} else {
diff --git a/src/libs/installer/componentselectionpage_p.cpp b/src/libs/installer/componentselectionpage_p.cpp
index a9f4ba134..974ae1502 100644
--- a/src/libs/installer/componentselectionpage_p.cpp
+++ b/src/libs/installer/componentselectionpage_p.cpp
@@ -49,6 +49,7 @@
#include <QFileDialog>
#include <QStackedLayout>
#include <QStackedWidget>
+#include <QToolBox>
namespace QInstaller {
@@ -66,19 +67,29 @@ ComponentSelectionPagePrivate::ComponentSelectionPagePrivate(ComponentSelectionP
, m_updaterModel(m_core->updaterComponentModel())
, m_currentModel(m_allModel)
, m_allowCompressedRepositoryInstall(false)
+ , m_toolBox(nullptr)
+ , m_descriptionBaseWidget(nullptr)
, m_categoryWidget(Q_NULLPTR)
+ , m_categoryLayoutVisible(false)
{
m_treeView->setObjectName(QLatin1String("ComponentsTreeView"));
- QVBoxLayout *descriptionVLayout = new QVBoxLayout;
+ m_descriptionBaseWidget = new QWidget(q);
+ m_descriptionBaseWidget->setObjectName(QLatin1String("DescriptionBaseWidget"));
+
+ QVBoxLayout *descriptionVLayout = new QVBoxLayout(m_descriptionBaseWidget);
descriptionVLayout->setObjectName(QLatin1String("DescriptionLayout"));
+ descriptionVLayout->setContentsMargins(0, 0, 0, 0);
+
+ m_toolBox = new QToolBox(q);
+ m_toolBox->setObjectName(QLatin1String("ToolBox"));
QScrollArea *descriptionScrollArea = new QScrollArea(q);
descriptionScrollArea->setWidgetResizable(true);
descriptionScrollArea->setFrameShape(QFrame::NoFrame);
descriptionScrollArea->setObjectName(QLatin1String("DescriptionScrollArea"));
- m_descriptionLabel = new QLabel(q);
+ m_descriptionLabel = new QLabel(m_descriptionBaseWidget);
m_descriptionLabel->setWordWrap(true);
m_descriptionLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
m_descriptionLabel->setOpenExternalLinks(true);
@@ -87,8 +98,7 @@ ComponentSelectionPagePrivate::ComponentSelectionPagePrivate(ComponentSelectionP
descriptionScrollArea->setWidget(m_descriptionLabel);
descriptionVLayout->addWidget(descriptionScrollArea);
- m_sizeLabel = new QLabel(q);
- m_sizeLabel->setMargin(5);
+ m_sizeLabel = new QLabel(m_descriptionBaseWidget);
m_sizeLabel->setWordWrap(true);
m_sizeLabel->setObjectName(QLatin1String("ComponentSizeLabel"));
descriptionVLayout->addWidget(m_sizeLabel);
@@ -151,11 +161,11 @@ ComponentSelectionPagePrivate::ComponentSelectionPagePrivate(ComponentSelectionP
QWidget *mainStackedWidget = new QWidget();
m_mainGLayout = new QGridLayout(mainStackedWidget);
- m_mainGLayout->addLayout(buttonHLayout, 0, 1);
- m_mainGLayout->addLayout(treeViewVLayout, 1, 1);
- m_mainGLayout->addLayout(descriptionVLayout, 1, 2);
- m_mainGLayout->setColumnStretch(1, 3);
- m_mainGLayout->setColumnStretch(2, 2);
+ m_mainGLayout->addLayout(buttonHLayout, 0, 0);
+ m_mainGLayout->addLayout(treeViewVLayout, 1, 0);
+ m_mainGLayout->addWidget(m_descriptionBaseWidget, 1, 1);
+ m_mainGLayout->setColumnStretch(0, 3);
+ m_mainGLayout->setColumnStretch(1, 2);
m_stackedLayout = new QStackedLayout(q);
m_stackedLayout->addWidget(mainStackedWidget);
@@ -227,11 +237,11 @@ void ComponentSelectionPagePrivate::setupCategoryLayout()
vLayout->setContentsMargins(0, 0, 0, 0);
m_categoryWidget->setLayout(vLayout);
m_categoryGroupBox = new QGroupBox(q);
- m_categoryGroupBox->setTitle(m_core->settings().repositoryCategoryDisplayName());
m_categoryGroupBox->setObjectName(QLatin1String("CategoryGroupBox"));
QVBoxLayout *categoryLayout = new QVBoxLayout(m_categoryGroupBox);
QPushButton *fetchCategoryButton = new QPushButton(tr("Filter"));
fetchCategoryButton->setObjectName(QLatin1String("FetchCategoryButton"));
+ fetchCategoryButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
fetchCategoryButton->setToolTip(
ComponentSelectionPage::tr("Filter the enabled repository categories to selection."));
connect(fetchCategoryButton, &QPushButton::clicked, this,
@@ -249,16 +259,29 @@ void ComponentSelectionPagePrivate::setupCategoryLayout()
vLayout->addWidget(m_categoryGroupBox);
vLayout->addStretch();
- m_mainGLayout->addWidget(m_categoryWidget, 1, 0);
+ m_toolBox->insertItem(1, m_categoryWidget, m_core->settings().repositoryCategoryDisplayName());
}
void ComponentSelectionPagePrivate::showCategoryLayout(bool show)
{
+ if (!show && !m_categoryWidget)
+ return;
+
+ if (show == m_categoryLayoutVisible)
+ return;
+
+ setupCategoryLayout();
if (show) {
- setupCategoryLayout();
+ m_mainGLayout->removeWidget(m_descriptionBaseWidget);
+ m_toolBox->insertItem(0, m_descriptionBaseWidget, tr("Component Information"));
+ m_mainGLayout->addWidget(m_toolBox, 1, 1);
+ } else {
+ m_toolBox->removeItem(0);
+ m_mainGLayout->removeWidget(m_toolBox);
+ m_mainGLayout->addWidget(m_descriptionBaseWidget, 1, 1);
}
- if (m_categoryWidget)
- m_categoryWidget->setVisible(show);
+ m_toolBox->setVisible(show);
+ m_categoryLayoutVisible = show;
}
void ComponentSelectionPagePrivate::updateTreeView()
@@ -399,10 +422,9 @@ void ComponentSelectionPagePrivate::fetchRepositoryCategories()
{
updateWidgetVisibility(true);
- QCheckBox *checkbox;
QList<QCheckBox*> checkboxes = m_categoryGroupBox->findChildren<QCheckBox *>();
for (int i = 0; i < checkboxes.count(); i++) {
- checkbox = checkboxes.at(i);
+ QCheckBox *checkbox = checkboxes.at(i);
enableRepositoryCategory(checkbox->objectName(), checkbox->isChecked());
}
diff --git a/src/libs/installer/componentselectionpage_p.h b/src/libs/installer/componentselectionpage_p.h
index 37f808286..d2d30e3f0 100644
--- a/src/libs/installer/componentselectionpage_p.h
+++ b/src/libs/installer/componentselectionpage_p.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -46,6 +46,7 @@ class QVBoxLayout;
class QHBoxLayout;
class QGridLayout;
class QStackedLayout;
+class QToolBox;
namespace QInstaller {
@@ -88,6 +89,8 @@ private:
ComponentSelectionPage *q;
PackageManagerCore *m_core;
QTreeView *m_treeView;
+ QToolBox *m_toolBox;
+ QWidget *m_descriptionBaseWidget;
QLabel *m_sizeLabel;
QLabel *m_descriptionLabel;
QPushButton *m_checkAll;
@@ -99,6 +102,7 @@ private:
QProgressBar *m_progressBar;
QGridLayout *m_mainGLayout;
bool m_allowCompressedRepositoryInstall;
+ bool m_categoryLayoutVisible;
ComponentModel *m_allModel;
ComponentModel *m_updaterModel;
ComponentModel *m_currentModel;
diff --git a/src/libs/installer/constants.h b/src/libs/installer/constants.h
index 42b14ce63..0e16d4c4b 100644
--- a/src/libs/installer/constants.h
+++ b/src/libs/installer/constants.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -67,6 +67,7 @@ static const QLatin1String scUncompressedSizeSum("UncompressedSizeSum");
static const QLatin1String scRequiresAdminRights("RequiresAdminRights");
static const QLatin1String scOfflineBinaryName("OfflineBinaryName");
static const QLatin1String scSHA1("SHA1");
+static const QLatin1String scContentSha1("ContentSha1");
// constants used throughout the components class
static const QLatin1String scVirtual("Virtual");
@@ -202,6 +203,8 @@ static const QLatin1String scCreateLocalRepositoryShort("cl");
static const QLatin1String scCreateLocalRepositoryLong("create-local-repository");
static const QLatin1String scNoDefaultInstallationShort("nd");
static const QLatin1String scNoDefaultInstallationLong("no-default-installations");
+static const QLatin1String scFilterPackagesShort("fp");
+static const QLatin1String scFilterPackagesLong("filter-packages");
// Developer options
static const QLatin1String scScriptShort("s");
diff --git a/src/libs/installer/installiconsoperation.cpp b/src/libs/installer/installiconsoperation.cpp
index 9443b7f71..de1ddcc4f 100644
--- a/src/libs/installer/installiconsoperation.cpp
+++ b/src/libs/installer/installiconsoperation.cpp
@@ -134,8 +134,8 @@ bool InstallIconsOperation::performOperation()
if (status == PackageManagerCore::Canceled || status == PackageManagerCore::Failure)
return true;
- const QString &source = it.next();
- QString target = targetDir.absoluteFilePath(sourceDir.relativeFilePath(source));
+ const QString &source2 = it.next();
+ QString target = targetDir.absoluteFilePath(sourceDir.relativeFilePath(source2));
emit outputTextChanged(target);
@@ -185,7 +185,7 @@ bool InstallIconsOperation::performOperation()
}
// copy the file to its new location
- QFile cf(source);
+ QFile cf(source2);
if (!cf.copy(target)) {
setError(UserDefinedError);
setErrorString(tr("Failed to copy file \"%1\": %2").arg(
@@ -193,8 +193,8 @@ bool InstallIconsOperation::performOperation()
undoOperation();
return false;
}
- deleteFileNowOrLater(source);
- files.push_back(source);
+ deleteFileNowOrLater(source2);
+ files.push_back(source2);
files.push_back(target);
setValue(QLatin1String("files"), files);
} else if (fi.isDir() && !QDir(target).exists()) {
diff --git a/src/libs/installer/keepaliveobject.cpp b/src/libs/installer/keepaliveobject.cpp
index 94e91efd8..18ec9743a 100644
--- a/src/libs/installer/keepaliveobject.cpp
+++ b/src/libs/installer/keepaliveobject.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -48,7 +48,12 @@ KeepAliveObject::KeepAliveObject()
void KeepAliveObject::start()
{
+ if (m_timer)
+ delete m_timer;
m_timer = new QTimer(this);
+
+ if (m_socket)
+ delete m_socket;
m_socket = new QLocalSocket(this);
connect(m_timer, &QTimer::timeout, [this]() {
diff --git a/src/libs/installer/loggingutils.cpp b/src/libs/installer/loggingutils.cpp
index 0ebba10db..45f7aab1b 100644
--- a/src/libs/installer/loggingutils.cpp
+++ b/src/libs/installer/loggingutils.cpp
@@ -259,7 +259,7 @@ void LoggingHandler::printComponentInfo(const QList<Component *> components) con
QDomElement root = doc.createElement(QLatin1String("updates"));
doc.appendChild(root);
- foreach (Component *component, components) {
+ foreach (const Component *component, components) {
QDomElement update = doc.createElement(QLatin1String("update"));
update.setAttribute(QLatin1String("name"), component->value(scDisplayName));
update.setAttribute(QLatin1String("version"), component->value(scVersion));
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index 145eb30d7..61b2273af 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -1556,9 +1556,8 @@ bool PackageManagerCore::fetchPackagesTree(const PackagesList &packages, const L
continue;
const LocalPackage localPackage = installedPackages.value(name);
- const QString updateVersion = update->data(scVersion).toString();
- if (KDUpdater::compareVersion(updateVersion, localPackage.version) <= 0)
- continue; // remote version equals or is less than the installed maintenance tool
+ if (!d->packageNeedsUpdate(localPackage, update))
+ continue;
const QDate updateDate = update->data(scReleaseDate).toDate();
if (localPackage.lastUpdateDate >= updateDate)
@@ -2192,26 +2191,50 @@ ComponentModel *PackageManagerCore::updaterComponentModel() const
/*!
Lists available packages filtered with \a regexp without GUI. Virtual
- components are not listed unless set visible.
+ components are not listed unless set visible. Optionally, a \a filters
+ hash containing package information elements and regular expressions
+ can be used to further filter listed packages.
\sa setVirtualComponentsVisible()
*/
-void PackageManagerCore::listAvailablePackages(const QString &regexp)
+void PackageManagerCore::listAvailablePackages(const QString &regexp, const QHash<QString, QString> &filters)
{
+ setPackageViewer();
qCDebug(QInstaller::lcInstallerInstallLog)
<< "Searching packages with regular expression:" << regexp;
+
+ ComponentModel *model = defaultComponentModel();
d->fetchMetaInformationFromRepositories(DownloadType::UpdatesXML);
d->addUpdateResourcesFromRepositories(true);
QRegularExpression re(regexp);
const PackagesList &packages = d->remotePackages();
+ if (!fetchAllPackages(packages, LocalPackagesHash())) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "There was a problem with loading the package data.";
+ return;
+ }
PackagesList matchedPackages;
foreach (Package *package, packages) {
const QString name = package->data(scName).toString();
- if (re.match(name).hasMatch() &&
- (virtualComponentsVisible() ? true : !package->data(scVirtual, false).toBool())) {
- matchedPackages.append(package);
+ Component *component = componentByName(name);
+ if (!component)
+ continue;
+
+ const QModelIndex &idx = model->indexFromComponentName(component->treeName());
+ if (idx.isValid() && re.match(name).hasMatch()) {
+ bool ignoreComponent = false;
+ for (auto &key : filters.keys()) {
+ const QString elementValue = component->value(key);
+ QRegularExpression elementRegexp(filters.value(key));
+ if (elementValue.isEmpty() || !elementRegexp.match(elementValue).hasMatch()) {
+ ignoreComponent = true;
+ break;
+ }
+ }
+ if (!ignoreComponent)
+ matchedPackages.append(package);
}
}
if (matchedPackages.count() == 0)
@@ -2288,10 +2311,26 @@ bool PackageManagerCore::checkComponentsForInstallation(const QStringList &compo
model->setData(idx, Qt::Checked, Qt::CheckStateRole);
installComponentsFound = true;
}
- } else { // idx is invalid and component valid when we have invisible virtual component
- component->isVirtual()
- ? errorMessage.append(tr("Cannot install %1. Component is virtual.\n").arg(name))
- : errorMessage.append(tr("Cannot install %1. Component not found.\n").arg(name));
+ } else {
+ auto isDescendantOfVirtual = [&]() {
+ Component *trace = component;
+ forever {
+ trace = trace->parentComponent();
+ if (!trace) {
+ // We already checked the root component if there is no parent
+ return false;
+ } else if (trace->isVirtual()) {
+ errorMessage.append(tr("Cannot install %1. Component is descendant "
+ "of a virtual component %2.\n").arg(name, trace->name()));
+ return true;
+ }
+ }
+ };
+ // idx is invalid and component valid when we have invisible virtual component
+ if (component->isVirtual())
+ errorMessage.append(tr("Cannot install %1. Component is virtual.\n").arg(name));
+ else if (!isDescendantOfVirtual())
+ errorMessage.append(tr("Cannot install %1. Component not found.\n").arg(name));
}
}
if (!installComponentsFound)
@@ -2305,6 +2344,7 @@ bool PackageManagerCore::checkComponentsForInstallation(const QStringList &compo
*/
void PackageManagerCore::listInstalledPackages(const QString &regexp)
{
+ setPackageViewer();
LocalPackagesHash installedPackages = this->localInstalledPackages();
if (!regexp.isEmpty()) {
@@ -2342,6 +2382,7 @@ PackageManagerCore::Status PackageManagerCore::updateComponentsSilently(const QS
if (componentList.count() == 0) {
qCDebug(QInstaller::lcInstallerInstallLog) << "No updates available.";
+ setCanceled();
} else {
// Check if essential components are available (essential components are disabled).
// If essential components are found, update first essential updates,
@@ -3402,11 +3443,11 @@ bool PackageManagerCore::isPackageManager() const
}
/*!
- Sets current installer to be offline generator based on \a offlineGenerator.
+ Sets current installer to be offline generator.
*/
-void PackageManagerCore::setOfflineGenerator(bool offlineGenerator)
+void PackageManagerCore::setOfflineGenerator()
{
- d->m_offlineGenerator = offlineGenerator;
+ d->m_magicMarkerSupplement = BinaryContent::OfflineGenerator;
}
/*!
@@ -3420,6 +3461,24 @@ bool PackageManagerCore::isOfflineGenerator() const
}
/*!
+ Sets the current installer as the package viewer.
+*/
+void PackageManagerCore::setPackageViewer()
+{
+ d->m_magicMarkerSupplement = BinaryContent::PackageViewer;
+}
+
+/*!
+ Returns \c true if the current installer is executed as package viewer.
+
+ \sa {installer::isPackageViewer}{installer.isPackageViewer}
+*/
+bool PackageManagerCore::isPackageViewer() const
+{
+ return d->isPackageViewer();
+}
+
+/*!
Sets the installer magic binary marker based on \a magicMarker and
userSetBinaryMarker to \c true.
*/
@@ -3660,7 +3719,7 @@ void PackageManagerCore::storeReplacedComponents(QHash<QString, Component *> &co
qCWarning(QInstaller::lcDeveloperBuild) << componentName << "- Does not exist in the repositories anymore.";
continue;
}
- if (!componentToReplace && !d->componentsToReplace().contains(componentName)) {
+ if (!d->componentsToReplace().contains(componentName)) {
componentToReplace = new Component(this);
componentToReplace->setValue(scName, componentName);
} else {
@@ -3799,10 +3858,8 @@ 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(scVersion).toString();
- if (KDUpdater::compareVersion(updateVersion, localPackage.version) <= 0)
+ if (!d->packageNeedsUpdate(localPackage, update))
continue;
-
// It is quite possible that we may have already installed the update. Lets check the last
// update date of the package and the release date of the update. This way we can compare and
// figure out if the update has been installed or not.
diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h
index d4833a979..b5ef6304e 100644
--- a/src/libs/installer/packagemanagercore.h
+++ b/src/libs/installer/packagemanagercore.h
@@ -33,6 +33,7 @@
#include "repository.h"
#include "qinstallerglobal.h"
#include "utils.h"
+#include "commandlineparser.h"
#include <QtCore/QHash>
#include <QtCore/QObject>
@@ -242,7 +243,8 @@ public:
ComponentModel *defaultComponentModel() const;
ComponentModel *updaterComponentModel() const;
void listInstalledPackages(const QString &regexp = QString());
- void listAvailablePackages(const QString &regexp);
+ void listAvailablePackages(const QString &regexp = QString(),
+ const QHash<QString, QString> &filters = QHash<QString, QString>());
PackageManagerCore::Status updateComponentsSilently(const QStringList &componentsToUpdate);
PackageManagerCore::Status installSelectedComponentsSilently(const QStringList& components);
PackageManagerCore::Status installDefaultComponentsSilently();
@@ -264,9 +266,12 @@ public:
Q_INVOKABLE void setPackageManager();
Q_INVOKABLE bool isPackageManager() const;
- void setOfflineGenerator(bool offlineGenerator = true);
+ void setOfflineGenerator();
Q_INVOKABLE bool isOfflineGenerator() const;
+ void setPackageViewer();
+ Q_INVOKABLE bool isPackageViewer() const;
+
void setUserSetBinaryMarker(qint64 magicMarker);
Q_INVOKABLE bool isUserSetBinaryMarker() const;
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index 24a67d095..0f1bb90be 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -225,6 +225,7 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
, m_repoFetched(false)
, m_updateSourcesAdded(false)
, m_magicBinaryMarker(0) // initialize with pseudo marker
+ , m_magicMarkerSupplement(BinaryContent::Default)
, m_componentsToInstallCalculated(false)
, m_componentScriptEngine(nullptr)
, m_controlScriptEngine(nullptr)
@@ -243,7 +244,6 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
, m_autoAcceptLicenses(false)
, m_disableWriteMaintenanceTool(false)
, m_autoConfirmCommand(false)
- , m_offlineGenerator(false)
{
}
@@ -264,6 +264,7 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q
, m_repoFetched(false)
, m_updateSourcesAdded(false)
, m_magicBinaryMarker(magicInstallerMaker)
+ , m_magicMarkerSupplement(BinaryContent::Default)
, m_componentsToInstallCalculated(false)
, m_componentScriptEngine(nullptr)
, m_controlScriptEngine(nullptr)
@@ -282,7 +283,6 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q
, m_autoAcceptLicenses(false)
, m_disableWriteMaintenanceTool(false)
, m_autoConfirmCommand(false)
- , m_offlineGenerator(false)
{
foreach (const OperationBlob &operation, performedOperations) {
QScopedPointer<QInstaller::Operation> op(KDUpdater::UpdateOperationFactory::instance()
@@ -717,7 +717,12 @@ bool PackageManagerCorePrivate::isPackageManager() const
bool PackageManagerCorePrivate::isOfflineGenerator() const
{
- return m_offlineGenerator;
+ return m_magicMarkerSupplement == BinaryContent::OfflineGenerator;
+}
+
+bool PackageManagerCorePrivate::isPackageViewer() const
+{
+ return m_magicMarkerSupplement == BinaryContent::PackageViewer;
}
bool PackageManagerCorePrivate::statusCanceledOrFailed() const
@@ -2246,7 +2251,8 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr
component->value(scUncompressedSize).toULongLong(),
component->value(scInheritVersion),
component->isCheckable(),
- component->isExpandedByDefault());
+ component->isExpandedByDefault(),
+ component->value(scContentSha1));
m_localPackageHub->writeToDisk();
component->setInstalled();
@@ -2908,4 +2914,19 @@ bool PackageManagerCorePrivate::askUserConfirmCommand() const
}
}
+bool PackageManagerCorePrivate::packageNeedsUpdate(const LocalPackage &localPackage, const Package *update) const
+{
+ bool updateNeeded = true;
+ const QString contentSha1 = update->data(scContentSha1).toString();
+ if (!contentSha1.isEmpty()) {
+ if (contentSha1 == localPackage.contentSha1)
+ updateNeeded = false;
+ } else {
+ const QString updateVersion = update->data(scVersion).toString();
+ if (KDUpdater::compareVersion(updateVersion, localPackage.version) <= 0)
+ updateNeeded = false;
+ }
+ return updateNeeded;
+}
+
} // namespace QInstaller
diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h
index 858baf9eb..b29808228 100644
--- a/src/libs/installer/packagemanagercore_p.h
+++ b/src/libs/installer/packagemanagercore_p.h
@@ -132,6 +132,8 @@ public:
bool runOfflineGenerator();
bool isOfflineGenerator() const;
+ bool isPackageViewer() const;
+
QString replaceVariables(const QString &str) const;
QByteArray replaceVariables(const QByteArray &str) const;
@@ -254,6 +256,7 @@ private:
bool acceptLicenseAgreements() const;
bool askUserAcceptLicense(const QString &name, const QString &content) const;
bool askUserConfirmCommand() const;
+ bool packageNeedsUpdate(const LocalPackage &localPackage, const Package *update) const;
private:
PackageManagerCore *m_core;
@@ -264,9 +267,10 @@ private:
bool m_repoFetched;
bool m_updateSourcesAdded;
qint64 m_magicBinaryMarker;
+ int m_magicMarkerSupplement;
+
bool m_componentsToInstallCalculated;
- bool m_foundEssentialUpdate;
- bool m_offlineGenerator;
+ bool m_foundEssentialUpdate;;
mutable ScriptEngine *m_componentScriptEngine;
mutable ScriptEngine *m_controlScriptEngine;
diff --git a/src/libs/installer/packagemanagergui.cpp b/src/libs/installer/packagemanagergui.cpp
index 86c3a2d0c..d52034389 100644
--- a/src/libs/installer/packagemanagergui.cpp
+++ b/src/libs/installer/packagemanagergui.cpp
@@ -321,7 +321,7 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
QFile sheet(styleSheetFile);
if (sheet.exists()) {
if (sheet.open(QIODevice::ReadOnly)) {
- setStyleSheet(QString::fromLatin1(sheet.readAll()));
+ qApp->setStyleSheet(QString::fromLatin1(sheet.readAll()));
} else {
qCWarning(QInstaller::lcDeveloperBuild) << "The specified style sheet file "
"can not be opened.";
diff --git a/src/libs/installer/performinstallationform.cpp b/src/libs/installer/performinstallationform.cpp
index 2fb6026cc..31b61ceeb 100644
--- a/src/libs/installer/performinstallationform.cpp
+++ b/src/libs/installer/performinstallationform.cpp
@@ -80,6 +80,7 @@ PerformInstallationForm::PerformInstallationForm(QObject *parent)
: QObject(parent)
, m_progressBar(nullptr)
, m_progressLabel(nullptr)
+ , m_downloadStatus(nullptr)
, m_productImagesScrollArea(nullptr)
, m_productImagesLabel(nullptr)
, m_detailsButton(nullptr)
diff --git a/src/libs/installer/qsettingswrapper.cpp b/src/libs/installer/qsettingswrapper.cpp
index 56db28d78..f57750bc1 100644
--- a/src/libs/installer/qsettingswrapper.cpp
+++ b/src/libs/installer/qsettingswrapper.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -74,9 +74,9 @@ public:
Private(const QString &fileName, QSettings::Format format)
: m_filename(fileName)
+ , m_format(format)
, settings(fileName, format)
{
- m_format = format;
m_scope = settings.scope();
m_application = settings.applicationName();
m_organization = settings.organizationName();
diff --git a/src/libs/installer/utils.cpp b/src/libs/installer/utils.cpp
index 59be2171b..7506a13fe 100644
--- a/src/libs/installer/utils.cpp
+++ b/src/libs/installer/utils.cpp
@@ -351,12 +351,12 @@ static QString qt_create_commandline(const QString &program, const QStringList &
// as escaping the quote -- rather put the \ behind the quote: e.g.
// rather use "foo"\ than "foo\"
QString endQuote(QLatin1Char('\"'));
- int i = tmp.length();
- while (i > 0 && tmp.at(i - 1) == QLatin1Char('\\')) {
- --i;
+ int j = tmp.length();
+ while (j > 0 && tmp.at(j - 1) == QLatin1Char('\\')) {
+ --j;
endQuote += QLatin1Char('\\');
}
- args += QLatin1String(" \"") + tmp.left(i) + endQuote;
+ args += QLatin1String(" \"") + tmp.left(j) + endQuote;
} else {
args += QLatin1Char(' ') + tmp;
}
diff --git a/src/libs/kdtools/filedownloader.cpp b/src/libs/kdtools/filedownloader.cpp
index 4cccfd9ca..a9f5040f0 100644
--- a/src/libs/kdtools/filedownloader.cpp
+++ b/src/libs/kdtools/filedownloader.cpp
@@ -192,6 +192,7 @@ struct KDUpdater::FileDownloader::Private
: m_hash(QCryptographicHash::Sha1)
, m_assumedSha1Sum("")
, autoRemove(true)
+ , followRedirect(false)
, m_speedTimerInterval(100)
, m_downloadDeadlineTimerInterval(30000)
, m_downloadPaused(false)
@@ -255,7 +256,6 @@ KDUpdater::FileDownloader::FileDownloader(const QString &scheme, QObject *parent
, d(new Private)
{
d->scheme = scheme;
- d->followRedirect = false;
}
/*!
diff --git a/src/libs/kdtools/localpackagehub.cpp b/src/libs/kdtools/localpackagehub.cpp
index 1a754d7d5..2ee880e04 100644
--- a/src/libs/kdtools/localpackagehub.cpp
+++ b/src/libs/kdtools/localpackagehub.cpp
@@ -327,7 +327,8 @@ void LocalPackageHub::addPackage(const QString &name,
quint64 uncompressedSize,
const QString &inheritVersionFrom,
bool checkable,
- bool expandedByDefault)
+ bool expandedByDefault,
+ const QString &contentSha1)
{
// TODO: This somewhat unexpected, remove?
if (d->m_packageInfoMap.contains(name)) {
@@ -350,6 +351,7 @@ void LocalPackageHub::addPackage(const QString &name,
info.uncompressedSize = uncompressedSize;
info.checkable = checkable;
info.expandedByDefault = expandedByDefault;
+ info.contentSha1 = contentSha1;
d->m_packageInfoMap.insert(name, info);
}
d->modified = true;
@@ -426,6 +428,8 @@ void LocalPackageHub::writeToDisk()
addTextChildHelper(&package, QLatin1String("Checkable"), QLatin1String("true"));
if (info.expandedByDefault)
addTextChildHelper(&package, QLatin1String("ExpandedByDefault"), QLatin1String("true"));
+ if (!info.contentSha1.isEmpty())
+ addTextChildHelper(&package, scContentSha1, info.contentSha1);
root.appendChild(package);
}
@@ -498,6 +502,8 @@ void LocalPackageHub::PackagesInfoData::addPackageFrom(const QDomElement &packag
info.checkable = childNodeE.text().toLower() == QLatin1String("true") ? true : false;
else if (childNodeE.tagName() == QLatin1String("ExpandedByDefault"))
info.expandedByDefault = childNodeE.text().toLower() == QLatin1String("true") ? true : false;
+ else if (childNodeE.tagName() == QLatin1String("ContentSha1"))
+ info.contentSha1 = childNodeE.text();
}
m_packageInfoMap.insert(info.name, info);
}
diff --git a/src/libs/kdtools/localpackagehub.h b/src/libs/kdtools/localpackagehub.h
index d43c4a6a5..648d6cf6e 100644
--- a/src/libs/kdtools/localpackagehub.h
+++ b/src/libs/kdtools/localpackagehub.h
@@ -55,6 +55,7 @@ struct KDTOOLS_EXPORT LocalPackage
quint64 uncompressedSize;
bool checkable;
bool expandedByDefault;
+ QString contentSha1;
};
class KDTOOLS_EXPORT LocalPackageHub
@@ -108,7 +109,8 @@ public:
quint64 uncompressedSize,
const QString &inheritVersionFrom,
bool checkable,
- bool expandedByDefault);
+ bool expandedByDefault,
+ const QString &contentSha1);
bool removePackage(const QString &pkgName);
void refresh();
diff --git a/src/libs/kdtools/selfrestarter.cpp b/src/libs/kdtools/selfrestarter.cpp
index e94d0fea7..7771fafac 100644
--- a/src/libs/kdtools/selfrestarter.cpp
+++ b/src/libs/kdtools/selfrestarter.cpp
@@ -36,19 +36,21 @@ class SelfRestarter::Private
{
public:
Private(int argc, char *argv[])
- : restartOnQuit(false)
+ : executable(QString::fromLocal8Bit(argv[0]))
+ , restartOnQuit(false)
+ , workingPath(QDir::currentPath())
{
- executable = QString::fromLocal8Bit(argv[0]);
- workingPath = QDir::currentPath();
+
for (int i = 1; i < argc; ++i)
args << QString::fromLocal8Bit(argv[i]);
}
Private()
+ : executable(qApp->applicationFilePath())
+ , args(qApp->arguments().mid(1))
+ , restartOnQuit(false)
+ , workingPath(QDir::currentPath())
{
- executable = qApp->applicationFilePath();
- workingPath = QDir::currentPath();
- args = qApp->arguments().mid(1);
}
~Private()
diff --git a/src/libs/kdtools/updatefinder.cpp b/src/libs/kdtools/updatefinder.cpp
index 535dfde3d..034e162d3 100644
--- a/src/libs/kdtools/updatefinder.cpp
+++ b/src/libs/kdtools/updatefinder.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -79,8 +79,9 @@ public:
RemoveExisting
};
- Private(UpdateFinder *qq)
+ explicit Private(UpdateFinder *qq)
: q(qq)
+ , cancel(false)
, downloadCompleteCount(0)
, m_downloadsToComplete(0)
{}
@@ -93,7 +94,7 @@ public:
struct Data {
Data()
: downloader(0) {}
- Data(const PackageSource &i, FileDownloader *d = 0)
+ explicit Data(const PackageSource &i, FileDownloader *d = 0)
: info(i), downloader(d) {}
PackageSource info;
diff --git a/src/libs/kdtools/updateoperation.cpp b/src/libs/kdtools/updateoperation.cpp
index 00b059af1..897fecf1b 100644
--- a/src/libs/kdtools/updateoperation.cpp
+++ b/src/libs/kdtools/updateoperation.cpp
@@ -283,7 +283,7 @@ void UpdateOperation::setRequiresUnreplacedVariables(bool isRequired)
struct StartsWith
{
- StartsWith(const QString &searchTerm)
+ explicit StartsWith(const QString &searchTerm)
: m_searchTerm(searchTerm) {}
bool operator()(const QString &searchString)
diff --git a/src/libs/kdtools/updatesinfo.cpp b/src/libs/kdtools/updatesinfo.cpp
index 3119b6240..eaa9b039e 100644
--- a/src/libs/kdtools/updatesinfo.cpp
+++ b/src/libs/kdtools/updatesinfo.cpp
@@ -125,8 +125,8 @@ bool UpdatesInfoData::parsePackageUpdateElement(const QDomElement &updateE)
} else if (childE.tagName() == QLatin1String("Licenses")) {
QHash<QString, QVariant> licenseHash;
const QDomNodeList licenseNodes = childE.childNodes();
- for (int i = 0; i < licenseNodes.count(); ++i) {
- const QDomNode licenseNode = licenseNodes.at(i);
+ for (int index = 0; index < licenseNodes.count(); ++index) {
+ const QDomNode licenseNode = licenseNodes.at(index);
if (licenseNode.nodeName() == QLatin1String("License")) {
QDomElement element = licenseNode.toElement();
QVariantMap attributes;
@@ -210,8 +210,8 @@ QVariant UpdatesInfoData::parseOperations(const QDomNodeList &operationNodes)
if (operationNode.nodeName() == QLatin1String("Operation")) {
const QDomNodeList argumentNodes = operationNode.childNodes();
QStringList attributes;
- for (int i = 0; i < argumentNodes.count(); ++i) {
- const QDomNode argumentNode = argumentNodes.at(i);
+ for (int index = 0; index < argumentNodes.count(); ++index) {
+ const QDomNode argumentNode = argumentNodes.at(index);
if (argumentNode.nodeName() == QLatin1String("Argument")) {
QDomElement argumentElement = argumentNode.toElement();
attributes.append(argumentElement.text());