diff options
author | kh1 <qt-info@nokia.com> | 2011-03-30 15:18:21 +0200 |
---|---|---|
committer | kh1 <qt-info@nokia.com> | 2011-03-30 15:18:21 +0200 |
commit | 5fb9e4cd8488e67315df18fad585dedf3aeb9be8 (patch) | |
tree | ee98c73d6e91a5498ef8dd3fc8e8f1085b30ba70 | |
parent | a5507f265067a1268b29a204bf356d1951dc3be6 (diff) | |
parent | ca229bc660b7367c94022aea8fa8fc7b4c5b38dd (diff) |
Merge branch 'master' into refactor
Conflicts:
examples/testapp/testapp.pro
installerbuilder/installerbase/installerbasecommons.cpp
installerbuilder/libinstaller/qinstaller.cpp
installerbuilder/tests/tests.pro
-rw-r--r-- | installerbuilder/common/installersettings.cpp | 7 | ||||
-rw-r--r-- | installerbuilder/common/installersettings.h | 1 | ||||
-rw-r--r-- | installerbuilder/common/utils.cpp | 17 | ||||
-rw-r--r-- | installerbuilder/installerbase/installerbasecommons.cpp | 11 | ||||
-rw-r--r-- | installerbuilder/libinstaller/elevatedexecuteoperation.cpp | 112 | ||||
-rw-r--r-- | installerbuilder/libinstaller/elevatedexecuteoperation.h | 9 | ||||
-rw-r--r-- | installerbuilder/libinstaller/init.cpp | 2 | ||||
-rw-r--r-- | installerbuilder/libinstaller/libinstaller.pro | 5 | ||||
-rw-r--r-- | installerbuilder/libinstaller/persistentsettings.cpp | 216 | ||||
-rw-r--r-- | installerbuilder/libinstaller/persistentsettings.h | 76 | ||||
-rw-r--r-- | installerbuilder/libinstaller/projectexplorer_export.h | 1 | ||||
-rw-r--r-- | installerbuilder/libinstaller/qinstaller_p.cpp | 34 | ||||
-rw-r--r-- | installerbuilder/libinstaller/qinstallergui.cpp | 4 | ||||
-rw-r--r-- | installerbuilder/libinstaller/registertoolchainoperation.cpp | 187 | ||||
-rw-r--r-- | installerbuilder/libinstaller/registertoolchainoperation.h | 65 |
15 files changed, 690 insertions, 57 deletions
diff --git a/installerbuilder/common/installersettings.cpp b/installerbuilder/common/installersettings.cpp index 7f104c4f6..19f3eeb25 100644 --- a/installerbuilder/common/installersettings.cpp +++ b/installerbuilder/common/installersettings.cpp @@ -68,6 +68,7 @@ public: QString targetDir; QString adminTargetDir; QString icon; + QString removeTargetDir; QString uninstallerName; QString uninstallerIniFile; QString configurationFileName; @@ -163,6 +164,7 @@ InstallerSettings InstallerSettings::fromFileAndPrefix( const QString& path, con s.d->targetDir = readChild( root, QLatin1String("TargetDir") ); s.d->adminTargetDir = readChild( root, QLatin1String("AdminTargetDir") ); s.d->icon = readChild( root, QLatin1String( "Icon" ) ); + s.d->removeTargetDir = readChild(root, QLatin1String("RemoveTargetDir"), QLatin1String("true")); s.d->uninstallerName = readChild( root, QLatin1String( "UninstallerName" ), QLatin1String("uninstall") ); s.d->uninstallerIniFile = readChild( root, QLatin1String("UninstallerIniFile"), s.d->uninstallerName + QLatin1String(".ini") ); s.d->privateKey = splitTrimmed( readChild( root, QLatin1String( "PrivateKey" ) ) ).toLatin1(); @@ -256,6 +258,11 @@ QString InstallerSettings::icon() const #endif } +QString InstallerSettings::removeTargetDir() const +{ + return d->removeTargetDir; +} + QString InstallerSettings::uninstallerName() const { if( d->uninstallerName.isEmpty() ) diff --git a/installerbuilder/common/installersettings.h b/installerbuilder/common/installersettings.h index d73049345..939d35f00 100644 --- a/installerbuilder/common/installersettings.h +++ b/installerbuilder/common/installersettings.h @@ -70,6 +70,7 @@ namespace QInstaller { QString targetDir() const; QString adminTargetDir() const; + QString removeTargetDir() const; QString uninstallerName() const; QString uninstallerIniFile() const; diff --git a/installerbuilder/common/utils.cpp b/installerbuilder/common/utils.cpp index 31d92f6be..e4460bd4c 100644 --- a/installerbuilder/common/utils.cpp +++ b/installerbuilder/common/utils.cpp @@ -192,14 +192,15 @@ QInstaller::VerboseWriter::~VerboseWriter() return; } QFile output(logFileName); - if (!output.open(QIODevice::ReadWrite | QIODevice::Append)) - qFatal("Could not open logfile!"); - QString logInfo; - logInfo += QLatin1String("*************************************"); - logInfo += QString::fromLatin1("Invoked:") + QDateTime::currentDateTime().toString(); - output.write(logInfo.toLocal8Bit()); - output.write(preFileBuffer.data()); - output.close(); + if (output.open(QIODevice::ReadWrite | QIODevice::Append)) { + QString logInfo; + logInfo += QLatin1String("*************************************"); + logInfo += QString::fromLatin1("Invoked:") + QDateTime::currentDateTime().toString(); + output.write(logInfo.toLocal8Bit()); + output.write(preFileBuffer.data()); + output.close(); + } + stream.setDevice(0); } void QInstaller::VerboseWriter::setOutputStream(const QString &fileName) diff --git a/installerbuilder/installerbase/installerbasecommons.cpp b/installerbuilder/installerbase/installerbasecommons.cpp index c82574d5a..cb29359bb 100644 --- a/installerbuilder/installerbase/installerbasecommons.cpp +++ b/installerbuilder/installerbase/installerbasecommons.cpp @@ -225,6 +225,17 @@ bool TargetDirectoryPageImpl::validatePage() if (!isVisible()) return true; + if (targetDir().isEmpty()) { + MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), + QLatin1String("forbiddenTargetDirectory"), tr("Error"), + tr( "The install directory cannot be empty, please specify a valid folder"), QMessageBox::Ok); + return false; + } + + QString remove = installer()->value(QLatin1String("RemoveTargetDir")); + if (!QVariant(remove).toBool()) + return true; + if (QFileInfo(targetDir()).isDir()) { QFileInfo fi2(targetDir() + QDir::separator() + installer()->uninstallerName()); if (QDir(targetDir()) == QDir::root()) { diff --git a/installerbuilder/libinstaller/elevatedexecuteoperation.cpp b/installerbuilder/libinstaller/elevatedexecuteoperation.cpp index c255a28af..b333bf7da 100644 --- a/installerbuilder/libinstaller/elevatedexecuteoperation.cpp +++ b/installerbuilder/libinstaller/elevatedexecuteoperation.cpp @@ -58,6 +58,7 @@ private: public: void readProcessOutput(); + bool run(const QStringList& arguments); QProcessWrapper* process; bool showStandardError; @@ -78,14 +79,26 @@ bool ElevatedExecuteOperation::performOperation() { // This operation receives only one argument. It is the complete // command line of the external program to execute. - QStringList args = arguments(); - if( args.isEmpty() ) + if( arguments().isEmpty() ) { setError( InvalidArguments ); - setErrorString( tr("Invalid arguments in %1: %2 arguments given, at least 1 expected.").arg( name(), QString::number( args.count() ) ) ); + setErrorString( tr("Invalid arguments in %1: %2 arguments given, at least 1 expected.").arg( name(), QString::number( arguments().count() ) ) ); return false; } + QStringList args; + foreach(const QString &argument, arguments()) { + if (argument!=QLatin1String("UNDOEXECUTE")) + args.append(argument); + else + break; //we don't need the UNDOEXECUTE args here + } + + return d->run(args); +} +bool ElevatedExecuteOperation::Private::run(const QStringList& arguments) +{ + QStringList args = arguments; QString workingDirectory; QStringList filteredWorkingDirectoryArgs = args.filter(QLatin1String("workingdirectory="), Qt::CaseInsensitive); if (!filteredWorkingDirectoryArgs.isEmpty()) { @@ -97,7 +110,7 @@ bool ElevatedExecuteOperation::performOperation() if ( args.last().endsWith( QLatin1String("showStandardError") ) ) { - d->showStandardError = true; + showStandardError = true; args.pop_back(); } @@ -124,87 +137,87 @@ bool ElevatedExecuteOperation::performOperation() args.pop_back(); const bool success = QProcess::startDetached( args.front(), args.mid( 1 ) ); if ( !success ) { - setError( UserDefinedError ); - setErrorString( tr( "Execution failed: Could not start detached: \"%1\"" ).arg( callstr ) ); + q->setError( UserDefinedError ); + q->setErrorString( tr( "Execution failed: Could not start detached: \"%1\"" ).arg( callstr ) ); } return success; } - d->process = new QProcessWrapper(); + process = new QProcessWrapper(); if (!workingDirectory.isEmpty()) { - d->process->setWorkingDirectory( workingDirectory ); + process->setWorkingDirectory( workingDirectory ); QInstaller::verbose() << " ElevatedExecuteOperation setWorkingDirectory: " << workingDirectory << std::endl; } QProcessEnvironment penv; //there is no way to serialize a QProcessEnvironment properly other than per mangled QStringList :/ (i.e. no other way to list all keys) - d->process->setEnvironment( KDUpdater::Environment::instance()->applyTo( penv ).toStringList() ); + process->setEnvironment( KDUpdater::Environment::instance()->applyTo( penv ).toStringList() ); - if (d->showStandardError) - d->process->setProcessChannelMode(QProcess::MergedChannels); + if (showStandardError) + process->setProcessChannelMode(QProcess::MergedChannels); - connect(this, SIGNAL(cancelProcess()), d->process, SLOT(cancel())); + connect(q, SIGNAL(cancelProcess()), process, SLOT(cancel())); //we still like the none blocking possibility to perform this operation without threads QEventLoop loop; if (QThread::currentThread() == qApp->thread()) { - QObject::connect( d->process, SIGNAL( finished( int, QProcess::ExitStatus ) ), &loop, SLOT( quit() ) ); + QObject::connect( process, SIGNAL( finished( int, QProcess::ExitStatus ) ), &loop, SLOT( quit() ) ); } //readProcessOutput should only called from this current Thread -> Qt::DirectConnection - QObject::connect( d->process, SIGNAL( readyRead() ), this, SLOT( readProcessOutput() ), Qt::DirectConnection ); + QObject::connect( process, SIGNAL( readyRead() ), q, SLOT( readProcessOutput() ), Qt::DirectConnection ); #ifdef Q_OS_WIN if (args.count() == 1) { - d->process->setNativeArguments( args.front() ); + process->setNativeArguments( args.front() ); QInstaller::verbose() << " ElevatedExecuteOperation setNativeArguments to start: " << args.front() << std::endl; - d->process->start(QString(), QStringList()); + process->start(QString(), QStringList()); } else #endif - d->process->start( args.front(), args.mid( 1 ) ); + process->start( args.front(), args.mid( 1 ) ); QInstaller::verbose() << args.front() << " started, arguments: " << QStringList(args.mid( 1 )).join(QLatin1String(" ")) << std::endl; bool success = false; //we still like the none blocking possibility to perform this operation without threads if (QThread::currentThread() == qApp->thread()) { - success = d->process->waitForStarted(); + success = process->waitForStarted(); } else { - success = d->process->waitForFinished(-1); + success = process->waitForFinished(-1); } bool returnValue = true; if ( !success ) { - setError( UserDefinedError ); + q->setError( UserDefinedError ); //TODO: pass errorString() through the wrapper */ - setErrorString( tr( "Execution failed: Could not start: \"%1\"" ).arg( callstr ) ); + q->setErrorString( tr( "Execution failed: Could not start: \"%1\"" ).arg( callstr ) ); returnValue = false; } if (QThread::currentThread() == qApp->thread()) { - if (d->process->state() != QProcess::NotRunning) { + if (process->state() != QProcess::NotRunning) { loop.exec(); } - d->readProcessOutput(); + readProcessOutput(); } - setValue( QLatin1String( "ExitCode" ), d->process->exitCode() ); + q->setValue( QLatin1String( "ExitCode" ), process->exitCode() ); - if ( d->process->exitStatus() == QProcess::CrashExit ) + if ( process->exitStatus() == QProcess::CrashExit ) { - setError( UserDefinedError ); - setErrorString( tr( "Execution failed (Crash): \"%1\"" ).arg( callstr ) ); + q->setError( UserDefinedError ); + q->setErrorString( tr( "Execution failed (Crash): \"%1\"" ).arg( callstr ) ); returnValue = false; } - if ( !allowedExitCodes.contains( d->process->exitCode() ) ) + if ( !allowedExitCodes.contains( process->exitCode() ) ) { - setError( UserDefinedError ); - setErrorString( tr( "Execution failed (Unexpected exit code: %1): \"%2\"" ).arg( QString::number( d->process->exitCode() ), callstr ) ); + q->setError( UserDefinedError ); + q->setErrorString( tr( "Execution failed (Unexpected exit code: %1): \"%2\"" ).arg( QString::number( process->exitCode() ), callstr ) ); returnValue = false; } - Q_ASSERT(d->process); - d->process->deleteLater(); - d->process = 0; + Q_ASSERT(process); + process->deleteLater(); + process = 0; return returnValue; } @@ -232,4 +245,37 @@ void ElevatedExecuteOperation::Private::readProcessOutput() } } + +bool ElevatedExecuteOperation::undoOperation() +{ + QStringList args; + bool found = false; + foreach(const QString &argument, arguments()) { + if (found) + args.append(argument); + else + found = argument==QLatin1String("UNDOEXECUTE"); + } + if (args.isEmpty()) + return true; + + return d->run(args); +} + +bool ElevatedExecuteOperation::testOperation() +{ + // TODO + return true; +} + +ElevatedExecuteOperation* ElevatedExecuteOperation::clone() const +{ + return new ElevatedExecuteOperation; +} + +void ElevatedExecuteOperation::backup() +{ +} + + #include "moc_elevatedexecuteoperation.cpp" diff --git a/installerbuilder/libinstaller/elevatedexecuteoperation.h b/installerbuilder/libinstaller/elevatedexecuteoperation.h index 6fcb5e8de..35cb84afd 100644 --- a/installerbuilder/libinstaller/elevatedexecuteoperation.h +++ b/installerbuilder/libinstaller/elevatedexecuteoperation.h @@ -33,17 +33,22 @@ namespace QInstaller { -class INSTALLER_EXPORT ElevatedExecuteOperation : public KDUpdater::ExecuteOperation +class INSTALLER_EXPORT ElevatedExecuteOperation : public QObject, public KDUpdater::UpdateOperation { Q_OBJECT public: ElevatedExecuteOperation(); ~ElevatedExecuteOperation(); - bool performOperation(); + virtual void backup(); + virtual bool performOperation(); + virtual bool undoOperation(); + virtual bool testOperation(); + virtual ElevatedExecuteOperation* clone() const; Q_SIGNALS: void cancelProcess(); + void outputTextChanged(const QString &text); public Q_SLOTS: void cancelOperation(); diff --git a/installerbuilder/libinstaller/init.cpp b/installerbuilder/libinstaller/init.cpp index 07512808a..df4f89477 100644 --- a/installerbuilder/libinstaller/init.cpp +++ b/installerbuilder/libinstaller/init.cpp @@ -57,6 +57,7 @@ #include "registerqtoperation.h" #include "setqtcreatorvalueoperation.h" #include "simplemovefileoperation.h" +#include "registertoolchainoperation.h" #include "minimumprogressoperation.h" @@ -175,6 +176,7 @@ void QInstaller::init() KDUpdater::UpdateOperationFactory::instance().registerUpdateOperation< QInstaller::CopyDirectoryOperation >( QLatin1String( "CopyDirectory") ); KDUpdater::UpdateOperationFactory::instance().registerUpdateOperation< QInstaller::RegisterDocumentationOperation >( QLatin1String( "RegisterDocumentation") ); KDUpdater::UpdateOperationFactory::instance().registerUpdateOperation< QInstaller::RegisterQtInCreatorOperation>( QLatin1String( "RegisterQtInCreator") ); + KDUpdater::UpdateOperationFactory::instance().registerUpdateOperation< QInstaller::RegisterToolChainOperation>( QLatin1String( "RegisterToolChain") ); KDUpdater::UpdateOperationFactory::instance().registerUpdateOperation< QInstaller::SetDemosPathOnQtOperation>( QLatin1String( "SetDemosPathOnQt") ); KDUpdater::UpdateOperationFactory::instance().registerUpdateOperation< QInstaller::SetExamplesPathOnQtOperation>( QLatin1String( "SetExamplesPathOnQt") ); KDUpdater::UpdateOperationFactory::instance().registerUpdateOperation< QInstaller::SetPluginPathOnQtCoreOperation>( QLatin1String( "SetPluginPathOnQtCore") ); diff --git a/installerbuilder/libinstaller/libinstaller.pro b/installerbuilder/libinstaller/libinstaller.pro index 21a55dea0..04832f902 100644 --- a/installerbuilder/libinstaller/libinstaller.pro +++ b/installerbuilder/libinstaller/libinstaller.pro @@ -48,6 +48,8 @@ HEADERS += $$PWD/qinstaller.h \ qinstallercomponentmodel.h \ qinstallerglobal.h \ qtpatch.h \ + persistentsettings.h \ + projectexplorer_export.h \ qtpatchoperation.h \ setdemospathonqtoperation.h \ setexamplespathonqtoperation.h \ @@ -57,6 +59,7 @@ HEADERS += $$PWD/qinstaller.h \ linereplaceoperation.h \ registerdocumentationoperation.h \ registerqtoperation.h \ + registertoolchainoperation.h \ setqtcreatorvalueoperation.h \ copydirectoryoperation.h \ simplemovefileoperation.h \ @@ -111,6 +114,7 @@ SOURCES += $$PWD/qinstaller.cpp \ qinstallercomponent.cpp \ qinstallercomponentmodel.cpp \ qtpatch.cpp \ + persistentsettings.cpp \ qtpatchoperation.cpp \ setdemospathonqtoperation.cpp \ setexamplespathonqtoperation.cpp \ @@ -120,6 +124,7 @@ SOURCES += $$PWD/qinstaller.cpp \ linereplaceoperation.cpp \ registerdocumentationoperation.cpp \ registerqtoperation.cpp \ + registertoolchainoperation.cpp \ setqtcreatorvalueoperation.cpp \ copydirectoryoperation.cpp \ simplemovefileoperation.cpp \ diff --git a/installerbuilder/libinstaller/persistentsettings.cpp b/installerbuilder/libinstaller/persistentsettings.cpp new file mode 100644 index 000000000..16131c228 --- /dev/null +++ b/installerbuilder/libinstaller/persistentsettings.cpp @@ -0,0 +1,216 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "persistentsettings.h" + +#include <QtCore/QDebug> +#include <QtCore/QFile> +#include <QtCore/QVariant> +#include <QtXml/QDomDocument> +#include <QtXml/QDomCDATASection> +#include <QtXml/QDomElement> + + +using namespace ProjectExplorer; + +PersistentSettingsReader::PersistentSettingsReader() +{ + +} + +QVariant PersistentSettingsReader::restoreValue(const QString & variable) const +{ + if (m_valueMap.contains(variable)) + return m_valueMap.value(variable); + return QVariant(); +} + +QVariantMap PersistentSettingsReader::restoreValues() const +{ + return m_valueMap; +} + +bool PersistentSettingsReader::load(const QString & fileName) +{ + m_valueMap.clear(); + + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly)) + return false; + + QDomDocument doc; + if (!doc.setContent(&file)) + return false; + + QDomElement root = doc.documentElement(); + if (root.nodeName() != QLatin1String("qtcreator")) + return false; + + QDomElement child = root.firstChildElement(); + for (; !child.isNull(); child = child.nextSiblingElement()) { + if (child.nodeName() == QLatin1String("data")) + readValues(child); + } + + file.close(); + return true; +} + +QVariant PersistentSettingsReader::readValue(const QDomElement &valElement) const +{ + QString name = valElement.nodeName(); + QString type = valElement.attribute(QLatin1String("type")); + QVariant v; + + if (name == QLatin1String("value")) { + if(type == QLatin1String("QChar")) { + //Workaround: QTBUG-12345 + v.setValue(QChar(valElement.text().at(0))); + } else { + v.setValue(valElement.text()); + v.convert(QVariant::nameToType(type.toLatin1().data())); + } + } else if (name == QLatin1String("valuelist")) { + QDomElement child = valElement.firstChildElement(); + QList<QVariant> valList; + for (; !child.isNull(); child = child.nextSiblingElement()) { + valList << readValue(child); + } + v.setValue(valList); + } else if (name == QLatin1String("valuemap")) { + QDomElement child = valElement.firstChildElement(); + QMap<QString, QVariant> valMap; + for (; !child.isNull(); child = child.nextSiblingElement()) { + QString key = child.attribute(QLatin1String("key")); + valMap.insert(key, readValue(child)); + } + v.setValue(valMap); + } + + return v; +} + +void PersistentSettingsReader::readValues(const QDomElement &data) +{ + QString variable; + QVariant v; + + QDomElement child = data.firstChildElement(); + for (; !child.isNull(); child = child.nextSiblingElement()) { + if (child.nodeName() == QLatin1String("variable")) { + variable = child.text(); + } else { + v = readValue(child); + } + } + + m_valueMap.insert(variable, v); +} + +/// +/// PersistentSettingsWriter +/// + +PersistentSettingsWriter::PersistentSettingsWriter() +{ + +} + +void PersistentSettingsWriter::writeValue(QDomElement &ps, const QVariant &variant) +{ + if (variant.type() == QVariant::StringList || variant.type() == QVariant::List) { + QDomElement values = ps.ownerDocument().createElement(QLatin1String("valuelist")); + values.setAttribute(QLatin1String("type"), QLatin1String(QVariant::typeToName(QVariant::List))); + QList<QVariant> varList = variant.toList(); + foreach (const QVariant &var, varList) { + writeValue(values, var); + } + ps.appendChild(values); + } else if (variant.type() == QVariant::Map) { + QDomElement values = ps.ownerDocument().createElement(QLatin1String("valuemap")); + values.setAttribute(QLatin1String("type"), QLatin1String(QVariant::typeToName(QVariant::Map))); + + QMap<QString, QVariant> varMap = variant.toMap(); + QMap<QString, QVariant>::const_iterator i = varMap.constBegin(); + while (i != varMap.constEnd()) { + writeValue(values, i.value()); + values.lastChild().toElement(). + setAttribute(QLatin1String("key"), i.key()); + ++i; + } + + ps.appendChild(values); + } else { + QDomElement value = ps.ownerDocument().createElement(QLatin1String("value")); + ps.appendChild(value); + QDomText valueText = ps.ownerDocument().createTextNode(variant.toString()); + value.appendChild(valueText); + value.setAttribute(QLatin1String("type"), QLatin1String(variant.typeName())); + ps.appendChild(value); + } +} + +void PersistentSettingsWriter::saveValue(const QString & variable, const QVariant &value) +{ + m_valueMap[variable] = value; +} + +bool PersistentSettingsWriter::save(const QString & fileName, const QString & docType) +{ + QFile file(fileName); + if (!file.open(QIODevice::WriteOnly)) + return false; + + QDomDocument doc(docType); + + QDomElement root = doc.createElement(QLatin1String("qtcreator")); + doc.appendChild(root); + + QMap<QString, QVariant>::const_iterator i = m_valueMap.constBegin(); + while (i != m_valueMap.constEnd()) { + QDomElement ps = doc.createElement(QLatin1String("data")); + root.appendChild(ps); + + QDomElement variable = doc.createElement(QLatin1String("variable")); + ps.appendChild(variable); + QDomText variableText = doc.createTextNode(i.key()); + variable.appendChild(variableText); + + writeValue(ps, i.value()); + ++i; + } + + file.write(doc.toByteArray()); + file.close(); + return true; +} diff --git a/installerbuilder/libinstaller/persistentsettings.h b/installerbuilder/libinstaller/persistentsettings.h new file mode 100644 index 000000000..605cb9cfb --- /dev/null +++ b/installerbuilder/libinstaller/persistentsettings.h @@ -0,0 +1,76 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef PERSISTENTSETTINGS_H +#define PERSISTENTSETTINGS_H + +#include "projectexplorer_export.h" + +#include <QtCore/QMap> +#include <QtCore/QVariant> + +QT_BEGIN_NAMESPACE +class QDomElement; +QT_END_NAMESPACE + +namespace ProjectExplorer { + +class PROJECTEXPLORER_EXPORT PersistentSettingsReader +{ +public: + PersistentSettingsReader(); + QVariant restoreValue(const QString & variable) const; + QVariantMap restoreValues() const; + bool load(const QString & fileName); + +private: + QVariant readValue(const QDomElement &valElement) const; + void readValues(const QDomElement &data); + QMap<QString, QVariant> m_valueMap; +}; + +class PROJECTEXPLORER_EXPORT PersistentSettingsWriter +{ +public: + PersistentSettingsWriter(); + void saveValue(const QString & variable, const QVariant &value); + bool save(const QString & fileName, const QString & docType); + +private: + void writeValue(QDomElement &ps, const QVariant &value); + QMap<QString, QVariant> m_valueMap; +}; + +} // namespace ProjectExplorer + +#endif // PERSISTENTSETTINGS_H diff --git a/installerbuilder/libinstaller/projectexplorer_export.h b/installerbuilder/libinstaller/projectexplorer_export.h new file mode 100644 index 000000000..d93c3da24 --- /dev/null +++ b/installerbuilder/libinstaller/projectexplorer_export.h @@ -0,0 +1 @@ +#define PROJECTEXPLORER_EXPORT
\ No newline at end of file diff --git a/installerbuilder/libinstaller/qinstaller_p.cpp b/installerbuilder/libinstaller/qinstaller_p.cpp index 870c43c61..d4ef12496 100644 --- a/installerbuilder/libinstaller/qinstaller_p.cpp +++ b/installerbuilder/libinstaller/qinstaller_p.cpp @@ -331,7 +331,8 @@ void InstallerPrivate::initialize() m_vars.insert(QLatin1String("TargetDir"), replaceVariables(m_installerSettings->adminTargetDir())); else #endif - m_vars.insert(QLatin1String("TargetDir"), replaceVariables(m_installerSettings->targetDir())); + m_vars.insert(QLatin1String("TargetDir"), replaceVariables(m_installerSettings->targetDir())); + m_vars.insert(QLatin1String("RemoveTargetDir"), replaceVariables(m_installerSettings->removeTargetDir())); QSettings creatorSettings(QSettings::IniFormat, QSettings::UserScope, QLatin1String("Nokia"), QLatin1String("QtCreator")); @@ -976,7 +977,9 @@ void InstallerPrivate::runInstaller() if (!q->gainAdminRights() || !performOperationThreaded(mkdirOp.data())) throw Error(mkdirOp->errorString()); } - addPerformed(mkdirOp.take()); + QString remove = q->value(QLatin1String("RemoveTargetDir")); + if (QVariant(remove).toBool()) + addPerformed(mkdirOp.take()); } else { QTemporaryFile tempAdminFile(target + QLatin1String("/adminrights")); if (!tempAdminFile.open() || !tempAdminFile.isWritable()) @@ -1456,18 +1459,21 @@ void InstallerPrivate::runUninstaller() (*it)->setValue(QLatin1String("CurrentState"), QLatin1String("Uninstalled")); } - // on !Windows, we need to remove TargetDir manually - m_packageManagingMode = ! m_completeUninstall; - verbose() << "Complete Uninstallation is chosen" << std::endl; - const QString target = targetDir(); - if (!target.isEmpty()) { - if (m_FSEngineClientHandler->isServerRunning() && !m_FSEngineClientHandler->isActive()) { - // we were root at least once, so we remove the target dir as root - q->gainAdminRights(); - removeDirectoryThreaded(target, true); - q->dropAdminRights(); - } else { - removeDirectoryThreaded(target, true); + QString remove = q->value(QLatin1String("RemoveTargetDir")); + if (QVariant(remove).toBool()) { + // on !Windows, we need to remove TargetDir manually + m_packageManagingMode = ! m_completeUninstall; + verbose() << "Complete Uninstallation is chosen" << std::endl; + const QString target = targetDir(); + if (!target.isEmpty()) { + if (m_FSEngineClientHandler->isServerRunning() && !m_FSEngineClientHandler->isActive()) { + // we were root at least once, so we remove the target dir as root + q->gainAdminRights(); + removeDirectoryThreaded(target, true); + q->dropAdminRights(); + } else { + removeDirectoryThreaded(target, true); + } } } diff --git a/installerbuilder/libinstaller/qinstallergui.cpp b/installerbuilder/libinstaller/qinstallergui.cpp index 5d0695bb3..aa3159a8d 100644 --- a/installerbuilder/libinstaller/qinstallergui.cpp +++ b/installerbuilder/libinstaller/qinstallergui.cpp @@ -1223,6 +1223,10 @@ bool TargetDirectoryPage::validatePage() return false; } + QString remove = installer()->value(QLatin1String("RemoveTargetDir")); + if (!QVariant(remove).toBool()) + return true; + return MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), QLatin1String("overwriteTargetDirectory"), tr("Warning"), tr("You have selected an existing, non-empty folder for installation.\n" diff --git a/installerbuilder/libinstaller/registertoolchainoperation.cpp b/installerbuilder/libinstaller/registertoolchainoperation.cpp new file mode 100644 index 000000000..22d5b6833 --- /dev/null +++ b/installerbuilder/libinstaller/registertoolchainoperation.cpp @@ -0,0 +1,187 @@ +/************************************************************************** +** +** This file is part of Qt SDK** +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** +** Contact: Nokia Corporation qt-info@nokia.com** +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception version +** 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you are unsure which license is appropriate for your use, please contact +** (qt-info@nokia.com). +** +**************************************************************************/ +#include "registertoolchainoperation.h" +#include "persistentsettings.h" + +#include <QString> +#include <QFileInfo> +#include <QDir> +#include <QSettings> +#include <QDebug> + +using namespace QInstaller; + +//Begin - copied from Creator +using namespace ProjectExplorer; + +static const char *const TOOLCHAIN_DATA_KEY = "ToolChain."; +static const char *const TOOLCHAIN_COUNT_KEY = "ToolChain.Count"; +static const char *const TOOLCHAIN_FILE_VERSION_KEY = "Version"; + +static const char *const ID_KEY = "ProjectExplorer.ToolChain.Id"; +static const char *const DISPLAY_NAME_KEY = "ProjectExplorer.ToolChain.DisplayName"; +//End - copied from Creator + + +RegisterToolChainOperation::RegisterToolChainOperation() +{ + setName(QLatin1String("RegisterToolChain")); +} + +RegisterToolChainOperation::~RegisterToolChainOperation() +{ +} + +void RegisterToolChainOperation::backup() +{ +} + +bool RegisterToolChainOperation::performOperation() +{ + const QStringList args = arguments(); + + if( args.count() < 5) { + setError( InvalidArguments ); + setErrorString( tr("Invalid arguments in %0: %1 arguments given, minimum 5 expected.") + .arg(name()).arg( args.count() ) ); + return false; + } + + int argCounter = 0; + const QString &rootInstallPath = args.at(argCounter++); //for example "C:\\Nokia_SDK\\" + const QString &toolChainKey = args.at(argCounter++); //Qt SDK:gccPath + const QString &toolChainType = args.at(argCounter++); //where this toolchain is defined in QtCreator + const QString &displayName = args.at(argCounter++); //nice special Toolchain (Qt SDK) + const QString &abiString = args.at(argCounter++); //x86-windows-msys-pe-32bit + const QString &compilerPath = args.at(argCounter++); //gccPath + QString debuggerPath; + QString armVersion; + QString force32Bit; + if (args.count() > argCounter) + debuggerPath = args.at(argCounter++); + if (args.count() > argCounter) + armVersion = args.at(argCounter++); + if (args.count() > argCounter) + force32Bit = args.at(argCounter++); + + QString toolChainsXmlFilePath; + +#if defined ( Q_OS_MAC ) + toolChainsXmlFilePath = QString( + QLatin1String("%1/Qt Creator.app/Contents/Resources/Nokia/toolChains.xml") + ).arg(rootInstallPath); +#else + toolChainsXmlFilePath = QString( + QLatin1String("%1/QtCreator/share/qtcreator/Nokia/toolChains.xml") + ).arg(rootInstallPath); +#endif + + + QHash< QString, QVariantMap > toolChainHash; + + PersistentSettingsReader reader; + if (reader.load(toolChainsXmlFilePath)) { + QVariantMap data = reader.restoreValues(); + + // Check version: + int version = data.value(QLatin1String(TOOLCHAIN_FILE_VERSION_KEY), 0).toInt(); + if (version < 1) { + setError( UserDefinedError ); + setErrorString(tr("Toolchain settings xml file %1 has not the right version.") + .arg(toolChainsXmlFilePath)); + return false; + } + + int count = data.value(QLatin1String(TOOLCHAIN_COUNT_KEY), 0).toInt(); + for (int i = 0; i < count; ++i) { + const QString key = QString::fromLatin1(TOOLCHAIN_DATA_KEY) + QString::number(i); + + const QVariantMap toolChainMap = data.value(key).toMap(); + + //gets the path variable, hope ".Path" will stay in QtCreator + QStringList pathContainingKeyList = + QStringList(toolChainMap.keys()).filter(QLatin1String(".Path")); + foreach(const QString& pathKey, pathContainingKeyList) { + QString path = toolChainMap.value(pathKey).toString(); + if (!path.isEmpty() && QFile::exists(path)) { + toolChainHash.insert(path, toolChainMap); + } + } + } + } + + QVariantMap newToolChainVariantMap; + + newToolChainVariantMap.insert(QLatin1String(ID_KEY), + QString(QLatin1String("%1:%2.%3")).arg(toolChainType, compilerPath, abiString)); + newToolChainVariantMap.insert(QLatin1String(DISPLAY_NAME_KEY), displayName); + newToolChainVariantMap.insert(QString(QLatin1String("ProjectExplorer.%1.Path")).arg(toolChainKey), + compilerPath); + newToolChainVariantMap.insert(QString(QLatin1String("ProjectExplorer.%1.TargetAbi")).arg(toolChainKey), + abiString); + newToolChainVariantMap.insert(QString(QLatin1String("ProjectExplorer.%1.Debugger")).arg(toolChainKey), + debuggerPath); + + toolChainHash.insert(compilerPath, newToolChainVariantMap); + + PersistentSettingsWriter writer; + writer.saveValue(QLatin1String(TOOLCHAIN_FILE_VERSION_KEY), 1); + + int count = 0; + + foreach (const QVariantMap &toolChainMap, toolChainHash.values()) { + if (toolChainMap.isEmpty()) + continue; + writer.saveValue(QString::fromLatin1(TOOLCHAIN_DATA_KEY) + QString::number(count++), + toolChainMap); + } + writer.saveValue(QLatin1String(TOOLCHAIN_COUNT_KEY), count); + writer.save(toolChainsXmlFilePath, QLatin1String("QtCreatorToolChains")); + + return true; +} + +bool RegisterToolChainOperation::undoOperation() +{ + return true; +} + +bool RegisterToolChainOperation::testOperation() +{ + return true; +} + +KDUpdater::UpdateOperation* RegisterToolChainOperation::clone() const +{ + return new RegisterToolChainOperation(); +} diff --git a/installerbuilder/libinstaller/registertoolchainoperation.h b/installerbuilder/libinstaller/registertoolchainoperation.h new file mode 100644 index 000000000..4fce9bc7a --- /dev/null +++ b/installerbuilder/libinstaller/registertoolchainoperation.h @@ -0,0 +1,65 @@ +/************************************************************************** +** +** This file is part of Qt SDK** +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).* +** +** Contact: Nokia Corporation qt-info@nokia.com** +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception version +** 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you are unsure which license is appropriate for your use, please contact +** (qt-info@nokia.com). +** +**************************************************************************/ +#ifndef REGISTERTOOLCHAINOPERATION_H +#define REGISTERTOOLCHAINOPERATION_H + +#include <KDUpdater/UpdateOperation> + +namespace QInstaller { + +/** Arguments: + * SDK Path - to find the QtCreator installation + * ToolChainKey - is the internal QtCreator settings key usually: GccToolChain + * toolchain type - where this toolchain is defined in QtCreator + * ProjectExplorer.ToolChain.Gcc ProjectExplorer.ToolChain.Mingw + * ProjectExplorer.ToolChain.LinuxIcc ProjectExplorer.ToolChain.Msvc + * Qt4ProjectManager.ToolChain.GCCE Qt4ProjectManager.ToolChain.Maemo + * display name - the name how it will be displayed in QtCreator + * application binary interface - this is an internal creator typ as a String CPU-OS-OS_FLAVOR-BINARY_FORMAT-WORD_WIDTH + * CPU: arm x86 mips ppc itanium + * OS: linux macos symbian unix windows + * OS_FLAVOR: generic maemo meego generic device emulator generic msvc2005 msvc2008 msvc2010 msys ce + * BINARY_FORMAT: elf pe mach_o qml_rt + * WORD_WIDTH: 8 16 32 64 + * compiler path - the binary which is used as the compiler + * debugger path - the binary which is used as the debugger + */ +class RegisterToolChainOperation : public KDUpdater::UpdateOperation +{ +public: + RegisterToolChainOperation(); + ~RegisterToolChainOperation(); + + void backup(); + bool performOperation(); + bool undoOperation(); + bool testOperation(); + KDUpdater::UpdateOperation* clone() const; +}; + +}; // namespace + +#endif // REGISTERTOOLCHAINOPERATION_H |