diff options
author | Tim Jenssen <tim.jenssen@digia.com> | 2014-01-17 14:34:57 +0100 |
---|---|---|
committer | Tim Jenssen <tim.jenssen@digia.com> | 2014-01-17 14:36:23 +0100 |
commit | fe92a09482c5abf7f2c56901f2d60e287282f939 (patch) | |
tree | fbfcefcc6f86dd2980b6b5816dece03664c57a76 /src | |
parent | 0b5241a696cf05612dae2c8810022f5e205d42df (diff) | |
parent | faa8f39bdd8c13b21c19bec1592f18e710c56206 (diff) |
Merge remote-tracking branch 'origin/1.5'
Change-Id: I64c405bdefa700e614b9a9d8f24f490856322d04
Diffstat (limited to 'src')
77 files changed, 1661 insertions, 700 deletions
diff --git a/src/libs/7zip/7zip.pro b/src/libs/7zip/7zip.pro index 549778e67..01b69dad2 100644 --- a/src/libs/7zip/7zip.pro +++ b/src/libs/7zip/7zip.pro @@ -1,8 +1,7 @@ -include(../../../installerfw.pri) - QT = core TARGET = 7z TEMPLATE = lib +include(../../../installerfw.pri) INCLUDEPATH += . .. CONFIG += staticlib DESTDIR = $$IFW_LIB_PATH diff --git a/src/libs/installer/adminauthorization_win.cpp b/src/libs/installer/adminauthorization_win.cpp index 03003b21a..528f3403d 100644 --- a/src/libs/installer/adminauthorization_win.cpp +++ b/src/libs/installer/adminauthorization_win.cpp @@ -45,17 +45,14 @@ #include <QDebug> #include <QDir> +#include <qt_windows.h> + #ifdef Q_CC_MINGW -# ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 -# endif # ifndef SEE_MASK_NOASYNC # define SEE_MASK_NOASYNC 0x00000100 # endif #endif -#include <windows.h> - struct DeCoInitializer { DeCoInitializer() diff --git a/src/libs/installer/applyproductkeyoperation.cpp b/src/libs/installer/applyproductkeyoperation.cpp index 4556df743..5b561bd19 100644 --- a/src/libs/installer/applyproductkeyoperation.cpp +++ b/src/libs/installer/applyproductkeyoperation.cpp @@ -46,6 +46,7 @@ bool ApplyProductKeyOperation::performOperation() if (!ProductKeyCheck::instance()->applyKey(arguments())) { setError(UserDefinedError); setErrorString(ProductKeyCheck::instance()->lastErrorString()); + return false; } return true; } diff --git a/src/libs/installer/binaryformat.cpp b/src/libs/installer/binaryformat.cpp index b07cc90de..7aa4d94ab 100644 --- a/src/libs/installer/binaryformat.cpp +++ b/src/libs/installer/binaryformat.cpp @@ -55,6 +55,7 @@ #include <QTemporaryFile> #include <errno.h> +#include <string.h> using namespace QInstaller; using namespace QInstallerCreator; @@ -215,38 +216,45 @@ QByteArray QInstaller::retrieveCompressedData(QIODevice *in, qint64 size) return qUncompress(ba); } +/*! + Search through 1MB, if smaller through the whole file. Note: QFile::map() does + not change QFile::pos(). Fallback to read the file content in case we can't map it. +*/ qint64 QInstaller::findMagicCookie(QFile *in, quint64 magicCookie) { Q_ASSERT(in); Q_ASSERT(in->isOpen()); Q_ASSERT(in->isReadable()); - const qint64 oldPos = in->pos(); - const qint64 MAX_SEARCH = 1024 * 1024; // stop searching after one MB - qint64 searched = 0; - try { - while (searched < MAX_SEARCH) { - const qint64 pos = in->size() - searched - sizeof(qint64); - if (pos < 0) - throw Error(QObject::tr("Searched whole file, no marker found")); - if (!in->seek(pos)) { - throw Error(QObject::tr("Could not seek to %1 in file %2: %3").arg(QString::number(pos), - in->fileName(), in->errorString())); - } - const quint64 num = static_cast<quint64>(retrieveInt64(in)); - if (num == magicCookie) { - in->seek(oldPos); - return pos; - } - searched += 1; + + const qint64 fileSize = in->size(); + const size_t markerSize = sizeof(qint64); + const qint64 maxSearch = qMin((1024LL * 1024LL), fileSize); + + QByteArray data(maxSearch, Qt::Uninitialized); + uchar *const mapped = in->map(fileSize - maxSearch, maxSearch); + if (!mapped) { + const int pos = in->pos(); + try { + in->seek(fileSize - maxSearch); + blockingRead(in, data.data(), maxSearch); + in->seek(pos); + } catch (const Error &error) { + in->seek(pos); + throw error; } - throw Error(QObject::tr("No marker found, stopped after %1.").arg(humanReadableSize(MAX_SEARCH))); - } catch (const Error& err) { - in->seek(oldPos); - throw err; - } catch (...) { - in->seek(oldPos); - throw Error(QObject::tr("No marker found, unknown exception caught.")); + } else { + data = QByteArray((const char*)mapped, maxSearch); + in->unmap(mapped); + } + + qint64 searched = maxSearch - markerSize; + while (searched >= 0) { + if (memcmp(&magicCookie, (data.data() + searched), markerSize) == 0) + return (fileSize - maxSearch) + searched; + --searched; } + throw Error(QObject::tr("No marker found, stopped after %1.").arg(humanReadableSize(maxSearch))); + return -1; // never reached } @@ -802,7 +810,7 @@ BinaryContentPrivate::BinaryContentPrivate(const BinaryContentPrivate &other) BinaryContentPrivate::~BinaryContentPrivate() { foreach (const QByteArray &rccData, m_resourceMappings) - QResource::unregisterResource((const uchar*)rccData.constData()); + QResource::unregisterResource((const uchar*)rccData.constData(), QLatin1String(":/metadata")); m_resourceMappings.clear(); } @@ -1144,6 +1152,29 @@ int BinaryContent::registerEmbeddedQResources() } /*! + Registers the passed file as default resource content. If the embedded resources are already mapped into + memory, it will replace the first with the new content. +*/ +void BinaryContent::registerAsDefaultQResource(const QString &path) +{ + QFile resource(path); + bool success = resource.open(QIODevice::ReadOnly); + if (success && (d->m_resourceMappings.count() > 0)) { + success = QResource::unregisterResource((const uchar*)d->m_resourceMappings.first().constData(), + QLatin1String(":/metadata")); + if (success) + d->m_resourceMappings.remove(0); + } + + if (success) { + d->m_resourceMappings.prepend(addResourceFromBinary(&resource, Range<qint64>::fromStartAndEnd(0, + resource.size()))); + } else { + qWarning() << QString::fromLatin1("Could not register '%1' as default resource.").arg(path); + } +} + +/*! Returns the binary component index as read from the file. */ QInstallerCreator::ComponentIndex BinaryContent::componentIndex() const diff --git a/src/libs/installer/binaryformat.h b/src/libs/installer/binaryformat.h index d255ea8a9..0abe78030 100644 --- a/src/libs/installer/binaryformat.h +++ b/src/libs/installer/binaryformat.h @@ -242,6 +242,7 @@ public: qint64 magicMarker() const; int registerEmbeddedQResources(); + void registerAsDefaultQResource(const QString &path); QInstallerCreator::ComponentIndex componentIndex() const; private: diff --git a/src/libs/installer/binaryformatenginehandler.cpp b/src/libs/installer/binaryformatenginehandler.cpp index d872ed229..1364ff431 100644 --- a/src/libs/installer/binaryformatenginehandler.cpp +++ b/src/libs/installer/binaryformatenginehandler.cpp @@ -122,3 +122,10 @@ void BinaryFormatEngineHandler::registerArchive(const QString &pathName, const Q c.appendArchive(newArchive); d->index.insertComponent(c); } + +void BinaryFormatEngineHandler::resetRegisteredArchives() +{ + QVector<QInstallerCreator::Component> registeredComponents = d->index.components(); + foreach (const QInstallerCreator::Component &component, registeredComponents) + d->index.removeComponent(component.name()); +} diff --git a/src/libs/installer/binaryformatenginehandler.h b/src/libs/installer/binaryformatenginehandler.h index cccc2f523..107f834f4 100644 --- a/src/libs/installer/binaryformatenginehandler.h +++ b/src/libs/installer/binaryformatenginehandler.h @@ -67,6 +67,7 @@ public: static BinaryFormatEngineHandler *instance(); void registerArchive(const QString &fileName, const QString &path); + void resetRegisteredArchives(); private: class Private; diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp index 0ac69aaf8..1b37cc12c 100644 --- a/src/libs/installer/component.cpp +++ b/src/libs/installer/component.cpp @@ -211,6 +211,7 @@ Component::Component(PackageManagerCore *core) setPrivate(d); connect(this, SIGNAL(valueChanged(QString, QString)), this, SLOT(updateModelData(QString, QString))); + qRegisterMetaType<QList<QInstaller::Component*> >("QList<QInstaller::Component*>"); } /*! @@ -485,14 +486,12 @@ void Component::loadComponentScript() */ void Component::loadComponentScript(const QString &fileName) { - ScriptEngine *scriptEngine = d->m_core->scriptEngine(); - // introduce the component object as javascript value and call the name to check that it // was successful QString scriptInjection(QString::fromLatin1( "var component = installer.componentByName('%1'); component.name;").arg(name())); - d->m_scriptContext = scriptEngine->loadInConext(QLatin1String("Component"), fileName, scriptInjection); + d->m_scriptContext = d->scriptEngine()->loadInConext(QLatin1String("Component"), fileName, scriptInjection); emit loaded(); languageChanged(); @@ -505,7 +504,7 @@ void Component::loadComponentScript(const QString &fileName) */ void Component::languageChanged() { - d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("retranslateUi")); + d->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("retranslateUi")); } /*! @@ -590,7 +589,7 @@ void Component::loadLicenses(const QString &directory, const QHash<QString, QVar for (it = licenseHash.begin(); it != licenseHash.end(); ++it) { const QString &fileName = it.value().toString(); - if (!ProductKeyCheck::instance(d->m_core)->isValidLicenseTextFile(fileName)) + if (!ProductKeyCheck::instance()->isValidLicenseTextFile(fileName)) continue; QFileInfo fileInfo(fileName); @@ -660,7 +659,7 @@ void Component::createOperationsForPath(const QString &path) return; // the script can override this method - if (d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext, + if (d->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("createOperationsForPath"), QScriptValueList() << path).isValid()) { return; } @@ -705,7 +704,7 @@ void Component::createOperationsForArchive(const QString &archive) return; // the script can override this method - if (d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext, + if (d->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("createOperationsForArchive"), QScriptValueList() << archive).isValid()) { return; } @@ -739,7 +738,7 @@ void Component::createOperationsForArchive(const QString &archive) void Component::beginInstallation() { // the script can override this method - if (d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext, + if (d->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("beginInstallation")).isValid()) { return; } @@ -758,7 +757,7 @@ void Component::beginInstallation() void Component::createOperations() { // the script can override this method - if (d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext, + if (d->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("createOperations")).isValid()) { d->m_operationsCreated = true; return; @@ -899,6 +898,7 @@ OperationList Component::operations() const if (!d->m_minimumProgressOperation) { d->m_minimumProgressOperation = KDUpdater::UpdateOperationFactory::instance() .create(QLatin1String("MinimumProgress")); + d->m_minimumProgressOperation->setValue(QLatin1String("component"), name()); d->m_operations.append(d->m_minimumProgressOperation); } @@ -906,6 +906,7 @@ OperationList Component::operations() const d->m_licenseOperation = KDUpdater::UpdateOperationFactory::instance() .create(QLatin1String("License")); d->m_licenseOperation->setValue(QLatin1String("installer"), QVariant::fromValue(d->m_core)); + d->m_licenseOperation->setValue(QLatin1String("component"), name()); QVariantMap licenses; const QList<QPair<QString, QString> > values = d->m_licenses.values(); @@ -1118,7 +1119,8 @@ void Component::setValidatorCallbackName(const QString &name) bool Component::validatePage() { if (!validatorCallbackName.isEmpty()) - return d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext, validatorCallbackName).toBool(); + return d->scriptEngine()->callScriptMethod( + d->m_scriptContext, validatorCallbackName).toBool(); return true; } @@ -1198,7 +1200,7 @@ bool Component::isAutoDependOn(const QSet<QString> &componentsToInstall) const if (autoDependOnList.first().compare(QLatin1String("script"), Qt::CaseInsensitive) == 0) { QScriptValue valueFromScript; try { - valueFromScript = d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext, + valueFromScript = d->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("isAutoDependOn")); } catch (const Error &error) { MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), @@ -1248,7 +1250,7 @@ bool Component::isDefault() const if (d->m_vars.value(scDefault).compare(QLatin1String("script"), Qt::CaseInsensitive) == 0) { QScriptValue valueFromScript; try { - valueFromScript = d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext, + valueFromScript = d->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("isDefault")); } catch (const Error &error) { MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), diff --git a/src/libs/installer/component_p.cpp b/src/libs/installer/component_p.cpp index 560cd6544..ae4a149a5 100644 --- a/src/libs/installer/component_p.cpp +++ b/src/libs/installer/component_p.cpp @@ -87,6 +87,11 @@ ComponentPrivate::~ComponentPrivate() delete widget.data(); } +ScriptEngine *ComponentPrivate::scriptEngine() const +{ + return m_core->componentScriptEngine(); +} + // -- ComponentModelHelper ComponentModelHelper::ComponentModelHelper() diff --git a/src/libs/installer/component_p.h b/src/libs/installer/component_p.h index 1da9eee1a..821e891d7 100644 --- a/src/libs/installer/component_p.h +++ b/src/libs/installer/component_p.h @@ -53,6 +53,7 @@ namespace QInstaller { class Component; class PackageManagerCore; +class ScriptEngine; class ComponentPrivate { @@ -62,6 +63,8 @@ public: explicit ComponentPrivate(PackageManagerCore *core, Component *qq); ~ComponentPrivate(); + ScriptEngine *scriptEngine() const; + PackageManagerCore *m_core; Component *m_parentComponent; OperationList m_operations; diff --git a/src/libs/installer/consumeoutputoperation.cpp b/src/libs/installer/consumeoutputoperation.cpp index 04d7c9a8c..95d143b4a 100644 --- a/src/libs/installer/consumeoutputoperation.cpp +++ b/src/libs/installer/consumeoutputoperation.cpp @@ -104,17 +104,20 @@ bool ConsumeOutputOperation::performOperation() } QByteArray executableOutput; - QProcess process; const QStringList processArguments = arguments().mid(2); // in some cases it is not runable, because another process is blocking it(filewatcher ...) int waitCount = 0; - while (executableOutput.isEmpty() && waitCount < 60) { - + while (executableOutput.isEmpty() && waitCount < 3) { + QProcess process; process.start(executable.absoluteFilePath(), processArguments, QIODevice::ReadOnly); - if (process.waitForFinished(2000)) { + if (process.waitForFinished(10000)) { if (process.exitStatus() == QProcess::CrashExit) { + qWarning() << executable.absoluteFilePath() << processArguments + << "crashed with exit code" << process.exitCode() + << "standard output: " << process.readAllStandardOutput() + << "error output: " << process.readAllStandardError(); setError(UserDefinedError); setErrorString(tr("Running '%1' resulted in a crash.").arg( QDir::toNativeSeparators(executable.absoluteFilePath()))); diff --git a/src/libs/installer/createlocalrepositoryoperation.cpp b/src/libs/installer/createlocalrepositoryoperation.cpp index 0eb11b3aa..c8964796d 100644 --- a/src/libs/installer/createlocalrepositoryoperation.cpp +++ b/src/libs/installer/createlocalrepositoryoperation.cpp @@ -365,8 +365,7 @@ bool CreateLocalRepositoryOperation::undoOperation() if (createdDir == QDir::root() || !createdDir.exists()) return true; - QFile::remove(createdDir.path() + QLatin1String("/.DS_Store")); - QFile::remove(createdDir.path() + QLatin1String("/Thumbs.db")); + QInstaller::removeSystemGeneratedFiles(createdDir.path()); errno = 0; const bool result = QDir::root().rmdir(createdDir.path()); diff --git a/src/libs/installer/createshortcutoperation.cpp b/src/libs/installer/createshortcutoperation.cpp index 963f0aaf8..8c5917852 100644 --- a/src/libs/installer/createshortcutoperation.cpp +++ b/src/libs/installer/createshortcutoperation.cpp @@ -52,12 +52,7 @@ using namespace QInstaller; #ifdef Q_OS_WIN -#ifdef Q_CC_MINGW -# ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 -# endif -#endif -#include <windows.h> +#include <qt_windows.h> #include <shlobj.h> #ifndef PIDLIST_ABSOLUTE diff --git a/src/libs/installer/downloadarchivesjob.cpp b/src/libs/installer/downloadarchivesjob.cpp index 24fba689a..82f9b365c 100644 --- a/src/libs/installer/downloadarchivesjob.cpp +++ b/src/libs/installer/downloadarchivesjob.cpp @@ -182,7 +182,7 @@ void DownloadArchivesJob::fetchNextArchive() if (m_downloader != 0) m_downloader->deleteLater(); - m_downloader = setupDownloader(); + m_downloader = setupDownloader(QString(), m_core->value(QLatin1String("UrlQueryString"))); if (!m_downloader) { m_archivesToDownload.removeFirst(); QMetaObject::invokeMethod(this, "fetchNextArchive", Qt::QueuedConnection); @@ -292,13 +292,16 @@ void DownloadArchivesJob::finishWithError(const QString &error) emitFinishedWithError(QInstaller::DownloadError, msg.arg(error, m_downloader->url().toString())); } -KDUpdater::FileDownloader *DownloadArchivesJob::setupDownloader(const QString &suffix) +KDUpdater::FileDownloader *DownloadArchivesJob::setupDownloader(const QString &suffix, const QString &queryString) { KDUpdater::FileDownloader *downloader = 0; const QFileInfo fi = QFileInfo(m_archivesToDownload.first().first); const Component *const component = m_core->componentByName(QFileInfo(fi.path()).fileName()); if (component) { - const QUrl url(m_archivesToDownload.first().second + suffix); + QString fullQueryString; + if (!queryString.isEmpty()) + fullQueryString = QLatin1String("?") + queryString; + const QUrl url(m_archivesToDownload.first().second + suffix + fullQueryString); const QString &scheme = url.scheme(); downloader = FileDownloaderFactory::instance().create(scheme, this); diff --git a/src/libs/installer/downloadarchivesjob.h b/src/libs/installer/downloadarchivesjob.h index 9cf904fae..765d2c564 100644 --- a/src/libs/installer/downloadarchivesjob.h +++ b/src/libs/installer/downloadarchivesjob.h @@ -91,7 +91,7 @@ protected Q_SLOTS: void emitDownloadProgress(double progress); private: - KDUpdater::FileDownloader *setupDownloader(const QString &suffix = QString()); + KDUpdater::FileDownloader *setupDownloader(const QString &suffix = QString(), const QString &queryString = QString()); private: PackageManagerCore *m_core; diff --git a/src/libs/installer/environmentvariablesoperation.cpp b/src/libs/installer/environmentvariablesoperation.cpp index e66c6fc0d..4c423d94f 100644 --- a/src/libs/installer/environmentvariablesoperation.cpp +++ b/src/libs/installer/environmentvariablesoperation.cpp @@ -67,19 +67,15 @@ void EnvironmentVariableOperation::backup() } #ifdef Q_OS_WIN -static bool broadcastChange() { +static void broadcastEnvironmentChange() +{ // Use SendMessageTimeout to Broadcast a message to the whole system to update settings of all // running applications. This is needed to activate the changes done above without logout+login. - // Note that cmd.exe does not respond to any WM_SETTINGCHANGE messages... DWORD_PTR aResult = 0; - LRESULT sendresult = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, - 0, (LPARAM) "Environment", SMTO_BLOCK | SMTO_ABORTIFHUNG, 5000, &aResult); - if (sendresult == 0 || aResult != 0) { - qWarning("Failed to broadcast a WM_SETTINGCHANGE message\n"); - return false; - } - - return true; + LRESULT sendresult = SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, + 0, (LPARAM) L"Environment", SMTO_BLOCK | SMTO_ABORTIFHUNG, 5000, &aResult); + if (sendresult == 0 || aResult != 0) + qWarning("Failed to broadcast the WM_SETTINGCHANGE message."); } #endif @@ -161,16 +157,15 @@ bool EnvironmentVariableOperation::performOperation() Error err = NoError; - err = isSystemWide - ? writeSetting<QSettingsWrapper>(regPath, name, value, &errorString, &oldvalue) - : writeSetting<QSettingsWrapper>(regPath, name, value, &errorString, &oldvalue); + err = writeSetting<QSettingsWrapper>(regPath, name, value, &errorString, &oldvalue); if (err != NoError) { setError(err); setErrorString(errorString); return false; } - const bool bret = broadcastChange(); - Q_UNUSED(bret); // this is not critical, so fall-through + + broadcastEnvironmentChange(); + setValue(QLatin1String("oldvalue"), oldvalue); return true; } @@ -215,9 +210,7 @@ bool EnvironmentVariableOperation::undoOperation() QString errorString; - const Error err = isSystemWide - ? undoSetting<QSettingsWrapper>(regPath, name, value, oldvalue, &errorString) - : undoSetting<QSettingsWrapper>(regPath, name, value, oldvalue, &errorString); + const Error err = undoSetting<QSettingsWrapper>(regPath, name, value, oldvalue, &errorString); if (err != NoError) { setError(err); diff --git a/src/libs/installer/extractarchiveoperation.cpp b/src/libs/installer/extractarchiveoperation.cpp index 48c5db2c9..3897de4e4 100644 --- a/src/libs/installer/extractarchiveoperation.cpp +++ b/src/libs/installer/extractarchiveoperation.cpp @@ -75,13 +75,12 @@ bool ExtractArchiveOperation::performOperation() Receiver receiver; Callback callback; - // usually we have to connect it as queued connection but then some blocking work is in the main thread - connect(&callback, SIGNAL(progressChanged(QString)), this, SLOT(slotProgressChanged(QString)), - Qt::DirectConnection); + connect(&callback, SIGNAL(currentFileChanged(QString)), this, SLOT(fileFinished(QString))); + connect(&callback, SIGNAL(progressChanged(double)), this, SIGNAL(progressChanged(double))); if (PackageManagerCore *core = this->value(QLatin1String("installer")).value<PackageManagerCore*>()) { connect(core, SIGNAL(statusChanged(QInstaller::PackageManagerCore::Status)), &callback, - SLOT(statusChanged(QInstaller::PackageManagerCore::Status)), Qt::QueuedConnection); + SLOT(statusChanged(QInstaller::PackageManagerCore::Status))); } //Runnable is derived from QRunable which will be deleted by the ThreadPool -> no parent is needed @@ -125,8 +124,8 @@ bool ExtractArchiveOperation::undoOperation() const QStringList files = value(QLatin1String("files")).toStringList(); WorkerThread *const thread = new WorkerThread(this, files); - connect(thread, SIGNAL(outputTextChanged(QString)), this, SIGNAL(outputTextChanged(QString)), - Qt::QueuedConnection); + connect(thread, SIGNAL(currentFileChanged(QString)), this, SIGNAL(outputTextChanged(QString))); + connect(thread, SIGNAL(progressChanged(double)), this, SIGNAL(progressChanged(double))); QEventLoop loop; connect(thread, SIGNAL(finished()), &loop, SLOT(quit()), Qt::QueuedConnection); @@ -149,7 +148,7 @@ Operation *ExtractArchiveOperation::clone() const /*! This slot is direct connected to the caller so please don't call it from another thread in the same time. */ -void ExtractArchiveOperation::slotProgressChanged(const QString &filename) +void ExtractArchiveOperation::fileFinished(const QString &filename) { QStringList files = value(QLatin1String("files")).toStringList(); files.prepend(filename); diff --git a/src/libs/installer/extractarchiveoperation.h b/src/libs/installer/extractarchiveoperation.h index 818672fd3..53df81e73 100644 --- a/src/libs/installer/extractarchiveoperation.h +++ b/src/libs/installer/extractarchiveoperation.h @@ -64,9 +64,10 @@ public: Q_SIGNALS: void outputTextChanged(const QString &progress); + void progressChanged(double); private Q_SLOTS: - void slotProgressChanged(const QString &progress); + void fileFinished(const QString &progress); private: class Callback; diff --git a/src/libs/installer/extractarchiveoperation_p.h b/src/libs/installer/extractarchiveoperation_p.h index 4e0632830..c7284d9c2 100644 --- a/src/libs/installer/extractarchiveoperation_p.h +++ b/src/libs/installer/extractarchiveoperation_p.h @@ -71,9 +71,12 @@ public: ExtractArchiveOperation *const op = m_op;//dynamic_cast< ExtractArchiveOperation* >(parent()); Q_ASSERT(op != 0); + int removedCounter = 0; foreach (const QString &file, m_files) { + removedCounter++; const QFileInfo fi(file); - emit outputTextChanged(file); + emit currentFileChanged(file); + emit progressChanged(double(removedCounter) / m_files.count()); if (fi.isFile() || fi.isSymLink()) { op->deleteFileNowOrLater(fi.absoluteFilePath()); } else if (fi.isDir()) { @@ -85,7 +88,8 @@ public: } Q_SIGNALS: - void outputTextChanged(const QString &filename); + void currentFileChanged(const QString &filename); + void progressChanged(double); private: QStringList m_files; @@ -105,7 +109,8 @@ public: Callback() : state(S_OK), createBackups(true) {} Q_SIGNALS: - void progressChanged(const QString &filename); + void currentFileChanged(const QString &filename); + void progressChanged(double progress); public Q_SLOTS: void statusChanged(QInstaller::PackageManagerCore::Status status) @@ -130,7 +135,7 @@ public Q_SLOTS: protected: void setCurrentFile(const QString &filename) { - emit progressChanged(QDir::toNativeSeparators(filename)); + emit currentFileChanged(QDir::toNativeSeparators(filename)); } static QString generateBackupName(const QString &fn) @@ -161,8 +166,9 @@ protected: return true; } - HRESULT setCompleted(quint64 /*completed*/, quint64 /*total*/) + HRESULT setCompleted(quint64 completed, quint64 total) { + emit progressChanged(double(completed) / total); return state; } }; diff --git a/src/libs/installer/fileutils.cpp b/src/libs/installer/fileutils.cpp index 010c30621..fe10277ea 100644 --- a/src/libs/installer/fileutils.cpp +++ b/src/libs/installer/fileutils.cpp @@ -289,8 +289,7 @@ void QInstaller::removeDirectory(const QString &path, bool ignoreErrors) QDirIterator it(path, QDir::NoDotAndDotDot | QDir::Dirs | QDir::NoSymLinks | QDir::Hidden, QDirIterator::Subdirectories); while (it.hasNext()) { - it.next(); - dirs.prepend(it.filePath()); + dirs.prepend(it.next()); removeFiles(dirs.at(0), ignoreErrors); } @@ -461,27 +460,68 @@ QString QInstaller::generateTemporaryFileName(const QString &templ) return f.fileName(); } -QString QInstaller::createTemporaryDirectory(const QString &templ) +static char *installer_mkdtemp(char *templateName) { - const QString t = QDir::tempPath() + QLatin1String("/") + templ + QLatin1String("XXXXXX"); - QTemporaryFile f(t); - if (!f.open()) - throw Error(QObject::tr("Could not create temporary folder for template %1: %2").arg(t, f.errorString())); - const QString path = f.fileName() + QLatin1String("meta"); - qDebug() << "\nCreating meta data directory at" << path; + QDir newDir; +#if defined(Q_OS_QNX ) || defined(Q_OS_WIN) || defined(Q_OS_ANDROID) + static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - QInstaller::mkpath(path); + const size_t length = strlen(templateName); + + char *XXXXXX = templateName + length - 6; + + if ((length < 6u) || strncmp(XXXXXX, "XXXXXX", 6)) + return 0; + + for (int i = 0; i < 256; ++i) { + /* Fill in the random bits. */ + int v = qrand(); + XXXXXX[0] = letters[v % 62]; + v /= 62; + XXXXXX[1] = letters[v % 62]; + v = qrand(); + XXXXXX[2] = letters[v % 62]; + v /= 62; + XXXXXX[3] = letters[v % 62]; + v = qrand(); + XXXXXX[4] = letters[v % 62]; + v /= 62; + XXXXXX[5] = letters[v % 62]; + + QString templateNameStr = QFile::decodeName(templateName); + + newDir = QDir(templateNameStr); + if (newDir.mkpath(templateNameStr)) + return templateName; + } + return 0; +#else + return mkdtemp(templateName); +#endif +} + +QString QInstaller::createTemporaryDirectory(const QString &templateName) +{ + // TODO: use QTemporaryDir if we switched to Qt5 + QString path = QDir::tempPath() + QLatin1String("/") + templateName + QLatin1String("XXXXXX"); + path = QFile::decodeName(installer_mkdtemp(QFile::encodeName(path).data())); + if (path.isEmpty()) { + QTemporaryFile f(path); + if (!f.open()) { + throw Error(QObject::tr("Could not create temporary directory at %1: %2" + ).arg(QFileInfo(f).absolutePath(), f.errorString())); + } else { + throw Error(QObject::tr("Could not create temporary directory at %1: unknown error" + ).arg(QFileInfo(f).absolutePath())); + } + } + + qDebug() << "Temporary directory created:" << path; return path; } #ifdef Q_OS_WIN -# ifdef Q_CC_MINGW -# ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 -# endif -# endif -#include <windows.h> - +#include <qt_windows.h> QString QInstaller::getShortPathName(const QString &name) { diff --git a/src/libs/installer/fileutils.h b/src/libs/installer/fileutils.h index 9bbcec72a..c22aa36b6 100644 --- a/src/libs/installer/fileutils.h +++ b/src/libs/installer/fileutils.h @@ -108,7 +108,7 @@ private: Creates a temporary directory @throws QInstaller::Error if creating the temporary directory fails */ - QString INSTALLER_EXPORT createTemporaryDirectory(const QString &templ=QString()); + QString INSTALLER_EXPORT createTemporaryDirectory(const QString &templateName = QString()); QString INSTALLER_EXPORT generateTemporaryFileName(const QString &templ=QString()); diff --git a/src/libs/installer/getrepositoriesmetainfojob.cpp b/src/libs/installer/getrepositoriesmetainfojob.cpp index c4564e781..cde872064 100644 --- a/src/libs/installer/getrepositoriesmetainfojob.cpp +++ b/src/libs/installer/getrepositoriesmetainfojob.cpp @@ -121,7 +121,7 @@ void GetRepositoriesMetaInfoJob::doStart() { if ((m_core->isInstaller() && !m_core->isOfflineOnly()) || (m_core->isUpdater() || m_core->isPackageManager())) { - const ProductKeyCheck *const productKeyCheck = ProductKeyCheck::instance(m_core); + const ProductKeyCheck *const productKeyCheck = ProductKeyCheck::instance(); foreach (const Repository &repo, m_core->settings().repositories()) { if (repo.isEnabled() && productKeyCheck->isValidRepository(repo)) m_repositories += repo; diff --git a/src/libs/installer/getrepositorymetainfojob.cpp b/src/libs/installer/getrepositorymetainfojob.cpp index 1c8d07525..14bcf26f2 100644 --- a/src/libs/installer/getrepositorymetainfojob.cpp +++ b/src/libs/installer/getrepositorymetainfojob.cpp @@ -49,6 +49,8 @@ #include "kdupdaterfiledownloader.h" #include "kdupdaterfiledownloaderfactory.h" +#include "productkeycheck.h" + #include <QTimer> @@ -197,14 +199,14 @@ void GetRepositoryMetaInfoJob::startUpdatesXmlDownload() } if (!url.isValid()) { - finished(QInstaller::InvalidUrl, tr("Invalid repository URL: %1").arg(url.toString())); + finished(QInstaller::InvalidUrl, tr("Invalid repository URL: %1").arg(m_repository.displayname())); return; } m_downloader = FileDownloaderFactory::instance().create(url.scheme(), this); if (!m_downloader) { finished(QInstaller::InvalidUrl, tr("URL scheme not supported: %1 (%2)").arg(url.scheme(), - url.toString())); + m_repository.displayname())); return; } @@ -244,20 +246,7 @@ void GetRepositoryMetaInfoJob::updatesXmlDownloadFinished() Q_ASSERT(!fn.isEmpty()); Q_ASSERT(QFile::exists(fn)); - try { - m_temporaryDirectory = createTemporaryDirectory(QLatin1String("remoterepo")); - m_tempDirDeleter.add(m_temporaryDirectory); - } catch (const QInstaller::Error& e) { - finished(QInstaller::ExtractionError, e.message()); - return; - } - QFile updatesFile(fn); - if (!updatesFile.rename(m_temporaryDirectory + QLatin1String("/Updates.xml"))) { - finished(QInstaller::DownloadError, tr("Could not move Updates.xml to target location. Error: %1") - .arg(updatesFile.errorString())); - return; - } if (!updatesFile.open(QIODevice::ReadOnly)) { finished(QInstaller::DownloadError, tr("Could not open Updates.xml for reading. Error: %1") @@ -272,7 +261,7 @@ void GetRepositoryMetaInfoJob::updatesXmlDownloadFinished() if (!success) { const QString msg = tr("Could not fetch a valid version of Updates.xml from repository: %1. " - "Error: %2").arg(m_repository.url().toString(), err); + "Error: %2").arg(m_repository.displayname(), err); const QMessageBox::StandardButton b = MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), @@ -302,15 +291,16 @@ void GetRepositoryMetaInfoJob::updatesXmlDownloadFinished() repository.setUsername(el.attribute(QLatin1String("username"))); repository.setPassword(el.attribute(QLatin1String("password"))); repository.setDisplayName(el.attribute(QLatin1String("displayname"))); - repositoryUpdates.insertMulti(action, qMakePair(repository, Repository())); - - qDebug() << "Repository to add:" << repository.url().toString(); + if (ProductKeyCheck::instance()->isValidRepository(repository)) { + repositoryUpdates.insertMulti(action, qMakePair(repository, Repository())); + qDebug() << "Repository to add:" << repository.displayname(); + } } else if (action == QLatin1String("remove")) { // remove possible default repositories using the given server url Repository repository(el.attribute(QLatin1String("url")), true); repositoryUpdates.insertMulti(action, qMakePair(repository, Repository())); - qDebug() << "Repository to remove:" << repository.url().toString(); + qDebug() << "Repository to remove:" << repository.displayname(); } else if (action == QLatin1String("replace")) { // replace possible default repositories using the given server url Repository oldRepository(el.attribute(QLatin1String("oldUrl")), true); @@ -319,19 +309,42 @@ void GetRepositoryMetaInfoJob::updatesXmlDownloadFinished() newRepository.setPassword(el.attribute(QLatin1String("password"))); newRepository.setDisplayName(el.attribute(QLatin1String("displayname"))); - // store the new repository and the one old it replaces - repositoryUpdates.insertMulti(action, qMakePair(newRepository, oldRepository)); - qDebug() << "Replace repository:" << oldRepository.url().toString() << "with:" - << newRepository.url().toString(); + 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:" + << newRepository.displayname(); + } } else { qDebug() << "Invalid additional repositories action set in Updates.xml fetched from:" - << m_repository.url().toString() << "Line:" << el.lineNumber(); + << m_repository.displayname() << "Line:" << el.lineNumber(); } } } if (!repositoryUpdates.isEmpty()) { - if (m_core->settings().updateDefaultRepositories(repositoryUpdates) == Settings::UpdatesApplied) { + const QSet<Repository> temporaries = m_core->settings().temporaryRepositories(); + // in case the temp repository introduced something new, we only want that temporary + if (temporaries.contains(m_repository)) { + + QSet<Repository> childTempRepositories; + typedef QPair<Repository, Repository> RepositoryPair; + + QList<RepositoryPair> values = repositoryUpdates.values(QLatin1String("add")); + foreach (const RepositoryPair &value, values) + childTempRepositories.insert(value.first); + + values = repositoryUpdates.values(QLatin1String("replace")); + foreach (const RepositoryPair &value, values) + childTempRepositories.insert(value.first); + + QSet<Repository> newChildTempRepositories = childTempRepositories.subtract(temporaries); + if (newChildTempRepositories.count() > 0) { + m_core->settings().addTemporaryRepositories(newChildTempRepositories, true); + finished(QInstaller::RepositoryUpdatesReceived, tr("Repository updates received.")); + return; + } + } else if (m_core->settings().updateDefaultRepositories(repositoryUpdates) == Settings::UpdatesApplied) { if (m_core->isUpdater() || m_core->isPackageManager()) m_core->writeMaintenanceConfigFiles(); finished(QInstaller::RepositoryUpdatesReceived, tr("Repository updates received.")); @@ -358,6 +371,19 @@ void GetRepositoryMetaInfoJob::updatesXmlDownloadFinished() } } + try { + m_temporaryDirectory = createTemporaryDirectory(QLatin1String("remoterepo-")); + m_tempDirDeleter.add(m_temporaryDirectory); + } catch (const QInstaller::Error& e) { + finished(QInstaller::ExtractionError, e.message()); + return; + } + if (!updatesFile.rename(m_temporaryDirectory + QLatin1String("/Updates.xml"))) { + finished(QInstaller::DownloadError, tr("Could not move Updates.xml to target location. Error: %1") + .arg(updatesFile.errorString())); + return; + } + setTotalAmount(m_packageNames.count() + 1); setProcessedAmount(1); emit infoMessage(this, tr("Finished updating component meta information.")); @@ -427,7 +453,7 @@ void GetRepositoryMetaInfoJob::fetchNextMetaInfo() if (!m_downloader) { m_currentPackageName.clear(); m_currentPackageVersion.clear(); - qWarning() << "Scheme not supported:" << url.toString(); + qWarning() << "Scheme not supported:" << m_repository.displayname(); QMetaObject::invokeMethod(this, "fetchNextMetaInfo", Qt::QueuedConnection); return; } diff --git a/src/libs/installer/init.cpp b/src/libs/installer/init.cpp index 9ef72b4dd..12891f0e2 100644 --- a/src/libs/installer/init.cpp +++ b/src/libs/installer/init.cpp @@ -59,6 +59,7 @@ #include "minimumprogressoperation.h" #include "licenseoperation.h" #include "applyproductkeyoperation.h" +#include "settingsoperation.h" // QtSDK specific #include "qtpatchoperation.h" @@ -139,9 +140,12 @@ static void initResources() { Q_INIT_RESOURCE(patch_file_lists); Q_INIT_RESOURCE(installer); + // Qt5 or better qmake generates that automatically, so this is only needed on Qt4 # if QT_VERSION < 0x050000 Q_IMPORT_PLUGIN(qico) Q_UNUSED(qt_plugin_instance_qico()); + Q_IMPORT_PLUGIN(qtaccessiblewidgets) + Q_UNUSED(qt_plugin_instance_qtaccessiblewidgets()); # endif } #endif @@ -237,6 +241,7 @@ void QInstaller::init() factory.registerUpdateOperation<LicenseOperation>(QLatin1String("License")); factory.registerUpdateOperation<ApplyProductKeyOperation>(QLatin1String("ApplyProductKey")); factory.registerUpdateOperation<ConsumeOutputOperation>(QLatin1String("ConsumeOutput")); + factory.registerUpdateOperation<SettingsOperation>(QLatin1String("Settings")); // QtSDK specific factory.registerUpdateOperation<SetQtCreatorValueOperation>(QLatin1String("SetQtCreatorValue")); diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro index a1631c4a3..149287428 100644 --- a/src/libs/installer/installer.pro +++ b/src/libs/installer/installer.pro @@ -101,7 +101,10 @@ HEADERS += packagemanagercore.h \ packagemanagercoredata.h \ applyproductkeyoperation.h \ globals.h \ - graph.h + graph.h \ + settingsoperation.h \ + testrepository.h \ + packagemanagerpagefactory.h SOURCES += packagemanagercore.cpp \ packagemanagercore_p.cpp \ @@ -163,7 +166,10 @@ HEADERS += packagemanagercore.h \ createlinkoperation.cpp \ packagemanagercoredata.cpp \ applyproductkeyoperation.cpp \ - globals.cpp + globals.cpp \ + settingsoperation.cpp \ + testrepository.cpp \ + packagemanagerpagefactory.cpp RESOURCES += resources/patch_file_lists.qrc \ resources/installer.qrc diff --git a/src/libs/installer/link.cpp b/src/libs/installer/link.cpp index f8b872f33..d7588d077 100644 --- a/src/libs/installer/link.cpp +++ b/src/libs/installer/link.cpp @@ -50,13 +50,7 @@ #endif #ifdef Q_OS_WIN -#ifdef Q_CC_MINGW -# ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 -# endif -#endif - -#include <windows.h> +#include <qt_windows.h> #include <winioctl.h> #ifndef Q_CC_MINGW diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp index c617dd239..09e1a5094 100644 --- a/src/libs/installer/packagemanagercore.cpp +++ b/src/libs/installer/packagemanagercore.cpp @@ -421,13 +421,26 @@ void PackageManagerCore::writeMaintenanceConfigFiles() void PackageManagerCore::reset(const QHash<QString, QString> ¶ms) { d->m_completeUninstall = false; - d->m_forceRestart = false; + d->m_needsHardRestart = false; d->m_status = PackageManagerCore::Unfinished; d->m_installerBaseBinaryUnreplaced.clear(); d->initialize(params); } +void PackageManagerCore::setGuiObject(QObject *gui) +{ + if (gui == d->m_guiObject) + return; + d->m_guiObject = gui; + emit guiObjectChanged(gui); +} + +QObject *PackageManagerCore::guiObject() const +{ + return d->m_guiObject; +} + /*! \qmlmethod void QInstaller::setCompleteUninstallation(bool complete) @@ -532,11 +545,12 @@ quint64 PackageManagerCore::requiredDiskSpace() const */ quint64 PackageManagerCore::requiredTemporaryDiskSpace() const { - quint64 result = 0; + if (isOfflineOnly()) + return 0; + quint64 result = 0; foreach (QInstaller::Component *component, orderedComponentsToInstall()) result += size(component, scCompressedSize); - return result; } @@ -596,11 +610,17 @@ int PackageManagerCore::downloadNeededArchives(double partProgressSize) If a component marked as important was installed during update process true is returned. */ -bool PackageManagerCore::needsRestart() const +bool PackageManagerCore::needsHardRestart() const { - return d->m_forceRestart; + return d->m_needsHardRestart; } +void PackageManagerCore::setNeedsHardRestart(bool needsHardRestart) +{ + d->m_needsHardRestart = needsHardRestart; +} + + void PackageManagerCore::rollBackInstallation() { emit titleMessageChanged(tr("Cancelling the Installer")); @@ -629,6 +649,19 @@ void PackageManagerCore::rollBackInstallation() const bool becameAdmin = !d->m_FSEngineClientHandler->isActive() && operation->value(QLatin1String("admin")).toBool() && gainAdminRights(); + if (operation->hasValue(QLatin1String("uninstall-only"))) { + // We know the mkdir operation which is creating the target path. If we do a + // full uninstall, prevent a forced remove of the full install path including the + // target , instead try to remove the target only and only if it is empty, + // otherwise fail silently. Note: we will ever experience this only -if- + // RemoveTargetDir is set, otherwise the operation does not exist at all. + const bool isMkDir = (operation->name() == QLatin1String("Mkdir")); + const bool removeTargetDir = QVariant(value(scRemoveTargetDir)).toBool(); + const bool uninstallOnly = operation->value(QLatin1String("uninstall-only")).toBool(); + if (isMkDir && uninstallOnly && removeTargetDir) + operation->setValue(QLatin1String("forceremoval"), false); + } + PackageManagerCorePrivate::performOperationThreaded(operation, PackageManagerCorePrivate::Undo); const QString componentName = operation->value(QLatin1String("component")).toString(); @@ -867,8 +900,8 @@ bool PackageManagerCore::fetchRemotePackagesTree() return false; } - if (!ProductKeyCheck::instance(this)->hasValidKey()) { - d->setStatus(Failure, ProductKeyCheck::instance(this)->lastErrorString()); + if (!ProductKeyCheck::instance()->hasValidKey()) { + d->setStatus(Failure, ProductKeyCheck::instance()->lastErrorString()); return false; } @@ -1084,9 +1117,14 @@ void PackageManagerCore::setTestChecksum(bool test) d->m_testChecksum = test; } -ScriptEngine *PackageManagerCore::scriptEngine() +ScriptEngine *PackageManagerCore::componentScriptEngine() const +{ + return d->componentScriptEngine(); +} + +ScriptEngine *PackageManagerCore::controlScriptEngine() const { - return d->scriptEngine(); + return d->controlScriptEngine(); } /*! diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h index 20a3293fa..392e5a018 100644 --- a/src/libs/installer/packagemanagercore.h +++ b/src/libs/installer/packagemanagercore.h @@ -125,6 +125,9 @@ public: bool run(); void reset(const QHash<QString, QString> ¶ms); + void setGuiObject(QObject *gui); + QObject *guiObject() const; + Q_INVOKABLE void setDependsOnLocalInstallerBinary(); Q_INVOKABLE bool localInstallerBinaryUsed(); @@ -177,7 +180,8 @@ public: Q_INVOKABLE bool fileExists(const QString &filePath) const; public: - ScriptEngine *scriptEngine(); + ScriptEngine *componentScriptEngine() const; + ScriptEngine *controlScriptEngine() const; // component handling @@ -248,7 +252,8 @@ public: int downloadNeededArchives(double partProgressSize); - bool needsRestart() const; + bool needsHardRestart() const; + void setNeedsHardRestart(bool needsHardRestart = true); bool finishedWithSuccess() const; public Q_SLOTS: @@ -300,6 +305,8 @@ Q_SIGNALS: void setAutomatedPageSwitchEnabled(bool request); void coreNetworkSettingsChanged(); + void guiObjectChanged(QObject *gui); + private: struct Data { Package *package; diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp index cf34cc2e8..43df0cdf8 100644 --- a/src/libs/installer/packagemanagercore_p.cpp +++ b/src/libs/installer/packagemanagercore_p.cpp @@ -78,7 +78,7 @@ #include <errno.h> #ifdef Q_OS_WIN -#include <windows.h> +#include <qt_windows.h> #endif namespace QInstaller { @@ -212,10 +212,12 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core) , m_repoFetched(false) , m_updateSourcesAdded(false) , m_componentsToInstallCalculated(false) - , m_scriptEngine(0) + , m_componentScriptEngine(0) + , m_controlScriptEngine(0) , m_proxyFactory(0) , m_defaultModel(0) , m_updaterModel(0) + , m_guiObject(0) { } @@ -225,7 +227,7 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q , m_updaterApplication(new DummyConfigurationInterface) , m_FSEngineClientHandler(initFSEngineClientHandler()) , m_status(PackageManagerCore::Unfinished) - , m_forceRestart(false) + , m_needsHardRestart(false) , m_testChecksum(false) , m_launchedAsRoot(AdminAuthorization::hasAdminRights()) , m_completeUninstall(false) @@ -239,10 +241,12 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q , m_updateSourcesAdded(false) , m_magicBinaryMarker(magicInstallerMaker) , m_componentsToInstallCalculated(false) - , m_scriptEngine(0) + , m_componentScriptEngine(0) + , m_controlScriptEngine(0) , m_proxyFactory(0) , m_defaultModel(0) , m_updaterModel(0) + , m_guiObject(0) { connect(this, SIGNAL(installationStarted()), m_core, SIGNAL(installationStarted())); connect(this, SIGNAL(installationFinished()), m_core, SIGNAL(installationFinished())); @@ -265,11 +269,13 @@ PackageManagerCorePrivate::~PackageManagerCorePrivate() m_FSEngineClientHandler->setActive(false); delete m_updateFinder; - delete m_scriptEngine; delete m_proxyFactory; delete m_defaultModel; delete m_updaterModel; + + // at the moment the tabcontroller deletes the m_gui, this needs to be changed in the future + // delete m_gui; } /*! @@ -392,11 +398,30 @@ bool PackageManagerCorePrivate::buildComponentTree(QHash<QString, Component*> &c return true; } -ScriptEngine *PackageManagerCorePrivate::scriptEngine() +void PackageManagerCorePrivate::cleanUpComponentEnvironment() +{ + // clean up already downloaded data, don't reset registered archives in offline installer case + if (QInstallerCreator::BinaryFormatEngineHandler::instance() && !m_core->isInstaller()) + QInstallerCreator::BinaryFormatEngineHandler::instance()->resetRegisteredArchives(); + + // there could be still some references to already deleted components, + // so we need to remove the current component script engine + delete m_componentScriptEngine; + m_componentScriptEngine = 0; +} + +ScriptEngine *PackageManagerCorePrivate::componentScriptEngine() const { - if (!m_scriptEngine) - m_scriptEngine = new ScriptEngine(m_core); - return m_scriptEngine; + if (!m_componentScriptEngine) + m_componentScriptEngine = new ScriptEngine(m_core); + return m_componentScriptEngine; +} + +ScriptEngine *PackageManagerCorePrivate::controlScriptEngine() const +{ + if (!m_controlScriptEngine) + m_controlScriptEngine = new ScriptEngine(m_core); + return m_controlScriptEngine; } void PackageManagerCorePrivate::clearAllComponentLists() @@ -411,6 +436,8 @@ void PackageManagerCorePrivate::clearAllComponentLists() delete list.at(i).second; m_componentsToReplaceAllMode.clear(); m_componentsToInstallCalculated = false; + + cleanUpComponentEnvironment(); } void PackageManagerCorePrivate::clearUpdaterComponentLists() @@ -435,6 +462,8 @@ void PackageManagerCorePrivate::clearUpdaterComponentLists() m_componentsToReplaceUpdaterMode.clear(); m_componentsToInstallCalculated = false; + + cleanUpComponentEnvironment(); } QList<Component *> &PackageManagerCorePrivate::replacementDependencyComponents() @@ -572,16 +601,6 @@ QString PackageManagerCorePrivate::installReason(Component *component) void PackageManagerCorePrivate::initialize(const QHash<QString, QString> ¶ms) { - if (!ProductKeyCheck::instance(m_core)->hasValidKey()) { - if (m_core->isInstaller()) { - setStatus(PackageManagerCore::Failure, ProductKeyCheck::instance(m_core)->lastErrorString()); - } else { - MessageBoxHandler::warning(MessageBoxHandler::currentBestSuitParent(), - QLatin1String("ProductKeyCheckError"), ProductKeyCheck::instance(m_core)->lastErrorString(), - ProductKeyCheck::instance(m_core)->maintainanceToolDetailErrorNotice(), QMessageBox::Ok); - } - } - m_coreCheckedHash.clear(); m_data = PackageManagerCoreData(params); m_componentsToInstallCalculated = false; @@ -1094,7 +1113,25 @@ void PackageManagerCorePrivate::writeUninstallerBinaryData(QIODevice *output, QF const qint64 dataBlockStart = output->pos(); QVector<Range<qint64> >resourceSegments; - foreach (const Range<qint64> &segment, layout.metadataResourceSegments) { + QVector<Range<qint64> >existingResourceSegments = layout.metadataResourceSegments; + + const QString newDefaultResource = m_core->value(QString::fromLatin1("DefaultResourceReplacement")); + if (!newDefaultResource.isEmpty()) { + QFile file(newDefaultResource); + if (file.open(QIODevice::ReadOnly)) { + resourceSegments.append(Range<qint64>::fromStartAndLength(output->pos(), file.size())); + appendData(output, &file, file.size()); + existingResourceSegments.remove(0); + + 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); + } + } + + foreach (const Range<qint64> &segment, existingResourceSegments) { input->seek(segment.start()); resourceSegments.append(Range<qint64>::fromStartAndLength(output->pos(), segment.length())); appendData(output, input, segment.length()); @@ -1156,8 +1193,6 @@ void PackageManagerCorePrivate::writeUninstaller(OperationList performedOperatio performedOperations.append(takeOwnedOperation(op)); } - writeMaintenanceConfigFiles(); - #ifdef Q_OS_MAC // if it is a bundle, we need some stuff in it... const QString sourceAppDirPath = QCoreApplication::applicationDirPath(); @@ -1264,7 +1299,7 @@ void PackageManagerCorePrivate::writeUninstaller(OperationList performedOperatio bool newBinaryWritten = false; bool replacementExists = false; - const QString installerBaseBinary = m_core->replaceVariables(m_installerBaseBinaryUnreplaced); + const QString installerBaseBinary = replaceVariables(m_installerBaseBinaryUnreplaced); if (!installerBaseBinary.isEmpty() && QFileInfo(installerBaseBinary).exists()) { qDebug() << "Got a replacement installer base binary:" << installerBaseBinary; @@ -1272,8 +1307,8 @@ void PackageManagerCorePrivate::writeUninstaller(OperationList performedOperatio try { openForRead(&replacementBinary, replacementBinary.fileName()); writeUninstallerBinary(&replacementBinary, replacementBinary.size(), true); + qDebug() << "Wrote the binary with the new replacement."; - m_forceRestart = true; newBinaryWritten = true; replacementExists = true; } catch (const Error &error) { @@ -1283,10 +1318,17 @@ void PackageManagerCorePrivate::writeUninstaller(OperationList performedOperatio 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 " + qDebug() << QString::fromLatin1("Could not remove installer base binary '%1' after updating " "the uninstaller: %2").arg(installerBaseBinary, replacementBinary.errorString()); + } else { + qDebug() << QString::fromLatin1("Removed installer base binary '%1' after updating the " + "uninstaller/ maintenance tool.").arg(installerBaseBinary); } m_installerBaseBinaryUnreplaced.clear(); + } else if (!installerBaseBinary.isEmpty() && !QFileInfo(installerBaseBinary).exists()) { + qWarning() << QString::fromLatin1("The current uninstaller/ 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); } QFile input; @@ -1330,9 +1372,7 @@ void PackageManagerCorePrivate::writeUninstaller(OperationList performedOperatio #endif } - performedOperations = sortOperationsBasedOnComponentDependencies( - performedOperations); - + performedOperations = sortOperationsBasedOnComponentDependencies(performedOperations); m_core->setValue(QLatin1String("installedOperationAreSorted"), QLatin1String("true")); try { @@ -1363,10 +1403,11 @@ void PackageManagerCorePrivate::writeUninstaller(OperationList performedOperatio appendInt64(&file, MagicCookie); } input.close(); + writeMaintenanceConfigFiles(); deferredRename(dataFile + QLatin1String(".new"), dataFile, false); if (newBinaryWritten) { - const bool restart = replacementExists && isUpdater() && (!statusCanceledOrFailed()); + const bool restart = replacementExists && isUpdater() && (!statusCanceledOrFailed()) && m_needsHardRestart; deferredRename(uninstallerName() + QLatin1String(".new"), uninstallerName(), restart); qDebug() << "Maintenance tool restart:" << (restart ? "true." : "false."); } @@ -1888,7 +1929,7 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr throw Error(operation->errorString()); if (component->value(scEssential, scFalse) == scTrue) - m_forceRestart = true; + m_needsHardRestart = true; } registerPathesForUninstallation(component->pathesForUninstallation(), component->name()); @@ -2389,9 +2430,11 @@ OperationList PackageManagerCorePrivate::sortOperationsBasedOnComponentDependenc // create the complete component graph Graph<QString> componentGraph; + const QRegExp dash(QLatin1String("-.*")); foreach (const Component* componentNode, m_core->availableComponents()) { componentGraph.addNode(componentNode->name()); - componentGraph.addEdges(componentNode->name(), componentNode->dependencies()); + const QStringList dependencies = componentNode->dependencies().replaceInStrings(dash,QString()); + componentGraph.addEdges(componentNode->name(), dependencies); } foreach (const QString &componentName, componentGraph.sort()) diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h index d5bdc78fd..a6b9d4438 100644 --- a/src/libs/installer/packagemanagercore_p.h +++ b/src/libs/installer/packagemanagercore_p.h @@ -135,7 +135,10 @@ public: bool buildComponentTree(QHash<QString, Component*> &components, bool loadScript); - ScriptEngine *scriptEngine(); + void cleanUpComponentEnvironment(); + ScriptEngine *componentScriptEngine() const; + ScriptEngine *controlScriptEngine() const; + void clearAllComponentLists(); void clearUpdaterComponentLists(); QList<Component*> &replacementDependencyComponents(); @@ -205,7 +208,7 @@ public: int m_status; QString m_error; - bool m_forceRestart; + bool m_needsHardRestart; bool m_testChecksum; bool m_launchedAsRoot; bool m_completeUninstall; @@ -263,7 +266,8 @@ private: qint64 m_magicBinaryMarker; bool m_componentsToInstallCalculated; - ScriptEngine *m_scriptEngine; + mutable ScriptEngine *m_componentScriptEngine; + mutable ScriptEngine *m_controlScriptEngine; // < name (component to replace), < replacement component, component to replace > > QHash<QString, QPair<Component*, Component*> > m_componentsToReplaceAllMode; QHash<QString, QPair<Component*, Component*> > m_componentsToReplaceUpdaterMode; @@ -285,6 +289,8 @@ private: ComponentModel *m_defaultModel; ComponentModel *m_updaterModel; + QObject *m_guiObject; + private: // remove once we deprecate isSelected, setSelected etc... void resetComponentsToUserCheckedState(); diff --git a/src/libs/installer/packagemanagercoredata.cpp b/src/libs/installer/packagemanagercoredata.cpp index 2294a8086..16fc6dc00 100644 --- a/src/libs/installer/packagemanagercoredata.cpp +++ b/src/libs/installer/packagemanagercoredata.cpp @@ -44,8 +44,14 @@ #include "fileutils.h" #include "qsettingswrapper.h" +#include <QDesktopServices> #include <QDir> +#ifdef Q_OS_WIN +# include <windows.h> +# include <shlobj.h> +#endif + namespace QInstaller { @@ -61,6 +67,20 @@ PackageManagerCoreData::PackageManagerCoreData(const QHash<QString, QString> &va m_variables.insert(QLatin1String("HomeDir"), QDir::homePath()); m_variables.insert(scTargetConfigurationFile, QLatin1String("components.xml")); + 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_MAC) +# if QT_VERSION < 0x050000 + dir = QDesktopServices::storageLocation(QDesktopServices::ApplicationsLocation); +# else + dir = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).value(0); +# endif +#endif + m_variables.insert(QLatin1String("ApplicationsDir"), dir); + #ifdef Q_OS_WIN m_variables.insert(QLatin1String("os"), QLatin1String("win")); #elif defined(Q_OS_MAC) @@ -138,7 +158,7 @@ QVariant PackageManagerCoreData::value(const QString &key, const QVariant &_defa if (key == scTargetDir) { QString dir = m_variables.value(key); if (dir.isEmpty()) - dir = m_settings.value(key, _default).toString(); + dir = replaceVariables(m_settings.value(key, _default).toString()); #ifdef Q_OS_WIN return QInstaller::normalizePathName(dir); #else diff --git a/src/libs/installer/packagemanagergui.cpp b/src/libs/installer/packagemanagergui.cpp index c70d00f13..9d6414adc 100644 --- a/src/libs/installer/packagemanagergui.cpp +++ b/src/libs/installer/packagemanagergui.cpp @@ -128,7 +128,7 @@ public: setPixmap(QWizard::BannerPixmap, QPixmap()); setLayout(new QVBoxLayout); - setColoredSubTitle(QString()); + setColoredSubTitle(QLatin1String(" ")); setColoredTitle(widget->windowTitle()); m_widget->setProperty("complete", true); m_widget->setProperty("final", false); @@ -252,7 +252,7 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent) connect(m_core, SIGNAL(installationFinished()), this, SLOT(showFinishedPage()), Qt::QueuedConnection); connect(m_core, SIGNAL(uninstallationFinished()), this, SLOT(showFinishedPage()), Qt::QueuedConnection); - connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(slotCurrentPageChanged(int))); + connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(executeControlScript(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())); @@ -283,7 +283,7 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent) for (int i = QWizard::BackButton; i < QWizard::CustomButton1; ++i) d->m_defaultButtonText.insert(i, buttonText(QWizard::WizardButton(i))); - m_core->scriptEngine()->setGuiQObject(this); + m_core->setGuiObject(this); } PackageManagerGui::~PackageManagerGui() @@ -318,8 +318,8 @@ void PackageManagerGui::clickButton(int wb, int delay) { // transform the FinishButton to CancelButton, because of the needed misuse of the // CancelButton as a FinishButton to have some more control of closing the wizard - if (!m_core->isInstaller() && currentId() == PackageManagerCore::InstallationFinished && - wb == QWizard::FinishButton) { + if ((m_core->isUpdater() || m_core->isPackageManager()) && currentId() == + PackageManagerCore::InstallationFinished && wb == QWizard::FinishButton) { wb = QWizard::CancelButton; } if (QAbstractButton *b = button(static_cast<QWizard::WizardButton>(wb) )) @@ -332,8 +332,8 @@ bool PackageManagerGui::isButtonEnabled(int wb) { // transform the FinishButton to CancelButton, because of the needed misuse of the // CancelButton as a FinishButton to have some more control of closing the wizard - if (!m_core->isInstaller() && currentId() == PackageManagerCore::InstallationFinished && - wb == QWizard::FinishButton) { + if ((m_core->isUpdater() || m_core->isPackageManager()) && currentId() == + PackageManagerCore::InstallationFinished && wb == QWizard::FinishButton) { wb = QWizard::CancelButton; } if (QAbstractButton *b = button(static_cast<QWizard::WizardButton>(wb) )) @@ -365,23 +365,17 @@ void PackageManagerGui::setValidatorForCustomPageRequested(Component *component, */ void PackageManagerGui::loadControlScript(const QString &scriptPath) { - d->m_controlScriptContext = m_core->scriptEngine()->loadInConext( + d->m_controlScriptContext = m_core->controlScriptEngine()->loadInConext( QLatin1String("Controller"), scriptPath); qDebug() << "Loaded control script" << scriptPath; } -void PackageManagerGui::slotCurrentPageChanged(int id) -{ - QMetaObject::invokeMethod(this, "delayedControlScriptExecution", Qt::QueuedConnection, - Q_ARG(int, id)); -} - void PackageManagerGui::callControlScriptMethod(const QString &methodName) { if (!d->m_controlScriptContext.isValid()) return; try { - QScriptValue returnValue = m_core->scriptEngine()->callScriptMethod( + QScriptValue returnValue = m_core->controlScriptEngine()->callScriptMethod( d->m_controlScriptContext, methodName); if (!returnValue.isValid()) { @@ -393,9 +387,9 @@ void PackageManagerGui::callControlScriptMethod(const QString &methodName) } } -void PackageManagerGui::delayedControlScriptExecution(int id) +void PackageManagerGui::executeControlScript(int pageId) { - if (PackageManagerPage *const p = qobject_cast<PackageManagerPage*> (page(id))) + if (PackageManagerPage *const p = qobject_cast<PackageManagerPage*> (page(pageId))) callControlScriptMethod(p->objectName() + QLatin1String("Callback")); } @@ -541,6 +535,7 @@ void PackageManagerGui::cancelButtonClicked() QDialog::reject(); } } else { + m_core->setNeedsHardRestart(false); QDialog::reject(); } } @@ -645,6 +640,7 @@ void PackageManagerGui::dependsOnLocalInstallerBinary() PackageManagerPage::PackageManagerPage(PackageManagerCore *core) : m_fresh(true) , m_complete(true) + , m_needsSettingsButton(false) , m_core(core) , validatorComponent(0) { @@ -1905,7 +1901,7 @@ void FinishedPage::entering() if (!finishedText.isEmpty()) m_msgLabel->setText(finishedText); - if (!packageManagerCore()->value(scRunProgram).isEmpty()) { + if (!packageManagerCore()->isUninstaller() && !packageManagerCore()->value(scRunProgram).isEmpty()) { m_runItCheckBox->show(); m_runItCheckBox->setText(packageManagerCore()->value(scRunProgramDescription, tr("Run %1 now.")) .arg(productName())); @@ -1938,7 +1934,7 @@ void FinishedPage::handleFinishClicked() { const QString program = packageManagerCore()->replaceVariables(packageManagerCore()->value(scRunProgram)); const QStringList args = packageManagerCore()->replaceVariables( - packageManagerCore()->value(scRunProgramArguments)).split(QLatin1Char(' ')); + packageManagerCore()->value(scRunProgramArguments)).split(QLatin1Char(' '), QString::SkipEmptyParts); if (!m_runItCheckBox->isChecked() || program.isEmpty()) return; @@ -1977,7 +1973,7 @@ int RestartPage::nextId() const void RestartPage::entering() { - if (!packageManagerCore()->needsRestart()) { + if (!packageManagerCore()->needsHardRestart()) { if (QAbstractButton *finish = wizard()->button(QWizard::FinishButton)) finish->setVisible(false); QMetaObject::invokeMethod(this, "restart", Qt::QueuedConnection); diff --git a/src/libs/installer/packagemanagergui.h b/src/libs/installer/packagemanagergui.h index 2039dabfb..948fb346a 100644 --- a/src/libs/installer/packagemanagergui.h +++ b/src/libs/installer/packagemanagergui.h @@ -60,7 +60,6 @@ class QListWidget; class QListWidgetItem; class QRadioButton; class QTextBrowser; -class QScriptEngine; QT_END_NAMESPACE namespace QInstaller { @@ -117,8 +116,7 @@ protected Q_SLOTS: void wizardWidgetInsertionRequested(QWidget *widget, QInstaller::PackageManagerCore::WizardPage page); void wizardWidgetRemovalRequested(QWidget *widget); void wizardPageVisibilityChangeRequested(bool visible, int page); - void slotCurrentPageChanged(int id); - void delayedControlScriptExecution(int id); + void executeControlScript(int pageId); void setValidatorForCustomPageRequested(QInstaller::Component *component, const QString &name, const QString &callbackName); @@ -168,6 +166,10 @@ public: void setValidatePageComponent(QInstaller::Component *component); bool validatePage(); + + bool settingsButtonRequested() const { return m_needsSettingsButton; } + void setSettingsButtonRequested(bool request) { m_needsSettingsButton = request; } + signals: void entered(); void left(); @@ -192,6 +194,7 @@ private: bool m_fresh; bool m_complete; QString m_titleColor; + bool m_needsSettingsButton; PackageManagerCore *m_core; QInstaller::Component *validatorComponent; diff --git a/src/libs/installer/packagemanagerpagefactory.cpp b/src/libs/installer/packagemanagerpagefactory.cpp new file mode 100644 index 000000000..ddfb5b6d4 --- /dev/null +++ b/src/libs/installer/packagemanagerpagefactory.cpp @@ -0,0 +1,57 @@ +/************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include <packagemanagerpagefactory.h> + +namespace QInstaller { + +PackageManagerPageFactory &PackageManagerPageFactory::instance() +{ + static PackageManagerPageFactory factory; + 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 new file mode 100644 index 000000000..001fb6cd5 --- /dev/null +++ b/src/libs/installer/packagemanagerpagefactory.h @@ -0,0 +1,72 @@ +/************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef PACKAGEMANAGERPAGEFACTORY_H +#define PACKAGEMANAGERPAGEFACTORY_H + +#include <kdgenericfactory.h> +#include <packagemanagergui.h> + +namespace QInstaller { + +class PackageManagerCore; +class PackageManagerPage; + +class INSTALLER_EXPORT PackageManagerPageFactory : public KDGenericFactory<PackageManagerPage, + int, QInstaller::PackageManagerCore*> +{ + Q_DISABLE_COPY(PackageManagerPageFactory) + +public: + static PackageManagerPageFactory &instance(); + template<typename T> void registerPackageManagerPage(int id) + { + registerProductWithArg<T>(id); + } + PackageManagerPage *create(int id, QInstaller::PackageManagerCore *core) const; + +private: + PackageManagerPageFactory() {} +}; + +} // namespace QInstaller + +#endif // PACKAGEMANAGERPAGEFACTORY_H diff --git a/src/libs/installer/packagemanagerproxyfactory.cpp b/src/libs/installer/packagemanagerproxyfactory.cpp index 42f8e9893..219ff5e49 100644 --- a/src/libs/installer/packagemanagerproxyfactory.cpp +++ b/src/libs/installer/packagemanagerproxyfactory.cpp @@ -79,8 +79,10 @@ QList<QNetworkProxy> PackageManagerProxyFactory::queryProxy(const QNetworkProxyQ if (query.url().scheme() == QLatin1String("ftp")) return list << settings.ftpProxy(); - if (query.url().scheme() == QLatin1String("http")) - return list << settings.httpProxy(); + if ((query.url().scheme() == QLatin1String("http")) + || (query.url().scheme() == QLatin1String("https"))) { + return list << settings.httpProxy(); + } } return list << QNetworkProxy(QNetworkProxy::DefaultProxy); } diff --git a/src/libs/installer/productkeycheck.cpp b/src/libs/installer/productkeycheck.cpp index a4af2b6d3..232dbb719 100644 --- a/src/libs/installer/productkeycheck.cpp +++ b/src/libs/installer/productkeycheck.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (c) 2012 Digia Plc and/or its subsidiary(-ies). +** Copyright (c) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Installer Framework @@ -27,18 +27,13 @@ ** **************************************************************************/ -#include <productkeycheck.h> -#include <packagemanagercore.h> +#include "productkeycheck.h" +#include "packagemanagercore.h" class ProductKeyCheckPrivate { - public: - static QPointer<QInstaller::PackageManagerCore> core; }; -QPointer<QInstaller::PackageManagerCore> ProductKeyCheckPrivate::core = 0; - - ProductKeyCheck::ProductKeyCheck() : d(new ProductKeyCheckPrivate()) { @@ -49,20 +44,17 @@ ProductKeyCheck::~ProductKeyCheck() delete d; } -ProductKeyCheck *ProductKeyCheck::instance(QInstaller::PackageManagerCore *core) +ProductKeyCheck *ProductKeyCheck::instance() { static ProductKeyCheck instance; - if (core) - instance.setPackageManagerCore(core); return &instance; } -void ProductKeyCheck::setPackageManagerCore(QInstaller::PackageManagerCore *core) +void ProductKeyCheck::init(QInstaller::PackageManagerCore *core) { - ProductKeyCheckPrivate::core = core; + Q_UNUSED(core) } - bool ProductKeyCheck::hasValidKey() { return true; @@ -89,9 +81,13 @@ bool ProductKeyCheck::isValidLicenseTextFile(const QString &/*fileName*/) return true; } - bool ProductKeyCheck::isValidRepository(const QInstaller::Repository &repository) const { Q_UNUSED(repository) return true; -}
\ No newline at end of file +} + +QList<int> ProductKeyCheck::registeredPages() const +{ + return QList<int>(); +} diff --git a/src/libs/installer/productkeycheck.h b/src/libs/installer/productkeycheck.h index 6d72089e2..3df747f37 100644 --- a/src/libs/installer/productkeycheck.h +++ b/src/libs/installer/productkeycheck.h @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (c) 2012 Digia Plc and/or its subsidiary(-ies). +** Copyright (c) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Installer Framework @@ -30,11 +30,9 @@ #ifndef PRODUCTKEYCHECK_H #define PRODUCTKEYCHECK_H -#include "qinstallerglobal.h" +#include "installer_global.h" #include <QString> -#include <QHash> -#include <QPointer> namespace QInstaller{ class PackageManagerCore; @@ -47,8 +45,8 @@ class INSTALLER_EXPORT ProductKeyCheck { public: ~ProductKeyCheck(); - static ProductKeyCheck *instance(QInstaller::PackageManagerCore *core = 0); - static void setPackageManagerCore(QInstaller::PackageManagerCore *core); + static ProductKeyCheck *instance(); + void init(QInstaller::PackageManagerCore *core); // was validLicense bool hasValidKey(); @@ -64,9 +62,12 @@ public: // to filter repositories not matching the license bool isValidRepository(const QInstaller::Repository &repository) const; + QList<int> registeredPages() const; + private: ProductKeyCheck(); ProductKeyCheckPrivate *const d; + Q_DISABLE_COPY(ProductKeyCheck) }; #endif // PRODUCTKEYCHECK_H diff --git a/src/libs/installer/progresscoordinator.cpp b/src/libs/installer/progresscoordinator.cpp index 0850b39d0..e55f4b8bb 100644 --- a/src/libs/installer/progresscoordinator.cpp +++ b/src/libs/installer/progresscoordinator.cpp @@ -103,6 +103,14 @@ void ProgressCoordinator::registerPartProgress(QObject *sender, const char *sign Q_ASSERT(isConnected); } + +/*! + This slot gets the progress changed signals from different tasks. The values 0 and 1 are handled as + special values. + + 0 - is just ignored, so you can use a timer which gives the progress, e.g. like a downloader does. + 1 - means the task is finished, even if there comes another 1 from that task, so it will be ignored. +*/ void ProgressCoordinator::partProgressChanged(double fraction) { if (fraction < 0 || fraction > 1) { @@ -110,6 +118,16 @@ void ProgressCoordinator::partProgressChanged(double fraction) return; } + // no fraction no change + if (fraction == 0) + return; + + // ignore senders sending 100% multiple times + if (fraction == 1 && m_senderPendingCalculatedPercentageHash.contains(sender()) + && m_senderPendingCalculatedPercentageHash.value(sender()) == 0) { + return; + } + double partProgressSize = m_senderPartProgressSizeHash.value(sender(), 0); if (partProgressSize == 0) { qWarning() << "It seems that this sender was not registered in the right way:" << sender(); @@ -137,9 +155,9 @@ void ProgressCoordinator::partProgressChanged(double fraction) newCurrentCompletePercentage = 100; } - if (qRound(m_currentCompletePercentage) < qRound(newCurrentCompletePercentage)) { - qWarning("This should not happen!"); - } + // In undo mode, the progress has to go backward, new has to be smaller than current + if (qRound(m_currentCompletePercentage) < qRound(newCurrentCompletePercentage)) + qDebug("Something is wrong with the calculation of the progress."); m_currentCompletePercentage = newCurrentCompletePercentage; if (fraction == 1) { @@ -170,12 +188,13 @@ void ProgressCoordinator::partProgressChanged(double fraction) newCurrentCompletePercentage = 100; } - if (qRound(m_currentCompletePercentage) > qRound(newCurrentCompletePercentage)) { - qWarning("This should not happen!"); - } + // In normal mode, the progress has to go forward, new has to be larger than current + if (qRound(m_currentCompletePercentage) > qRound(newCurrentCompletePercentage)) + qDebug("Something is wrong with the calculation of the progress."); + m_currentCompletePercentage = newCurrentCompletePercentage; - if (fraction == 1 || fraction == 0) { + if (fraction == 1) { m_currentBasePercentage = m_currentBasePercentage + pendingCalculatedPartPercentage; m_senderPendingCalculatedPercentageHash.insert(sender(), 0); } else { diff --git a/src/libs/installer/progresscoordinator.h b/src/libs/installer/progresscoordinator.h index 263b25695..bdd154195 100644 --- a/src/libs/installer/progresscoordinator.h +++ b/src/libs/installer/progresscoordinator.h @@ -42,13 +42,15 @@ #ifndef PROGRESSCOORDINATOR_H #define PROGRESSCOORDINATOR_H +#include "installer_global.h" + #include <QtCore/QHash> #include <QtCore/QObject> #include <QtCore/QPointer> namespace QInstaller { -class ProgressCoordinator : public QObject +class INSTALLER_EXPORT ProgressCoordinator : public QObject { Q_OBJECT diff --git a/src/libs/installer/qtpatch.cpp b/src/libs/installer/qtpatch.cpp index 7a1e18df3..825c9ad48 100644 --- a/src/libs/installer/qtpatch.cpp +++ b/src/libs/installer/qtpatch.cpp @@ -75,7 +75,7 @@ QHash<QString, QByteArray> QtPatch::qmakeValues(const QString &qmakePath, QByteA // in some cases qmake is not runable, because another process is blocking it(filewatcher ...) int waitCount = 0; - while (qmakeValueHash.isEmpty() && waitCount < 60) { + while (qmakeValueHash.isEmpty() && waitCount < 3) { QFileInfo qmake(qmakePath); if (!qmake.exists()) { @@ -92,13 +92,16 @@ QHash<QString, QByteArray> QtPatch::qmakeValues(const QString &qmakePath, QByteA QProcess process; process.start(qmake.absoluteFilePath(), args, QIODevice::ReadOnly); - if (process.waitForFinished(2000)) { + if (process.waitForFinished(10000)) { + QByteArray output = process.readAllStandardOutput(); + qmakeOutput->append(output); if (process.exitStatus() == QProcess::CrashExit) { - qDebug() << qmakePath << "was crashed"; + qWarning() << qmake.absoluteFilePath() << args + << "crashed with exit code" << process.exitCode() + << "standard output: " << output + << "error output: " << process.readAllStandardError(); return qmakeValueHash; } - QByteArray output = process.readAllStandardOutput(); - qmakeOutput->append(output); qmakeValueHash = readQmakeOutput(output); } if (qmakeValueHash.isEmpty()) { diff --git a/src/libs/installer/resources/files-to-patch-linux-emb-arm b/src/libs/installer/resources/files-to-patch-linux-emb-arm index f6a4b59b7..8ea297b50 100644 --- a/src/libs/installer/resources/files-to-patch-linux-emb-arm +++ b/src/libs/installer/resources/files-to-patch-linux-emb-arm @@ -8,5 +8,5 @@ host-bin/qdoc *.la *.prl *.pc - - +*.pri +*.cmake diff --git a/src/libs/installer/resources/files-to-patch-linux-emb-arm-qt4 b/src/libs/installer/resources/files-to-patch-linux-emb-arm-qt4 new file mode 100644 index 000000000..f6a4b59b7 --- /dev/null +++ b/src/libs/installer/resources/files-to-patch-linux-emb-arm-qt4 @@ -0,0 +1,12 @@ +bin/qmake +bin/lrelease +bin/qdoc +host-bin/qmake +host-bin/lrelease +host-bin/qdoc +%% +*.la +*.prl +*.pc + + diff --git a/src/libs/installer/resources/files-to-patch-linux-emb-arm-qt5 b/src/libs/installer/resources/files-to-patch-linux-emb-arm-qt5 new file mode 100644 index 000000000..8ea297b50 --- /dev/null +++ b/src/libs/installer/resources/files-to-patch-linux-emb-arm-qt5 @@ -0,0 +1,12 @@ +bin/qmake +bin/lrelease +bin/qdoc +host-bin/qmake +host-bin/lrelease +host-bin/qdoc +%% +*.la +*.prl +*.pc +*.pri +*.cmake diff --git a/src/libs/installer/resources/files-to-patch-macx-emb-arm b/src/libs/installer/resources/files-to-patch-macx-emb-arm-qt5 index c01fe17a1..c01fe17a1 100644 --- a/src/libs/installer/resources/files-to-patch-macx-emb-arm +++ b/src/libs/installer/resources/files-to-patch-macx-emb-arm-qt5 diff --git a/src/libs/installer/resources/files-to-patch-windows-emb-arm b/src/libs/installer/resources/files-to-patch-windows-emb-arm index 674adaff6..a43229d18 100644 --- a/src/libs/installer/resources/files-to-patch-windows-emb-arm +++ b/src/libs/installer/resources/files-to-patch-windows-emb-arm @@ -8,4 +8,6 @@ host-bin/qdoc.exe *.la *.prl *.pc +*.pri +*.cmake diff --git a/src/libs/installer/resources/files-to-patch-windows-emb-arm-qt5 b/src/libs/installer/resources/files-to-patch-windows-emb-arm-qt5 new file mode 100644 index 000000000..a43229d18 --- /dev/null +++ b/src/libs/installer/resources/files-to-patch-windows-emb-arm-qt5 @@ -0,0 +1,13 @@ +bin/qmake.exe +bin/lrelease.exe +bin/qdoc.exe +host-bin/qmake.exe +host-bin/lrelease.exe +host-bin/qdoc.exe +%% +*.la +*.prl +*.pc +*.pri +*.cmake + diff --git a/src/libs/installer/resources/patch_file_lists.qrc b/src/libs/installer/resources/patch_file_lists.qrc index e898b9b23..b300b69ac 100644 --- a/src/libs/installer/resources/patch_file_lists.qrc +++ b/src/libs/installer/resources/patch_file_lists.qrc @@ -8,6 +8,8 @@ <file>files-to-patch-macx-qt5</file> <file>files-to-patch-linux-emb-arm</file> <file>files-to-patch-windows-emb-arm</file> - <file>files-to-patch-macx-emb-arm</file> + <file>files-to-patch-windows-emb-arm-qt5</file> + <file>files-to-patch-macx-emb-arm-qt5</file> + <file>files-to-patch-linux-emb-arm-qt5</file> </qresource> </RCC> diff --git a/src/libs/installer/scriptengine.cpp b/src/libs/installer/scriptengine.cpp index e85ce9671..a2fe9f049 100644 --- a/src/libs/installer/scriptengine.cpp +++ b/src/libs/installer/scriptengine.cpp @@ -192,6 +192,7 @@ ScriptEngine::ScriptEngine(PackageManagerCore *core) installTranslatorFunctions(); globalObject().setProperty(QLatin1String("QMessageBox"), generateMessageBoxObject()); + globalObject().setProperty(QLatin1String("buttons"), generateWizardButtonsObject()); globalObject().setProperty(QLatin1String("QDesktopServices"), generateDesktopServicesObject()); globalObject().setProperty(QLatin1String("QInstaller"), generateQInstallerObject()); @@ -216,6 +217,9 @@ ScriptEngine::ScriptEngine(PackageManagerCore *core) .setProperty(QLatin1String("components"), scriptComponentsObject); connect(this, SIGNAL(signalHandlerException(QScriptValue)), SLOT(handleException(QScriptValue))); + + connect(core, SIGNAL(guiObjectChanged(QObject*)), this, SLOT(setGuiQObject(QObject*))); + setGuiQObject(core->guiObject()); } ScriptEngine::~ScriptEngine() @@ -224,25 +228,6 @@ ScriptEngine::~ScriptEngine() void ScriptEngine::setGuiQObject(QObject *guiQObject) { - if (qobject_cast<QWizard*>(guiQObject)) { -#undef REGISTER_BUTTON -#define REGISTER_BUTTON(x) buttons.setProperty(QLatin1String(#x), \ - newVariant(static_cast<int>(QWizard::x))); - - QScriptValue buttons = newArray(); - REGISTER_BUTTON(BackButton) - REGISTER_BUTTON(NextButton) - REGISTER_BUTTON(CommitButton) - REGISTER_BUTTON(FinishButton) - REGISTER_BUTTON(CancelButton) - REGISTER_BUTTON(HelpButton) - REGISTER_BUTTON(CustomButton1) - REGISTER_BUTTON(CustomButton2) - REGISTER_BUTTON(CustomButton3) - -#undef REGISTER_BUTTON - globalObject().setProperty(QLatin1String("buttons"), buttons); - } globalObject().setProperty(QLatin1String("gui"), newQObject(guiQObject)); } @@ -324,6 +309,27 @@ QScriptValue ScriptEngine::callScriptMethod(const QScriptValue &scriptContext, } +QScriptValue ScriptEngine::generateWizardButtonsObject() +{ +#undef REGISTER_BUTTON +#define REGISTER_BUTTON(x) buttons.setProperty(QLatin1String(#x), \ + newVariant(static_cast<int>(QWizard::x))); + + QScriptValue buttons = newArray(); + REGISTER_BUTTON(BackButton) + REGISTER_BUTTON(NextButton) + REGISTER_BUTTON(CommitButton) + REGISTER_BUTTON(FinishButton) + REGISTER_BUTTON(CancelButton) + REGISTER_BUTTON(HelpButton) + REGISTER_BUTTON(CustomButton1) + REGISTER_BUTTON(CustomButton2) + REGISTER_BUTTON(CustomButton3) + +#undef REGISTER_BUTTON + return buttons; +} + /*! generates QMessageBox::StandardButton enum as an QScriptValue array */ diff --git a/src/libs/installer/scriptengine.h b/src/libs/installer/scriptengine.h index 50c50539b..e52862e06 100644 --- a/src/libs/installer/scriptengine.h +++ b/src/libs/installer/scriptengine.h @@ -70,14 +70,15 @@ class INSTALLER_EXPORT ScriptEngine : public QScriptEngine public: explicit ScriptEngine(PackageManagerCore *core); ~ScriptEngine(); - void setGuiQObject(QObject *guiQObject); QScriptValue callScriptMethod(const QScriptValue &scriptContext, const QString &methodName, const QScriptValueList &arguments = QScriptValueList()) const; QScriptValue loadInConext(const QString &context, const QString &fileName, const QString &scriptInjection = QString()); private slots: void handleException(const QScriptValue &value); + void setGuiQObject(QObject *guiQObject); private: + QScriptValue generateWizardButtonsObject(); QScriptValue generateMessageBoxObject(); QScriptValue generateDesktopServicesObject(); QScriptValue generateQInstallerObject(); diff --git a/src/libs/installer/settings.cpp b/src/libs/installer/settings.cpp index 067dce47c..90cb431f4 100644 --- a/src/libs/installer/settings.cpp +++ b/src/libs/installer/settings.cpp @@ -573,6 +573,11 @@ bool Settings::repositorySettingsPageVisible() const return d->m_data.value(scRepositorySettingsPageVisible, true).toBool(); } +void Settings::setRepositorySettingsPageVisible(bool visible) +{ + d->m_data.insert(scRepositorySettingsPageVisible, visible); +} + Settings::ProxyType Settings::proxyType() const { return Settings::ProxyType(d->m_data.value(scProxyType, Settings::NoProxy).toInt()); diff --git a/src/libs/installer/settings.h b/src/libs/installer/settings.h index d8c827c61..9bce8bd70 100644 --- a/src/libs/installer/settings.h +++ b/src/libs/installer/settings.h @@ -144,6 +144,7 @@ public: QVariantList values(const QString &key, const QVariantList &defaultValue = QVariantList()) const; bool repositorySettingsPageVisible() const; + void setRepositorySettingsPageVisible(bool visible); Settings::ProxyType proxyType() const; void setProxyType(Settings::ProxyType type); diff --git a/src/libs/installer/settingsoperation.cpp b/src/libs/installer/settingsoperation.cpp new file mode 100644 index 000000000..6fde21268 --- /dev/null +++ b/src/libs/installer/settingsoperation.cpp @@ -0,0 +1,216 @@ +/************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ +#include "settingsoperation.h" +#include "packagemanagercore.h" +#include "kdupdaterupdateoperations.h" + +#include <QSettings> +#include <QDir> +#include <QDebug> + +using namespace QInstaller; + +SettingsOperation::SettingsOperation() +{ + setName(QLatin1String("Settings")); +} + +void SettingsOperation::backup() +{ +} + +bool SettingsOperation::checkArguments() +{ + const QString path = argumentKeyValue(QLatin1String("path")); + const QString method = argumentKeyValue(QLatin1String("method")); + const QString key = argumentKeyValue(QLatin1String("key")); + const QString aValue = argumentKeyValue(QLatin1String("value")); + + QStringList missingArguments; + if (path.isEmpty()) + missingArguments << QLatin1String("path"); + if (method.isEmpty()) + missingArguments << QLatin1String("method"); + if (key.isEmpty()) + missingArguments << QLatin1String("key"); + if (method != QLatin1String("remove") && aValue.isEmpty()) + missingArguments << QLatin1String("value"); + + if (!missingArguments.isEmpty()) { + setError(InvalidArguments); + setErrorString(tr("Missing argument(s) '%1' calling '%2' with arguments '%3'.").arg( + missingArguments.join(QLatin1String("; ")), name(), arguments().join(QLatin1String("; ")))); + return false; + } + QStringList possibleMethodValues; + possibleMethodValues << QLatin1String("set") << QLatin1String("remove") << + QLatin1String("add_array_value") << QLatin1String("remove_array_value"); + + if (!possibleMethodValues.contains(method)) { + setError(InvalidArguments); + 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; + } + return true; +} + + +bool SettingsOperation::performOperation() +{ + // Arguments: + // 1. path=settings file path or registry path + // 2. method=set|remove|add_array_value|remove_array_value + // 3. key=can be prepended by a category name separated by slash + // 4. value=just the value + // optional arguments are + // formate=native or ini TODO + // backup=true or false (default is true) TODO + // NOTE: remove and remove_array_value will do nothing at the undostep + + if (!checkArguments()) + return false; + const QString path = argumentKeyValue(QLatin1String("path")); + const QString method = argumentKeyValue(QLatin1String("method")); + const QString key = argumentKeyValue(QLatin1String("key")); + const QString aValue = argumentKeyValue(QLatin1String("value")); + + // use MkdirOperation to get the path so it can remove it with MkdirOperation::undoOperation later + KDUpdater::MkdirOperation mkDirOperation; + mkDirOperation.setArguments(QStringList() << QFileInfo(path).absolutePath()); + mkDirOperation.backup(); + if (!mkDirOperation.performOperation()) { + setError(mkDirOperation.error()); + setErrorString(mkDirOperation.errorString()); + return false; + } + setValue(QLatin1String("createddir"), mkDirOperation.value(QLatin1String("createddir"))); + + QSettings settings(path, QSettings::IniFormat); + if (method == QLatin1String("set")) + settings.setValue(key, aValue); + else if (method == QLatin1String("remove")) + settings.remove(key); + else if (method == QLatin1String("add_array_value")) { + QVariant valueVariant = settings.value(key); + if (valueVariant.canConvert<QStringList>()) { + QStringList array = valueVariant.toStringList(); + array.append(aValue); + settings.setValue(key, array); + } else { + settings.setValue(key, aValue); + } + } else if (method == QLatin1String("remove_array_value")) { + QVariant valueVariant = settings.value(key); + if (valueVariant.canConvert<QStringList>()) { + QStringList array = valueVariant.toStringList(); + array.removeOne(aValue); + settings.setValue(key, array); + } else { + settings.remove(key); + } + } + + return true; +} + +bool SettingsOperation::undoOperation() +{ + if (!checkArguments()) + return false; + const QString path = argumentKeyValue(QLatin1String("path")); + const QString method = argumentKeyValue(QLatin1String("method")); + const QString key = argumentKeyValue(QLatin1String("key")); + const QString aValue = argumentKeyValue(QLatin1String("value")); + + if (method.startsWith(QLatin1String("remove"))) + return true; + + bool cleanUp = false; + { // kill the scope to kill settings object, else remove file will not work + QSettings settings(path, QSettings::IniFormat); + if (method == QLatin1String("set")) { + settings.remove(key); + } else if (method == QLatin1String("add_array_value")) { + QVariant valueVariant = settings.value(key); + if (valueVariant.canConvert<QStringList>()) { + QStringList array = valueVariant.toStringList(); + array.removeOne(aValue); + if (array.isEmpty()) + settings.remove(key); + else + settings.setValue(key, array); + } else { + settings.setValue(key, aValue); + } + } + settings.sync(); // be safe + cleanUp = settings.allKeys().isEmpty(); + } + + if (cleanUp) { + QFile settingsFile(path); + if (!settingsFile.remove()) + qWarning() << 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(); + } + } + } + return true; +} + +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 new file mode 100644 index 000000000..248c9a0df --- /dev/null +++ b/src/libs/installer/settingsoperation.h @@ -0,0 +1,66 @@ +/************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef SETTINGSOPERATION_H +#define SETTINGSOPERATION_H + +#include "qinstallerglobal.h" + +namespace QInstaller { + +class INSTALLER_EXPORT SettingsOperation : public Operation +{ +public: + SettingsOperation(); + + void backup(); + bool performOperation(); + bool undoOperation(); + bool testOperation(); + Operation *clone() const; + +private: + bool checkArguments(); +}; + +} // namespace QInstaller + +#endif // SETTINGSOPERATION_H diff --git a/src/libs/installer/sysinfo_win.cpp b/src/libs/installer/sysinfo_win.cpp index 618d6cfdb..8b14d1567 100644 --- a/src/libs/installer/sysinfo_win.cpp +++ b/src/libs/installer/sysinfo_win.cpp @@ -40,7 +40,6 @@ **************************************************************************/ #include "kdsysinfo.h" - #include "link.h" #ifdef Q_CC_MINGW @@ -49,10 +48,10 @@ # endif #endif -#include <windows.h> +#include <qt_windows.h> #include <psapi.h> #include <tlhelp32.h> - +#include <winbase.h> #include <winnetwk.h> #ifndef Q_CC_MINGW diff --git a/src/libs/installer/testrepository.cpp b/src/libs/installer/testrepository.cpp new file mode 100644 index 000000000..a39c499a1 --- /dev/null +++ b/src/libs/installer/testrepository.cpp @@ -0,0 +1,168 @@ +/************************************************************************** +** +** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ +#include "testrepository.h" + +#include <kdupdaterfiledownloader.h> +#include <kdupdaterfiledownloaderfactory.h> + +#include <QtCore/QFile> + +using namespace QInstaller; + +TestRepository::TestRepository(QObject *parent) + : KDJob(parent) + , m_downloader(0) +{ + setTimeout(10000); + setAutoDelete(false); + setCapabilities(Cancelable); +} + +TestRepository::~TestRepository() +{ + if (m_downloader) + m_downloader->deleteLater(); +} + +Repository TestRepository::repository() const +{ + return m_repository; +} + +void TestRepository::setRepository(const Repository &repository) +{ + cancel(); + + setError(NoError); + setErrorString(QString()); + m_repository = repository; +} + +void TestRepository::doStart() +{ + if (m_downloader) + m_downloader->deleteLater(); + + 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())); + 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"))); + + m_downloader->download(); +} + +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); + } +} + +void TestRepository::downloadCompleted() +{ + QString errorMsg; + int error = DownloadError; + + if (m_downloader->isDownloaded()) { + QFile file(m_downloader->downloadedFileName()); + if (file.exists() && 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); + } else { + error = NoError; + } + } else { + errorMsg = tr("Updates.xml could not be opened for reading!"); + } + } else { + errorMsg = tr("Updates.xml could not be found on server!"); + } + + if (error > NoError) + emitFinishedWithError(error, errorMsg); + else + emitFinished(); + + m_downloader->deleteLater(); + m_downloader = 0; +} + +void TestRepository::downloadAborted(const QString &reason) +{ + emitFinishedWithError(DownloadError, reason); +} + +void TestRepository::onAuthenticatorChanged(const QAuthenticator &authenticator) +{ + m_repository.setUsername(authenticator.user()); + m_repository.setPassword(authenticator.password()); +} diff --git a/src/libs/installer/testrepository.h b/src/libs/installer/testrepository.h new file mode 100644 index 000000000..c1ecc039c --- /dev/null +++ b/src/libs/installer/testrepository.h @@ -0,0 +1,95 @@ +/************************************************************************** +** +** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ +#ifndef TESTREPOSITORY_H +#define TESTREPOSITORY_H + +#include "qinstallerglobal.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; +} + +namespace QInstaller { + class PackageManagerCore; +} + +namespace QInstaller { + +class INSTALLER_EXPORT TestRepository : public KDJob +{ + Q_OBJECT + +public: + + explicit TestRepository(QObject *parent = 0); + ~TestRepository(); + + QInstaller::Repository repository() const; + void setRepository(const QInstaller::Repository &repository); + +private: + void doStart(); + void doCancel(); + +private Q_SLOTS: + void downloadCompleted(); + void downloadAborted(const QString &reason); + void onAuthenticatorChanged(const QAuthenticator &authenticator); + +private: + QInstaller::Repository m_repository; + KDUpdater::FileDownloader *m_downloader; +}; + +} //namespace QInstaller + +#endif // TESTREPOSITORY_H diff --git a/src/libs/installer/updater.cpp b/src/libs/installer/updater.cpp index b51b332ed..ae6eaac29 100644 --- a/src/libs/installer/updater.cpp +++ b/src/libs/installer/updater.cpp @@ -40,6 +40,7 @@ **************************************************************************/ #include "updater.h" +#include "productkeycheck.h" #include "binaryformat.h" #include "component.h" #include "init.h" @@ -77,6 +78,7 @@ bool Updater::checkForUpdates() PackageManagerCore core(content.magicMarker(), content.performedOperations()); core.setUpdater(); PackageManagerCore::setVirtualComponentsVisible(true); + ProductKeyCheck::instance()->init(&core); if (!core.fetchRemotePackagesTree()) return false; diff --git a/src/libs/installer/utils.cpp b/src/libs/installer/utils.cpp index 2b5491f62..469ba5980 100644 --- a/src/libs/installer/utils.cpp +++ b/src/libs/installer/utils.cpp @@ -47,7 +47,7 @@ #include <QtCore/QVector> #include <QCoreApplication> -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) || defined(Q_OS_WINCE) # include "qt_windows.h" #endif @@ -55,10 +55,6 @@ #include <iostream> #include <sstream> - -#ifdef Q_OS_WIN -#include <windows.h> // for Sleep -#endif #ifdef Q_OS_UNIX #include <errno.h> #include <signal.h> diff --git a/src/libs/kdtools/kdgenericfactory.h b/src/libs/kdtools/kdgenericfactory.h index 349c5ee92..4108c16fd 100644 --- a/src/libs/kdtools/kdgenericfactory.h +++ b/src/libs/kdtools/kdgenericfactory.h @@ -46,13 +46,14 @@ #include <QtCore/QHash> -template <typename T_Product, typename T_Identifier = QString> +template <typename T_Product, typename T_Identifier = QString, typename T_Argument = QString> class KDGenericFactory { public: virtual ~KDGenericFactory() {} typedef T_Product *(*FactoryFunction)(); + typedef T_Product *(*FactoryFunctionWithArg)(const T_Argument &arg); template <typename T> void registerProduct(const T_Identifier &name) @@ -73,6 +74,25 @@ public: return (*it)(); } + template <typename T> + void registerProductWithArg(const T_Identifier &name) + { +#ifdef Q_CC_MSVC + FactoryFunctionWithArg function = &KDGenericFactory::create<T>; +#else // compile fix for old gcc + FactoryFunctionWithArg function = &create<T>; +#endif + map2.insert(name, function); + } + + T_Product *createWithArg(const T_Identifier &name, const T_Argument &arg) const + { + const typename QHash<T_Identifier, FactoryFunctionWithArg>::const_iterator it = map2.find(name); + if (it == map2.end()) + return 0; + return (*it)(arg); + } + private: template <typename T> static T_Product *create() @@ -80,7 +100,14 @@ private: return new T; } + template <typename T> + static T_Product *create(const T_Argument &arg) + { + return new T(arg); + } + QHash<T_Identifier, FactoryFunction> map; + QHash<T_Identifier, FactoryFunctionWithArg> map2; }; #endif diff --git a/src/libs/kdtools/kdsavefile.cpp b/src/libs/kdtools/kdsavefile.cpp index 483f1b338..88b95f42e 100644 --- a/src/libs/kdtools/kdsavefile.cpp +++ b/src/libs/kdtools/kdsavefile.cpp @@ -299,7 +299,7 @@ bool KDSaveFile::open(OpenMode mode) return opened; } -bool KDSaveFile::atEnd() +bool KDSaveFile::atEnd() const { return d->tmpFile ? d->tmpFile->atEnd() : QIODevice::atEnd(); } diff --git a/src/libs/kdtools/kdsavefile.h b/src/libs/kdtools/kdsavefile.h index 24eee9870..7408892d0 100644 --- a/src/libs/kdtools/kdsavefile.h +++ b/src/libs/kdtools/kdsavefile.h @@ -76,7 +76,7 @@ public: bool resize(qint64 size); int handle() const; - bool atEnd(); + bool atEnd() const; qint64 bytesAvailable() const; qint64 bytesToWrite() const; bool canReadLine() const; diff --git a/src/libs/kdtools/kdsysinfo_win.cpp b/src/libs/kdtools/kdsysinfo_win.cpp index edeeb6879..cc28b35d2 100644 --- a/src/libs/kdtools/kdsysinfo_win.cpp +++ b/src/libs/kdtools/kdsysinfo_win.cpp @@ -44,13 +44,7 @@ #include <QLibrary> #include <QStringList> -#ifdef Q_CC_MINGW -# ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 -# endif -#endif - -#include <windows.h> +#include <qt_windows.h> #include <psapi.h> #include <tlhelp32.h> diff --git a/src/libs/kdtools/kdupdaterupdateoperation.cpp b/src/libs/kdtools/kdupdaterupdateoperation.cpp index c1591f467..9ba165d4b 100644 --- a/src/libs/kdtools/kdupdaterupdateoperation.cpp +++ b/src/libs/kdtools/kdupdaterupdateoperation.cpp @@ -176,6 +176,40 @@ QStringList UpdateOperation::arguments() const return m_arguments; } +struct StartsWith +{ + StartsWith(const QString &searchTerm) + : m_searchTerm(searchTerm) {} + + bool operator()(const QString &searchString) + { + return searchString.startsWith(m_searchTerm); + } + + QString m_searchTerm; +}; + + +QString UpdateOperation::argumentKeyValue(const QString &key, const QString &defaultValue) const +{ + const QString keySeparater(key + QLatin1String("=")); + const QStringList tArguments(arguments()); + QStringList::const_iterator it = std::find_if(tArguments.begin(), tArguments.end(), + StartsWith(keySeparater)); + if (it == tArguments.end()) + return defaultValue; + + const QString value = it->mid(keySeparater.size()); + + it = std::find_if(++it, tArguments.end(), StartsWith(keySeparater)); + if (it != tArguments.end()) { + qWarning() << QString::fromLatin1("There are multiple keys in the arguments calling" + " '%1'. Only the first found '%2' is used: '%3'").arg(name(), key, arguments().join( + QLatin1String("; "))); + } + return value; +} + /*! Returns error details in case performOperation() failed. */ diff --git a/src/libs/kdtools/kdupdaterupdateoperation.h b/src/libs/kdtools/kdupdaterupdateoperation.h index cac68d2f1..21b7b64a3 100644 --- a/src/libs/kdtools/kdupdaterupdateoperation.h +++ b/src/libs/kdtools/kdupdaterupdateoperation.h @@ -75,6 +75,7 @@ public: void setArguments(const QStringList &args); QStringList arguments() const; + QString argumentKeyValue(const QString & key, const QString &defaultValue = QString()) const; void clear(); QString errorString() const; int error() const; diff --git a/src/libs/kdtools/kdupdaterupdateoperations.cpp b/src/libs/kdtools/kdupdaterupdateoperations.cpp index 5a4296242..be123fe61 100644 --- a/src/libs/kdtools/kdupdaterupdateoperations.cpp +++ b/src/libs/kdtools/kdupdaterupdateoperations.cpp @@ -65,29 +65,24 @@ static QString errnoToQString(int error) #endif } -static bool removeDirectory(const QString &path, QString *errorString, bool force = true) +static bool removeDirectory(const QString &path, QString *errorString, bool force) { Q_ASSERT(errorString); - const QFileInfoList entries = QDir(path).entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden); - for (QFileInfoList::const_iterator it = entries.constBegin(); it != entries.constEnd(); ++it) { - if (it->isDir() && !it->isSymLink()) { - removeDirectory(it->filePath(), errorString, force); - } else if (force) { - QFile f(it->filePath()); - if (!f.remove()) - return false; - } + + QDir dir = path; + const QFileInfoList entries = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden); + foreach (const QFileInfo &entry, entries) { + if (entry.isDir() && (!entry.isSymLink())) + removeDirectory(entry.filePath(), errorString, force); + else if (force && (!QFile(entry.filePath()).remove())) + return false; } // even remove some hidden, OS-created files in there -#if defined Q_OS_MAC - QFile::remove(path + QLatin1String("/.DS_Store")); -#elif defined Q_OS_WIN - QFile::remove(path + QLatin1String("/Thumbs.db")); -#endif + QInstaller::removeSystemGeneratedFiles(path); errno = 0; - const bool success = QDir().rmdir(path); + const bool success = dir.rmdir(path); if (errno) *errorString = errnoToQString(errno); return success; @@ -170,7 +165,7 @@ bool CopyOperation::performOperation() QFile sourceFile(source); if (!sourceFile.exists()) { setError(UserDefinedError); - setErrorString(tr("Could not copy a none existing file: %1").arg(source)); + setErrorString(tr("Could not copy a non-existent file: %1").arg(source)); return false; } // If destination file exists, we cannot use QFile::copy() because it does not overwrite an existing diff --git a/src/sdk/console.h b/src/sdk/console.h new file mode 100644 index 000000000..7eb4aa3f4 --- /dev/null +++ b/src/sdk/console.h @@ -0,0 +1,131 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef CONSOLE_H +#define CONSOLE_H + +#include <QtCore/QtGlobal> + +#ifdef Q_OS_WIN +# include <qt_windows.h> +# include <wincon.h> + +# include <fstream> +# include <iostream> + +# ifndef ENABLE_INSERT_MODE +# define ENABLE_INSERT_MODE 0x0020 +# endif + +# ifndef ENABLE_QUICK_EDIT_MODE +# define ENABLE_QUICK_EDIT_MODE 0x0040 +# endif + +# ifndef ENABLE_EXTENDED_FLAGS +# define ENABLE_EXTENDED_FLAGS 0x0080 +# endif + +class Console +{ +public: + Console() + { + AllocConsole(); + HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); + if (handle != INVALID_HANDLE_VALUE) { + COORD largestConsoleWindowSize = GetLargestConsoleWindowSize(handle); + largestConsoleWindowSize.X -= 3; + largestConsoleWindowSize.Y = 5000; + SetConsoleScreenBufferSize(handle, largestConsoleWindowSize); + } + + handle = GetStdHandle(STD_INPUT_HANDLE); + if (handle != INVALID_HANDLE_VALUE) + SetConsoleMode(handle, ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS); + + m_oldCin = std::cin.rdbuf(); + m_newCin.open("CONIN$"); + std::cin.rdbuf(m_newCin.rdbuf()); + + m_oldCout = std::cout.rdbuf(); + m_newCout.open("CONOUT$"); + std::cout.rdbuf(m_newCout.rdbuf()); + + m_oldCerr = std::cerr.rdbuf(); + m_newCerr.open("CONOUT$"); + std::cerr.rdbuf(m_newCerr.rdbuf()); +# ifndef Q_CC_MINGW + HMENU systemMenu = GetSystemMenu(GetConsoleWindow(), FALSE); + if (systemMenu != NULL) + RemoveMenu(systemMenu, SC_CLOSE, MF_BYCOMMAND); + DrawMenuBar(GetConsoleWindow()); +# endif + } + + ~Console() + { + system("PAUSE"); + + std::cin.rdbuf(m_oldCin); + std::cerr.rdbuf(m_oldCerr); + std::cout.rdbuf(m_oldCout); + + FreeConsole(); + } + +private: + std::ifstream m_newCin; + std::ofstream m_newCout; + std::ofstream m_newCerr; + + std::streambuf* m_oldCin; + std::streambuf* m_oldCout; + std::streambuf* m_oldCerr; +}; +#else +class Console +{ +public: + Console() {} +}; +#endif + +#endif // CONSOLE_H diff --git a/src/sdk/installerbase.cpp b/src/sdk/installerbase.cpp index 870182e13..3629cc22f 100644 --- a/src/sdk/installerbase.cpp +++ b/src/sdk/installerbase.cpp @@ -41,6 +41,7 @@ #include "installerbase_p.h" #include "installerbasecommons.h" +#include "sdkapp.h" #include "tabcontroller.h" #include <binaryformat.h> @@ -61,6 +62,9 @@ #include <kdrunoncechecker.h> #include <kdupdaterfiledownloaderfactory.h> +#include <productkeycheck.h> + +#include <QDirIterator> #include <QtCore/QTranslator> #include <QMessageBox> @@ -150,7 +154,7 @@ int main(int argc, char *argv[]) // this is the FSEngineServer as an admin rights process upon request: if (args.count() >= 3 && args[1] == QLatin1String("--startserver")) { - MyCoreApplication app(argc, argv); + SDKApp<QCoreApplication> app(argc, argv); FSEngineServer* const server = new FSEngineServer(args[2].toInt()); if (args.count() >= 4) server->setAuthorizationKey(args[3]); @@ -172,18 +176,21 @@ int main(int argc, char *argv[]) #endif if (args.contains(QLatin1String("--checkupdates"))) { - MyCoreApplication app(argc, argv); + SDKApp<QCoreApplication> app(argc, argv); if (runCheck.isRunning(KDRunOnceChecker::ProcessList)) return 0; Updater u; - u.setVerbose(args.contains(QLatin1String("--verbose")) || args.contains(QLatin1String("-v"))); + if (args.contains(QLatin1String("--verbose")) || args.contains(QLatin1String("-v"))) { + app.setVerbose(); + u.setVerbose(true); + } return u.checkForUpdates() ? 0 : 1; } if (args.contains(QLatin1String("--runoperation")) || args.contains(QLatin1String("--undooperation"))) { - MyCoreApplication app(argc, argv); + SDKApp<QCoreApplication> app(argc, argv); OperationRunner o; o.setVerbose(args.contains(QLatin1String("--verbose")) || args.contains(QLatin1String("-v"))); @@ -191,7 +198,7 @@ int main(int argc, char *argv[]) } if (args.contains(QLatin1String("--update-installerbase"))) { - MyCoreApplication app(argc, argv); + SDKApp<QCoreApplication> app(argc, argv); if (runCheck.isRunning(KDRunOnceChecker::ProcessList)) return 0; @@ -215,7 +222,7 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - MyCoreApplication app(argc, argv); + SDKApp<QCoreApplication> app(argc, argv); // input, if not given use current app QString input; @@ -232,7 +239,7 @@ int main(int argc, char *argv[]) } // from here, the "normal" installer binary is running - MyApplication app(argc, argv); + SDKApp<QApplication> app(argc, argv); args = app.arguments(); if (runCheck.isRunning(KDRunOnceChecker::ProcessList)) { @@ -254,11 +261,10 @@ int main(int argc, char *argv[]) qDebug() << "Resource tree before loading the in-binary resource:"; qDebug() << "Language: " << QLocale().uiLanguages().value(0, QLatin1String("No UI language set")); - QDir dir(QLatin1String(":/")); - foreach (const QString &i, dir.entryList()) { - const QByteArray ba = i.toUtf8(); - qDebug().nospace() << " :/" << ba.constData(); - } + QDirIterator it(QLatin1String(":/"), QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden, + QDirIterator::Subdirectories); + while (it.hasNext()) + qDebug() << QString::fromLatin1(" %1").arg(it.next()); } // register custom operations before reading the binary content cause they may used in @@ -295,59 +301,7 @@ int main(int argc, char *argv[]) // instantiate the installer we are actually going to use QInstaller::PackageManagerCore core(content.magicMarker(), content.performedOperations()); - - if (QInstaller::isVerbose()) { - qDebug() << "Resource tree after loading the in-binary resource:"; - - QDir dir = QDir(QLatin1String(":/")); - foreach (const QString &i, dir.entryList()) - qDebug() << QString::fromLatin1(" :/%1").arg(i); - - dir = QDir(QLatin1String(":/metadata/")); - foreach (const QString &i, dir.entryList()) - qDebug() << QString::fromLatin1(" :/metadata/%1").arg(i); - - dir = QDir(QLatin1String(":/translations/")); - foreach (const QString &i, dir.entryList()) - qDebug() << QString::fromLatin1(" :/translations/%1").arg(i); - } - - const QString directory = QLatin1String(":/translations"); - const QStringList translations = core.settings().translations(); - - // install the default Qt translator - QScopedPointer<QTranslator> translator(new QTranslator(&app)); - foreach (const QLocale locale, QLocale().uiLanguages()) { - // As there is no qt_en.qm, we simply end the search when the next - // preferred language is English. - if (locale.language() == QLocale::English) - break; - if (translator->load(locale, QLatin1String("qt"), QString::fromLatin1("_"), directory)) { - app.installTranslator(translator.take()); - break; - } - } - - translator.reset(new QTranslator(&app)); - // install English translation as fallback so that correct license button text is used - if (translator->load(QLatin1String("en_us"), directory)) - app.installTranslator(translator.take()); - - if (translations.isEmpty()) { - translator.reset(new QTranslator(&app)); - foreach (const QLocale locale, QLocale().uiLanguages()) { - if (translator->load(locale, QLatin1String(""), QLatin1String(""), directory)) { - app.installTranslator(translator.take()); - break; - } - } - } else { - foreach (const QString &translation, translations) { - translator.reset(new QTranslator(&app)); - if (translator->load(translation, QLatin1String(":/translations"))) - app.installTranslator(translator.take()); - } - } + ProductKeyCheck::instance()->init(&core); QString controlScript; QHash<QString, QString> params; @@ -413,6 +367,56 @@ int main(int argc, char *argv[]) } } + // this needs to happen after we parse the arguments, but before we use the actual resources + const QString newDefaultResource = core.value(QString::fromLatin1("DefaultResourceReplacement")); + if (!newDefaultResource.isEmpty()) + content.registerAsDefaultQResource(newDefaultResource); + + if (QInstaller::isVerbose()) { + qDebug() << "Resource tree after loading the in-binary resource:"; + QDirIterator it(QLatin1String(":/"), QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden, + QDirIterator::Subdirectories); + while (it.hasNext()) + qDebug() << QString::fromLatin1(" %1").arg(it.next()); + } + + const QString directory = QLatin1String(":/translations"); + const QStringList translations = core.settings().translations(); + + // install the default Qt translator + QScopedPointer<QTranslator> translator(new QTranslator(&app)); + foreach (const QLocale locale, QLocale().uiLanguages()) { + // As there is no qt_en.qm, we simply end the search when the next + // preferred language is English. + if (locale.language() == QLocale::English) + break; + if (translator->load(locale, QLatin1String("qt"), QString::fromLatin1("_"), directory)) { + app.installTranslator(translator.take()); + break; + } + } + + translator.reset(new QTranslator(&app)); + // install English translation as fallback so that correct license button text is used + if (translator->load(QLatin1String("en_us"), directory)) + app.installTranslator(translator.take()); + + if (translations.isEmpty()) { + translator.reset(new QTranslator(&app)); + foreach (const QLocale locale, QLocale().uiLanguages()) { + if (translator->load(locale, QLatin1String(""), QLatin1String(""), directory)) { + app.installTranslator(translator.take()); + break; + } + } + } else { + foreach (const QString &translation, translations) { + translator.reset(new QTranslator(&app)); + if (translator->load(translation, QLatin1String(":/translations"))) + app.installTranslator(translator.take()); + } + } + // Create the wizard gui TabController controller(0); controller.setManager(&core); diff --git a/src/sdk/installerbase_p.cpp b/src/sdk/installerbase_p.cpp index 6e4002f30..2c79e0dde 100644 --- a/src/sdk/installerbase_p.cpp +++ b/src/sdk/installerbase_p.cpp @@ -39,6 +39,7 @@ ** **************************************************************************/ #include "installerbase_p.h" +#include "console.h" #include <binaryformat.h> #include <errors.h> @@ -58,140 +59,14 @@ #include <QMessageBox> -#include <fstream> #include <iomanip> #include <iostream> -#ifdef Q_OS_WIN -# include <wincon.h> - -# ifndef ENABLE_INSERT_MODE -# define ENABLE_INSERT_MODE 0x0020 -# endif - -# ifndef ENABLE_QUICK_EDIT_MODE -# define ENABLE_QUICK_EDIT_MODE 0x0040 -# endif - -# ifndef ENABLE_EXTENDED_FLAGS -# define ENABLE_EXTENDED_FLAGS 0x0080 -# endif -#endif - using namespace KDUpdater; using namespace QInstaller; using namespace QInstallerCreator; -// -- MyCoreApplication - -MyCoreApplication::MyCoreApplication(int &argc, char **argv) - : QCoreApplication(argc, argv) -{ -} - -// re-implemented from QCoreApplication so we can throw exceptions in scripts and slots -bool MyCoreApplication::notify(QObject *receiver, QEvent *event) -{ - try { - return QCoreApplication::notify(receiver, event); - } catch(std::exception &e) { - qFatal("Exception thrown: %s", e.what()); - } - return false; -} - - -// -- MyApplicationConsole - -class MyApplicationConsole -{ -public: - MyApplicationConsole() - { -#ifdef Q_OS_WIN - AllocConsole(); - - HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); - if (handle != INVALID_HANDLE_VALUE) { - COORD largestConsoleWindowSize = GetLargestConsoleWindowSize(handle); - largestConsoleWindowSize.X -= 3; - largestConsoleWindowSize.Y = 5000; - SetConsoleScreenBufferSize(handle, largestConsoleWindowSize); - } - - handle = GetStdHandle(STD_INPUT_HANDLE); - if (handle != INVALID_HANDLE_VALUE) - SetConsoleMode(handle, ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS); - - m_oldCin = std::cin.rdbuf(); - m_newCin.open("CONIN$"); - std::cin.rdbuf(m_newCin.rdbuf()); - - m_oldCout = std::cout.rdbuf(); - m_newCout.open("CONOUT$"); - std::cout.rdbuf(m_newCout.rdbuf()); - - m_oldCerr = std::cerr.rdbuf(); - m_newCerr.open("CONOUT$"); - std::cerr.rdbuf(m_newCerr.rdbuf()); -#endif - } - ~MyApplicationConsole() - { -#ifdef Q_OS_WIN - system("PAUSE"); - - std::cin.rdbuf(m_oldCin); - std::cerr.rdbuf(m_oldCerr); - std::cout.rdbuf(m_oldCout); - - FreeConsole(); -#endif - } - -private: - std::ifstream m_newCin; - std::ofstream m_newCout; - std::ofstream m_newCerr; - - std::streambuf* m_oldCin; - std::streambuf* m_oldCout; - std::streambuf* m_oldCerr; -}; - - -// -- MyApplication - -MyApplication::MyApplication(int &argc, char **argv) - : QApplication(argc, argv) - , m_console(0) -{ -} - -MyApplication::~MyApplication() -{ - delete m_console; -} - -void MyApplication::setVerbose() -{ - if (!m_console) - m_console = new MyApplicationConsole; -} - -// re-implemented from QApplication so we can throw exceptions in scripts and slots -bool MyApplication::notify(QObject *receiver, QEvent *event) -{ - try { - return QApplication::notify(receiver, event); - } catch(std::exception &e) { - qFatal("Exception thrown: %s", e.what()); - } - return false; -} - - // -- InstallerBase InstallerBase::InstallerBase(QObject *parent) @@ -300,7 +175,7 @@ void InstallerBase::showUsage() { #define WIDTH1 46 #define WIDTH2 40 - MyApplicationConsole c; + Console c; std::cout << "Usage: SDKMaintenanceTool [OPTIONS]" << std::endl << std::endl; std::cout << "User:"<<std::endl; @@ -366,7 +241,7 @@ void InstallerBase::showUsage() /* static*/ void InstallerBase::showVersion(const QString &version) { - MyApplicationConsole c; + Console c; std::cout << qPrintable(version) << std::endl; } diff --git a/src/sdk/installerbase_p.h b/src/sdk/installerbase_p.h index cd6ed0142..5d3e66e31 100644 --- a/src/sdk/installerbase_p.h +++ b/src/sdk/installerbase_p.h @@ -39,8 +39,10 @@ ** **************************************************************************/ +#ifndef INSTALLERBASE_P_H +#define INSTALLERBASE_P_H + #include <QThread> -#include <QApplication> namespace KDUpdater { class FileDownloader; @@ -50,8 +52,6 @@ QT_BEGIN_NAMESPACE class QFile; QT_END_NAMESPACE -class MyApplicationConsole; - class Sleep : public QThread { public: @@ -89,22 +89,4 @@ private: QScopedPointer<KDUpdater::FileDownloader> m_downloader; }; -class MyCoreApplication : public QCoreApplication -{ -public: - MyCoreApplication(int &argc, char **argv); - virtual bool notify(QObject *receiver, QEvent *event); -}; - -class MyApplication : public QApplication -{ -public: - MyApplication(int &argc, char **argv); - ~MyApplication(); - - void setVerbose(); - virtual bool notify(QObject *receiver, QEvent *event); - -private: - MyApplicationConsole *m_console; -}; +#endif // INSTALLERBASE_P_H diff --git a/src/sdk/installerbasecommons.cpp b/src/sdk/installerbasecommons.cpp index d2fb5e27b..0cf85a0ec 100644 --- a/src/sdk/installerbasecommons.cpp +++ b/src/sdk/installerbasecommons.cpp @@ -43,6 +43,7 @@ #include <component.h> #include <messageboxhandler.h> #include <packagemanagercore.h> +#include <packagemanagerpagefactory.h> #include <settings.h> #include <productkeycheck.h> @@ -75,16 +76,19 @@ IntroductionPageImpl::IntroductionPageImpl(QInstaller::PackageManagerCore *core) QVBoxLayout *layout = new QVBoxLayout(widget); m_packageManager = new QRadioButton(tr("Package manager"), this); + m_packageManager->setObjectName(QLatin1String("PackageManagerRadioButton")); layout->addWidget(m_packageManager); m_packageManager->setChecked(core->isPackageManager()); connect(m_packageManager, SIGNAL(toggled(bool)), this, SLOT(setPackageManager(bool))); m_updateComponents = new QRadioButton(tr("Update components"), this); + m_updateComponents->setObjectName(QLatin1String("UpdaterRadioButton")); layout->addWidget(m_updateComponents); m_updateComponents->setChecked(core->isUpdater()); connect(m_updateComponents, SIGNAL(toggled(bool)), this, SLOT(setUpdater(bool))); m_removeAllComponents = new QRadioButton(tr("Remove all components"), this); + m_removeAllComponents->setObjectName(QLatin1String("UninstallerRadioButton")); layout->addWidget(m_removeAllComponents); m_removeAllComponents->setChecked(core->isUninstaller()); connect(m_removeAllComponents, SIGNAL(toggled(bool)), this, SLOT(setUninstaller(bool))); @@ -336,6 +340,7 @@ void IntroductionPageImpl::entering() showMaintenanceTools(); setMaintenanceToolsEnabled(true); } + setSettingsButtonRequested((!core->isOfflineOnly()) && (!core->isUninstaller())); } void IntroductionPageImpl::leaving() @@ -499,6 +504,13 @@ bool TargetDirectoryPageImpl::validatePage() InstallerGui::InstallerGui(PackageManagerCore *core) : PackageManagerGui(core, 0) { + ProductKeyCheck *checker = ProductKeyCheck::instance(); + foreach (const int id, checker->registeredPages()) { + PackageManagerPage *page = PackageManagerPageFactory::instance().create(id, core); + Q_ASSERT_X(page, Q_FUNC_INFO, qPrintable(QString::fromLatin1("Page with %1 couldn't be " + "constructed.").arg(id))); + setPage(id, page); + } setPage(PackageManagerCore::Introduction, new IntroductionPageImpl(core)); setPage(PackageManagerCore::TargetDirectory, new TargetDirectoryPageImpl(core)); setPage(PackageManagerCore::ComponentSelection, new ComponentSelectionPage(core)); @@ -521,6 +533,14 @@ void InstallerGui::init() MaintenanceGui::MaintenanceGui(PackageManagerCore *core) : PackageManagerGui(core, 0) { + ProductKeyCheck *checker = ProductKeyCheck::instance(); + foreach (const int id, checker->registeredPages()) { + PackageManagerPage *page = PackageManagerPageFactory::instance().create(id, core); + Q_ASSERT_X(page, Q_FUNC_INFO, qPrintable(QString::fromLatin1("Page with %1 couldn't be " + "constructed.").arg(id))); + setPage(id, page); + } + IntroductionPageImpl *intro = new IntroductionPageImpl(core); connect(intro, SIGNAL(packageManagerCoreTypeChanged()), this, SLOT(updateRestartPage())); diff --git a/src/sdk/sdk.pro b/src/sdk/sdk.pro index 8b428fe48..b2588603b 100644 --- a/src/sdk/sdk.pro +++ b/src/sdk/sdk.pro @@ -76,7 +76,9 @@ FORMS += settingsdialog.ui HEADERS += installerbase_p.h \ tabcontroller.h \ installerbasecommons.h \ - settingsdialog.h + settingsdialog.h \ + console.h \ + sdkapp.h SOURCES = installerbase.cpp \ installerbase_p.cpp \ diff --git a/src/sdk/sdkapp.h b/src/sdk/sdkapp.h new file mode 100644 index 000000000..f00f7b67b --- /dev/null +++ b/src/sdk/sdkapp.h @@ -0,0 +1,84 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef SDKAPP_H +#define SDKAPP_H + +#include "console.h" + +#include <QApplication> + +template<class T> +class SDKApp : public T +{ +public: + SDKApp(int argc, char** argv) + : T(argc, argv) + , m_console(0) + { + } + + virtual ~SDKApp() + { + delete m_console; + } + + void setVerbose() + { + if (!m_console) + m_console = new Console; + } + + virtual bool notify(QObject *receiver, QEvent *event) + { + try { + return T::notify(receiver, event); + } catch (std::exception &e) { + qFatal("Exception thrown: %s", e.what()); + } + return false; + } + +private: + Console *m_console; +}; + +#endif // SDKAPP_H diff --git a/src/sdk/settingsdialog.cpp b/src/sdk/settingsdialog.cpp index 1a7903403..305fc051a 100644 --- a/src/sdk/settingsdialog.cpp +++ b/src/sdk/settingsdialog.cpp @@ -42,8 +42,6 @@ #include "settingsdialog.h" #include "ui_settingsdialog.h" -#include <kdupdaterfiledownloader.h> -#include <kdupdaterfiledownloaderfactory.h> #include <packagemanagercore.h> #include <productkeycheck.h> @@ -57,130 +55,6 @@ using namespace QInstaller; - -// -- TestRepositoryJob - -TestRepository::TestRepository(QObject *parent) - : KDJob(parent) - , m_downloader(0) -{ - setTimeout(10000); - setAutoDelete(false); - setCapabilities(Cancelable); -} - -TestRepository::~TestRepository() -{ - if (m_downloader) - m_downloader->deleteLater(); -} - -Repository TestRepository::repository() const -{ - return m_repository; -} - -void TestRepository::setRepository(const Repository &repository) -{ - cancel(); - - setError(NoError); - setErrorString(QString()); - m_repository = repository; -} - -void TestRepository::doStart() -{ - if (m_downloader) - m_downloader->deleteLater(); - - 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())); - 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"))); - - m_downloader->download(); -} - -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); - } -} - -void TestRepository::downloadCompleted() -{ - QString errorMsg; - int error = DownloadError; - - if (m_downloader->isDownloaded()) { - QFile file(m_downloader->downloadedFileName()); - if (file.exists() && 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); - } else { - error = NoError; - } - } else { - errorMsg = tr("Updates.xml could not be opened for reading!"); - } - } else { - errorMsg = tr("Updates.xml could not be found on server!"); - } - - if (error > NoError) - emitFinishedWithError(error, errorMsg); - else - emitFinished(); - - m_downloader->deleteLater(); - m_downloader = 0; -} - -void TestRepository::downloadAborted(const QString &reason) -{ - emitFinishedWithError(DownloadError, reason); -} - -void TestRepository::onAuthenticatorChanged(const QAuthenticator &authenticator) -{ - m_repository.setUsername(authenticator.user()); - m_repository.setPassword(authenticator.password()); -} - - // -- PasswordDelegate void PasswordDelegate::showPasswords(bool show) @@ -576,6 +450,6 @@ void SettingsDialog::insertRepositories(const QSet<Repository> repos, QTreeWidge foreach (const Repository &repo, repos) { RepositoryItem *item = new RepositoryItem(repo); rootItem->addChild(item); - item->setHidden(!ProductKeyCheck::instance(m_core)->isValidRepository(repo)); + item->setHidden(!ProductKeyCheck::instance()->isValidRepository(repo)); } } diff --git a/src/sdk/settingsdialog.h b/src/sdk/settingsdialog.h index 1a6633c67..a2386acbb 100644 --- a/src/sdk/settingsdialog.h +++ b/src/sdk/settingsdialog.h @@ -43,8 +43,7 @@ #include <repository.h> #include <settings.h> - -#include <kdjob.h> +#include <testrepository.h> #include <QDialog> #include <QStyledItemDelegate> @@ -56,10 +55,6 @@ class QLocale; class QVariant; QT_END_NAMESPACE -namespace KDUpdater { - class FileDownloader; -} - namespace QInstaller { class PackageManagerCore; } @@ -68,36 +63,6 @@ namespace Ui { class SettingsDialog; } - -// -- TestRepositoryJob - -class TestRepository : public KDJob -{ - Q_OBJECT - -public: - - explicit TestRepository(QObject *parent = 0); - ~TestRepository(); - - QInstaller::Repository repository() const; - void setRepository(const QInstaller::Repository &repository); - -private: - void doStart(); - void doCancel(); - -private Q_SLOTS: - void downloadCompleted(); - void downloadAborted(const QString &reason); - void onAuthenticatorChanged(const QAuthenticator &authenticator); - -private: - QInstaller::Repository m_repository; - KDUpdater::FileDownloader *m_downloader; -}; - - // -- PasswordDelegate class PasswordDelegate : public QStyledItemDelegate @@ -177,7 +142,7 @@ private: QInstaller::PackageManagerCore *m_core; bool m_showPasswords; - TestRepository m_testRepository; + QInstaller::TestRepository m_testRepository; QList<QTreeWidgetItem*> m_rootItems; }; diff --git a/src/sdk/tabcontroller.cpp b/src/sdk/tabcontroller.cpp index 720f6f292..d0e322251 100644 --- a/src/sdk/tabcontroller.cpp +++ b/src/sdk/tabcontroller.cpp @@ -124,10 +124,6 @@ void TabController::setManagerParams(const QHash<QString, QString> ¶ms) int TabController::init() { - if (!ProductKeyCheck::instance()->hasValidKey() && d->m_core->isInstaller()) { - return PackageManagerCore::Failure; - } - if (!d->m_init) { d->m_init = true; // this should called as early as possible, to handle error message boxes for example @@ -150,7 +146,6 @@ int TabController::init() } d->m_gui->restart(); - d->m_gui->setWindowModality(Qt::WindowModal); d->m_gui->show(); onCurrentIdChanged(d->m_gui->currentId()); @@ -201,9 +196,9 @@ void TabController::onSettingsButtonClicked() void TabController::onCurrentIdChanged(int newId) { - if (d->m_gui && d->m_core) { - d->m_gui->showSettingsButton((newId == PackageManagerCore::Introduction) & - (!d->m_core->isOfflineOnly()) & (!d->m_core->isUninstaller())); + if (d->m_gui) { + if (PackageManagerPage *page = d->m_gui->page(newId)) + d->m_gui->showSettingsButton(page->settingsButtonRequested()); } } diff --git a/src/sdk/translations/ja_jp.ts b/src/sdk/translations/ja_jp.ts index 5e34e57e6..6af882705 100644 --- a/src/sdk/translations/ja_jp.ts +++ b/src/sdk/translations/ja_jp.ts @@ -99,7 +99,7 @@ <translation>無効な引数: %1個の引数が渡されましたが、必要なのは2個です。</translation> </message> <message> - <source>Could not copy a none existing file: %1</source> + <source>Could not copy a non-existent file: %1</source> <translation>存在しないファイルはコピーできません: %1</translation> </message> <message> |