diff --git a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp index 54a88c18aafa5bf7a912b962431c827b8a05cfa8..694db1012ee4638995ea093489d451a16a5106ac 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp @@ -31,13 +31,18 @@ #include "qt4projectmanagerconstants.h" #include "qt4buildconfiguration.h" +#include "qt4nodes.h" +#include "qt4project.h" #include "abldparser.h" #include <projectexplorer/buildconfiguration.h> #include <projectexplorer/target.h> +#include <projectexplorer/project.h> #include <projectexplorer/gnumakeparser.h> +#include <projectexplorer/task.h> #include <QtCore/QDir> +#include <QtCore/QTimer> using namespace Qt4ProjectManager::Internal; @@ -49,30 +54,41 @@ namespace { const char * const SMART_INSTALLER_KEY("Qt4ProjectManager.S60CreatorPackageStep.SmartInstaller"); } -// #pragma mark -- S60SignBuildStep - S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildConfiguration *bc) : - MakeStep(bc, QLatin1String(SIGN_BS_ID)), + BuildStep(bc, QLatin1String(SIGN_BS_ID)), m_signingMode(SignSelf), - m_createSmartInstaller(false) + m_createSmartInstaller(false), + m_outputParserChain(0), + m_process(0), + m_timer(0), + m_eventLoop(0), + m_futureInterface(0) { ctor_package(); } S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildConfiguration *bc, S60CreatePackageStep *bs) : - MakeStep(bc, bs), + BuildStep(bc, bs), m_signingMode(bs->m_signingMode), m_customSignaturePath(bs->m_customSignaturePath), m_customKeyPath(bs->m_customKeyPath), - m_createSmartInstaller(bs->m_createSmartInstaller) + m_createSmartInstaller(bs->m_createSmartInstaller), + m_outputParserChain(0), + m_timer(0), + m_eventLoop(0), + m_futureInterface(0) { ctor_package(); } S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildConfiguration *bc, const QString &id) : - MakeStep(bc, id), + BuildStep(bc, id), m_signingMode(SignSelf), - m_createSmartInstaller(false) + m_createSmartInstaller(false), + m_outputParserChain(0), + m_timer(0), + m_eventLoop(0), + m_futureInterface(0) { ctor_package(); } @@ -88,7 +104,7 @@ S60CreatePackageStep::~S60CreatePackageStep() QVariantMap S60CreatePackageStep::toMap() const { - QVariantMap map(MakeStep::toMap()); + QVariantMap map(BuildStep::toMap()); map.insert(QLatin1String(SIGNMODE_KEY), (int)m_signingMode); map.insert(QLatin1String(CERTIFICATE_KEY), m_customSignaturePath); map.insert(QLatin1String(KEYFILE_KEY), m_customKeyPath); @@ -102,34 +118,224 @@ bool S60CreatePackageStep::fromMap(const QVariantMap &map) m_customSignaturePath = map.value(QLatin1String(CERTIFICATE_KEY)).toString(); m_customKeyPath = map.value(QLatin1String(KEYFILE_KEY)).toString(); m_createSmartInstaller = map.value(QLatin1String(SMART_INSTALLER_KEY), false).toBool(); - return MakeStep::fromMap(map); + return BuildStep::fromMap(map); +} + +Qt4BuildConfiguration *S60CreatePackageStep::qt4BuildConfiguration() const +{ + return static_cast<Qt4BuildConfiguration *>(buildConfiguration()); } bool S60CreatePackageStep::init() { - if (!MakeStep::init()) - return false; - Qt4BuildConfiguration *bc = qt4BuildConfiguration(); - ProjectExplorer::Environment environment = bc->environment(); - setEnvironment(environment); - QStringList args; + Qt4Project *pro = qobject_cast<Qt4Project *>(buildConfiguration()->target()->project()); + + QList<Qt4ProFileNode *> nodes = pro->leafProFiles(); + + m_workingDirectories.clear(); + foreach (Qt4ProFileNode *node, nodes) + m_workingDirectories << node->buildDir(); + + m_makeCmd = qt4BuildConfiguration()->makeCommand(); + if (!QFileInfo(m_makeCmd).isAbsolute()) { + // Try to detect command in environment + const QString tmp = buildConfiguration()->environment().searchInPath(m_makeCmd); + if (tmp.isEmpty()) { + emit addOutput(tr("Could not find make command: %1 in the build environment").arg(m_makeCmd), BuildStep::ErrorOutput); + return false; + } + m_makeCmd = tmp; + } + + m_environment = qt4BuildConfiguration()->environment(); + + m_args.clear(); if (m_createSmartInstaller) - args << QLatin1String("installer_sis"); + m_args << QLatin1String("installer_sis"); else - args << QLatin1String("sis"); + m_args << QLatin1String("sis"); if (signingMode() == SignCustom) { - args << QLatin1String("QT_SIS_CERTIFICATE=") + QDir::toNativeSeparators(customSignaturePath()) - << QLatin1String("QT_SIS_KEY=") + QDir::toNativeSeparators(customKeyPath()); + m_args << QLatin1String("QT_SIS_CERTIFICATE=") + QDir::toNativeSeparators(customSignaturePath()) + << QLatin1String("QT_SIS_KEY=") + QDir::toNativeSeparators(customKeyPath()); + } + + delete m_outputParserChain; + m_outputParserChain = new ProjectExplorer::GnuMakeParser; + m_outputParserChain->appendOutputParser(new Qt4ProjectManager::AbldParser); + connect(m_outputParserChain, SIGNAL(addOutput(QString, ProjectExplorer::BuildStep::OutputFormat)), + this, SLOT(outputAdded(QString, ProjectExplorer::BuildStep::OutputFormat))); + connect(m_outputParserChain, SIGNAL(addTask(ProjectExplorer::Task)), + this, SLOT(taskAdded(ProjectExplorer::Task))); + + return true; +} + +void S60CreatePackageStep::run(QFutureInterface<bool> &fi) +{ + m_futureInterface = &fi; + + if (m_workingDirectories.isEmpty()) { + fi.reportResult(true); + return; + } + + // Setup everything... + m_process = new QProcess(); + m_process->setEnvironment(m_environment.toStringList()); + + connect(m_process, SIGNAL(readyReadStandardOutput()), + this, SLOT(processReadyReadStdOutput()), + Qt::DirectConnection); + connect(m_process, SIGNAL(readyReadStandardError()), + this, SLOT(processReadyReadStdError()), + Qt::DirectConnection); + + connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(slotProcessFinished(int, QProcess::ExitStatus)), + Qt::DirectConnection); + + m_timer = new QTimer(); + connect(m_timer, SIGNAL(timeout()), this, SLOT(checkForCancel()), Qt::DirectConnection); + m_timer->start(500); + m_eventLoop = new QEventLoop; + + bool returnValue = false; + if (startProcess()) + returnValue = m_eventLoop->exec(); + + // Finished + m_timer->stop(); + delete m_timer; + m_timer = 0; + + delete m_process; + m_process = 0; + delete m_eventLoop; + m_eventLoop = 0; + fi.reportResult(returnValue); + m_futureInterface = 0; + + return; +} + +void S60CreatePackageStep::slotProcessFinished(int, QProcess::ExitStatus) +{ + QString line = QString::fromLocal8Bit(m_process->readAllStandardError()); + if (!line.isEmpty()) + stdError(line); + + line = QString::fromLocal8Bit(m_process->readAllStandardOutput()); + if (!line.isEmpty()) + stdOutput(line); + + bool returnValue = false; + if (m_process->exitStatus() == QProcess::NormalExit && m_process->exitCode() == 0) { + emit addOutput(tr("The process \"%1\" exited normally.") + .arg(QDir::toNativeSeparators(m_makeCmd)), + BuildStep::MessageOutput); + returnValue = true; + } else if (m_process->exitStatus() == QProcess::NormalExit) { + emit addOutput(tr("The process \"%1\" exited with code %2.") + .arg(QDir::toNativeSeparators(m_makeCmd), QString::number(m_process->exitCode())), + BuildStep::ErrorMessageOutput); + } else { + emit addOutput(tr("The process \"%1\" crashed.").arg(QDir::toNativeSeparators(m_makeCmd)), BuildStep::ErrorMessageOutput); + } + + if (m_workingDirectories.isEmpty() || !returnValue) { + m_eventLoop->exit(returnValue); + } else { + // Success, do next + if (!startProcess()) + m_eventLoop->exit(returnValue); } - setArguments(args); // overwrite any stuff done in make step +} + +bool S60CreatePackageStep::startProcess() +{ + QString workingDirectory = m_workingDirectories.takeFirst(); + QDir wd(workingDirectory); + if (!wd.exists()) + wd.mkpath(wd.absolutePath()); - ProjectExplorer::GnuMakeParser *parser = new ProjectExplorer::GnuMakeParser; - parser->appendOutputParser(new Qt4ProjectManager::AbldParser); - setOutputParser(parser); + m_process->setWorkingDirectory(workingDirectory); + // Go for it! + m_process->start(m_makeCmd, m_args); + if (!m_process->waitForStarted()) { + emit addOutput(tr("Could not start process \"%1\" in %2") + .arg(QDir::toNativeSeparators(m_makeCmd), + workingDirectory), + BuildStep::ErrorMessageOutput); + return false; + } + emit addOutput(tr("Starting: \"%1\" %2 in %3\n") + .arg(QDir::toNativeSeparators(m_makeCmd), + m_args.join(" "), + workingDirectory), + BuildStep::MessageOutput); return true; } +void S60CreatePackageStep::processReadyReadStdOutput() +{ + m_process->setReadChannel(QProcess::StandardOutput); + while (m_process->canReadLine()) { + QString line = QString::fromLocal8Bit(m_process->readLine()); + stdOutput(line); + } +} + +void S60CreatePackageStep::stdOutput(const QString &line) +{ + if (m_outputParserChain) + m_outputParserChain->stdOutput(line); + emit addOutput(line, BuildStep::NormalOutput); +} + +void S60CreatePackageStep::processReadyReadStdError() +{ + m_process->setReadChannel(QProcess::StandardError); + while (m_process->canReadLine()) { + QString line = QString::fromLocal8Bit(m_process->readLine()); + stdError(line); + } +} + +void S60CreatePackageStep::stdError(const QString &line) +{ + if (m_outputParserChain) + m_outputParserChain->stdError(line); + emit addOutput(line, BuildStep::ErrorOutput); +} + +void S60CreatePackageStep::checkForCancel() +{ + if (m_futureInterface->isCanceled() && m_timer->isActive()) { + m_timer->stop(); + m_process->terminate(); + m_process->waitForFinished(5000); + m_process->kill(); + } +} + +void S60CreatePackageStep::taskAdded(const ProjectExplorer::Task &task) +{ + ProjectExplorer::Task editable(task); + QString filePath = QDir::cleanPath(task.file.trimmed()); + if (!filePath.isEmpty() && !QDir::isAbsolutePath(filePath)) { + // TODO which kind of tasks do we get from package building? + // No absoulte path + } + emit addTask(editable); +} + +void S60CreatePackageStep::outputAdded(const QString &string, ProjectExplorer::BuildStep::OutputFormat format) +{ + emit addOutput(string, format); +} + + bool S60CreatePackageStep::immutable() const { return false; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h index fd74500b9b60550886cd74379df2823b0d934e9e..e4a03985adc5d2239f988947a7e12a145b690214 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h @@ -59,7 +59,8 @@ public: ProjectExplorer::BuildStep *clone(ProjectExplorer::BuildConfiguration *parent, ProjectExplorer::BuildStep::Type type, ProjectExplorer::BuildStep *product); }; -class S60CreatePackageStep : public MakeStep { +class S60CreatePackageStep : public ProjectExplorer::BuildStep +{ Q_OBJECT friend class S60CreatePackageStepFactory; public: @@ -72,6 +73,7 @@ public: virtual ~S60CreatePackageStep(); virtual bool init(); + virtual void run(QFutureInterface<bool> &fi); virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget(); virtual bool immutable() const; @@ -91,13 +93,38 @@ protected: S60CreatePackageStep(ProjectExplorer::BuildConfiguration *bc, const QString &id); bool fromMap(const QVariantMap &map); + Qt4BuildConfiguration *qt4BuildConfiguration() const; + +private slots: + void slotProcessFinished(int, QProcess::ExitStatus); + void processReadyReadStdOutput(); + void processReadyReadStdError(); + void taskAdded(const ProjectExplorer::Task &task); + void outputAdded(const QString &string, ProjectExplorer::BuildStep::OutputFormat format); + void checkForCancel(); + private: + void stdOutput(const QString &line); + void stdError(const QString &line); + bool startProcess(); + QStringList m_workingDirectories; + + QString m_makeCmd; + ProjectExplorer::Environment m_environment; + QStringList m_args; + void ctor_package(); SigningMode m_signingMode; QString m_customSignaturePath; QString m_customKeyPath; bool m_createSmartInstaller; + ProjectExplorer::IOutputParser *m_outputParserChain; + + QProcess *m_process; + QTimer *m_timer; + QEventLoop *m_eventLoop; + QFutureInterface<bool> *m_futureInterface; }; class S60CreatePackageStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp index 129f52f7ccd6b335fe3d6f9a47bac63457d5ebcb..d1a9df646c61cf035fdbaf07fa64f7bdb2cf2d0c 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp @@ -126,8 +126,9 @@ bool S60DeployStep::init() } m_serialPortName = runConfiguration->serialPortName(); m_serialPortFriendlyName = SymbianUtils::SymbianDeviceManager::instance()->friendlyNameForPort(m_serialPortName); - m_packageFileNameWithTarget = runConfiguration->packageFileNameWithTargetInfo(); - m_signedPackage = runConfiguration->signedPackage(); + m_packageFileNamesWithTarget = runConfiguration->packageFileNamesWithTargetInfo(); + m_signedPackages = runConfiguration->signedPackages(); + m_installationDrive = runConfiguration->installationDrive(); m_silentInstall = runConfiguration->silentInstall(); @@ -174,31 +175,31 @@ void S60DeployStep::appendMessage(const QString &error, bool isError) bool S60DeployStep::processPackageName(QString &errorMessage) { - QFileInfo packageInfo(m_signedPackage); - { + for (int i = 0; i < m_signedPackages.count(); ++i) { + QFileInfo packageInfo(m_signedPackages.at(i)); // support for 4.6.1 and pre, where make sis creates 'targetname_armX_udeb.sis' instead of 'targetname.sis' - QFileInfo packageWithTargetInfo(m_packageFileNameWithTarget); + QFileInfo packageWithTargetInfo(m_packageFileNamesWithTarget.at(i)); // does the 4.6.1 version exist? if (packageWithTargetInfo.exists() && packageWithTargetInfo.isFile()) { // is the 4.6.1 version newer? (to guard against behavior change Qt Creator 1.3 --> 2.0) if (!packageInfo.exists() || packageInfo.lastModified() < packageWithTargetInfo.lastModified()) { //TODO change the QtCore // the 'targetname_armX_udeb.sis' crap exists and is new, rename it appendMessage(tr("Renaming new package '%1' to '%2'") - .arg(QDir::toNativeSeparators(m_packageFileNameWithTarget), - QDir::toNativeSeparators(m_signedPackage)), false); - return renameFile(m_packageFileNameWithTarget, m_signedPackage, &errorMessage); + .arg(QDir::toNativeSeparators(m_packageFileNamesWithTarget.at(i)), + QDir::toNativeSeparators(m_signedPackages.at(i))), false); + return renameFile(m_packageFileNamesWithTarget.at(i), m_signedPackages.at(i), &errorMessage); } else { // the 'targetname_armX_udeb.sis' crap exists but is old, remove it appendMessage(tr("Removing old package '%1'") - .arg(QDir::toNativeSeparators(m_packageFileNameWithTarget)), + .arg(QDir::toNativeSeparators(m_packageFileNamesWithTarget.at(i))), false); - ensureDeleteFile(m_packageFileNameWithTarget, &errorMessage); + ensureDeleteFile(m_packageFileNamesWithTarget.at(i), &errorMessage); } } - } - if (!packageInfo.exists() || !packageInfo.isFile()) { - errorMessage = tr("Package file not found"); - return false; + if (!packageInfo.exists() || !packageInfo.isFile()) { + errorMessage = tr("'%1': Package file not found").arg(m_signedPackages.at(i)); + return false; + } } return true; } @@ -217,7 +218,7 @@ void S60DeployStep::start() if (processPackageName(errorMessage)) { startDeployment(); } else { - errorMessage = tr("Failed to find package '%1': %2").arg(m_signedPackage, errorMessage); + errorMessage = tr("Failed to find package %1").arg(errorMessage); appendMessage(errorMessage, true); stop(); emit finished(); @@ -253,16 +254,19 @@ void S60DeployStep::startDeployment() setupConnections(); - const QString copyDst = QString::fromLatin1("%1:\\Data\\%2").arg(m_installationDrive).arg(QFileInfo(m_signedPackage).fileName()); + QStringList copyDst; + foreach (const QString &signedPackage, m_signedPackages) + copyDst << QString::fromLatin1("%1:\\Data\\%1").arg(m_installationDrive).arg(QFileInfo(signedPackage).fileName()); - m_launcher->setCopyFileName(m_signedPackage, copyDst); - m_launcher->setInstallFileName(copyDst); + m_launcher->setCopyFileNames(m_signedPackages, copyDst); + m_launcher->setInstallFileNames(copyDst); m_launcher->setInstallationDrive(m_installationDrive); m_launcher->setInstallationMode(m_silentInstall?trk::Launcher::InstallationModeSilentAndUser: trk::Launcher::InstallationModeUser); m_launcher->addStartupActions(trk::Launcher::ActionCopyInstall); - appendMessage(tr("Package: %1\nDeploying application to '%2'...").arg(m_signedPackage, m_serialPortFriendlyName), false); + // TODO readd information about packages? msgListFile(m_signedPackage) + appendMessage(tr("Deploying application to '%2'...").arg(m_serialPortFriendlyName), false); QString errorMessage; if (!m_launcher->startServer(&errorMessage)) { diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h index 2023270b5c63f2f93d2363a70b5e217913cc5f13..e3c324669dc7c78686d73d61f8841a1375a70761 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h @@ -129,8 +129,8 @@ signals: private: QString m_serialPortName; QString m_serialPortFriendlyName; - QString m_packageFileNameWithTarget; // Support for 4.6.1 - QString m_signedPackage; + QStringList m_packageFileNamesWithTarget; // Support for 4.6.1 + QStringList m_signedPackages; QTimer *m_timer; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index 4c66d059c7f5b12db3404b24230b924f1d21a9ac..8bb36a1982385ee23c00591e6fbce2aef0f61f32 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -286,16 +286,22 @@ static inline QString fixBaseNameTarget(const QString &in) return in; } -QString S60DeviceRunConfiguration::packageFileNameWithTargetInfo() const -{ - TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath); - if (!ti.valid) - return QString(); - QString baseFileName = ti.buildDir + QLatin1Char('/') + ti.target; - baseFileName += QLatin1Char('_') - + (isDebug() ? QLatin1String("debug") : QLatin1String("release")) - + QLatin1Char('-') + symbianPlatform() + QLatin1String(".sis"); - return baseFileName; +QStringList S60DeviceRunConfiguration::packageFileNamesWithTargetInfo() const +{ + QList<Qt4ProFileNode *> leafs = qt4Target()->qt4Project()->leafProFiles(); + + QStringList result; + foreach (Qt4ProFileNode *qt4ProFileNode, leafs) { + TargetInformation ti = qt4ProFileNode->targetInformation(); + if (!ti.valid) + continue; + QString baseFileName = ti.buildDir + QLatin1Char('/') + ti.target; + baseFileName += QLatin1Char('_') + + (isDebug() ? QLatin1String("debug") : QLatin1String("release")) + + QLatin1Char('-') + symbianPlatform() + QLatin1String(".sis"); + result << baseFileName; + } + return result; } QString S60DeviceRunConfiguration::symbianPlatform() const @@ -323,7 +329,19 @@ QString S60DeviceRunConfiguration::symbianTarget() const return isDebug() ? QLatin1String("udeb") : QLatin1String("urel"); } -QString S60DeviceRunConfiguration::packageTemplateFileName() const +QStringList S60DeviceRunConfiguration::packageTemplateFileNames() const +{ + QList<Qt4ProFileNode *> list = qt4Target()->qt4Project()->leafProFiles(); + QStringList result; + foreach (Qt4ProFileNode *node, list) { + TargetInformation ti = node->targetInformation(); + if (ti.valid) + result << ti.buildDir + QLatin1Char('/') + ti.target + QLatin1String("_template.pkg"); + } + return result; +} + +QString S60DeviceRunConfiguration::appPackageTemplateFileName() const { TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath); if (!ti.valid) @@ -331,6 +349,7 @@ QString S60DeviceRunConfiguration::packageTemplateFileName() const return ti.buildDir + QLatin1Char('/') + ti.target + QLatin1String("_template.pkg"); } + /* Grep a package file for the '.exe' file. Curently for use on Linux only * as the '.pkg'-files on Windows do not contain drive letters, which is not * handled here. \code @@ -373,7 +392,7 @@ QString S60DeviceRunConfiguration::localExecutableFileName() const switch (toolChainType()) { case ToolChain::GCCE_GNUPOC: case ToolChain::RVCT_ARMV5_GNUPOC: - localExecutable = executableFromPackageUnix(packageTemplateFileName()); + localExecutable = executableFromPackageUnix(appPackageTemplateFileName()); break; default: { const QtVersion *qtv = qtVersion(); @@ -403,7 +422,21 @@ bool S60DeviceRunConfiguration::runSmartInstaller() const return false; } -QString S60DeviceRunConfiguration::signedPackage() const +QStringList S60DeviceRunConfiguration::signedPackages() const +{ + QList<Qt4ProFileNode *> list = qt4Target()->qt4Project()->leafProFiles(); + QStringList result; + foreach (Qt4ProFileNode *node, list) { + TargetInformation ti = node->targetInformation(); + if (ti.valid) + result << ti.buildDir + QLatin1Char('/') + ti.target + + (runSmartInstaller() ? QLatin1String("_installer") : QLatin1String("")) + + QLatin1String(".sis"); + } + return result; +} + +QString S60DeviceRunConfiguration::appSignedPackage() const { TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath); if (!ti.valid) @@ -640,7 +673,6 @@ void S60DeviceRunControlBase::startDeployment() if (!m_commandLineArguments.isEmpty()) m_launcher->setCommandLineArgs(m_commandLineArguments); - const QString runFileName = QString::fromLatin1("%1:\\sys\\bin\\%2.exe").arg(m_installationDrive).arg(m_targetName); initLauncher(runFileName, m_launcher); const trk::PromptStartCommunicationResult src = diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h index d17716f9574971c85c2f40d7cb19accabb8f98a6..b2c7a4883a2f0c1027341f4900bf83e2e6320802 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h @@ -82,15 +82,14 @@ public: char installationDrive() const; void setInstallationDrive(char drive); + QStringList packageFileNamesWithTargetInfo() const; + QStringList packageTemplateFileNames() const; + QString appPackageTemplateFileName() const; QString targetName() const; - QString packageFileNameWithTargetInfo() const; - QString symbianPlatform() const; - QString symbianTarget() const; - bool isDebug() const; - QString packageTemplateFileName() const; QString localExecutableFileName() const; - QString signedPackage() const; + QStringList signedPackages() const; + QString appSignedPackage() const; const QtVersion *qtVersion() const; QStringList commandLineArguments() const; @@ -107,6 +106,7 @@ signals: void targetInformationChanged(); void serialPortNameChanged(); + private slots: void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro); void updateActiveBuildConfiguration(ProjectExplorer::BuildConfiguration *buildConfiguration); @@ -116,6 +116,9 @@ protected: virtual bool fromMap(const QVariantMap &map); private: + QString symbianPlatform() const; + QString symbianTarget() const; + bool isDebug() const; ProjectExplorer::ToolChain::ToolChainType toolChainType(ProjectExplorer::BuildConfiguration *configuration) const; void ctor(); @@ -197,7 +200,6 @@ private: QString m_serialPortFriendlyName; QString m_targetName; QStringList m_commandLineArguments; - QString m_workingDirectory; QString m_executableFileName; QString m_qtDir; QString m_qtBinPath; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp index d180b23498771ec58407ee4784f6b8c0647229e2..cb3a4c08c2e43d78f3b821c83c70caa5c72f41b6 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp @@ -247,7 +247,7 @@ void S60DeviceRunConfigurationWidget::argumentsEdited(const QString &text) void S60DeviceRunConfigurationWidget::updateTargetInformation() { - m_sisFileLabel->setText(QDir::toNativeSeparators(m_runConfiguration->signedPackage())); + m_sisFileLabel->setText(QDir::toNativeSeparators(m_runConfiguration->appPackageTemplateFileName())); } void S60DeviceRunConfigurationWidget::setInstallationDrive(int index) diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index 3e42ca965e81921c75a74f809e2d2ba1bbcf676f..202431549185afbebb468d6db477573725b6948a 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -977,6 +977,19 @@ QList<BuildConfigWidget*> Qt4Project::subConfigWidgets() return subWidgets; } +void Qt4Project::collectLeafProFiles(QList<Qt4ProFileNode *> &list, Qt4ProFileNode *node) +{ + if (node->projectType() != Internal::SubDirsTemplate) { + list.append(node); + } + foreach (ProjectNode *n, node->subProjectNodes()) { + Qt4ProFileNode *qt4ProFileNode = qobject_cast<Qt4ProFileNode *>(n); + if (qt4ProFileNode) + collectLeafProFiles(list, qt4ProFileNode); + } +} + + void Qt4Project::collectApplicationProFiles(QList<Qt4ProFileNode *> &list, Qt4ProFileNode *node) { if (node->projectType() == Internal::ApplicationTemplate @@ -1035,6 +1048,15 @@ void Qt4Project::createApplicationProjects() } } +QList<Qt4ProFileNode *> Qt4Project::leafProFiles() const +{ + QList<Qt4ProFileNode *> list; + if (!rootProjectNode()) + return list; + collectLeafProFiles(list, rootProjectNode()); + return list; +} + QList<Qt4ProFileNode *> Qt4Project::applicationProFiles() const { QList<Qt4ProFileNode *> list; diff --git a/src/plugins/qt4projectmanager/qt4project.h b/src/plugins/qt4projectmanager/qt4project.h index 7cd90165059975be4fa59722d84e7e1967acd1fa..2d805c21cb6e3cc5d91de624af2694bead3a1e27 100644 --- a/src/plugins/qt4projectmanager/qt4project.h +++ b/src/plugins/qt4projectmanager/qt4project.h @@ -136,6 +136,7 @@ public: ProjectExplorer::BuildConfigWidget *createConfigWidget(); QList<ProjectExplorer::BuildConfigWidget*> subConfigWidgets(); + QList<Internal::Qt4ProFileNode *> leafProFiles() const; QList<Internal::Qt4ProFileNode *> applicationProFiles() const; bool hasApplicationProFile(const QString &path) const; QStringList applicationProFilePathes(const QString &prepend = QString()) const; @@ -191,6 +192,7 @@ private: void updateCodeModel(); void updateFileList(); + static void collectLeafProFiles(QList<Internal::Qt4ProFileNode *> &list, Internal::Qt4ProFileNode *node); static void collectApplicationProFiles(QList<Internal::Qt4ProFileNode *> &list, Internal::Qt4ProFileNode *node); static void findProFile(const QString& fileName, Internal::Qt4ProFileNode *root, QList<Internal::Qt4ProFileNode *> &list); static bool hasSubNode(Internal::Qt4PriFileNode *root, const QString &path); diff --git a/src/shared/symbianutils/launcher.cpp b/src/shared/symbianutils/launcher.cpp index e6b790f45af0bbc9bfeb7741353315333645026f..4f8eaf7ad28875a776edf4840e649c2deb5309a6 100644 --- a/src/shared/symbianutils/launcher.cpp +++ b/src/shared/symbianutils/launcher.cpp @@ -74,15 +74,24 @@ void CrashReportState::clear() } struct LauncherPrivate { - struct CopyState { - QString sourceFileName; - QString destinationFileName; + struct TransferState { + int currentFileName; uint copyFileHandle; QScopedPointer<QByteArray> data; qint64 position; QScopedPointer<QFile> localFile; }; + struct CopyState : public TransferState { + QStringList sourceFileNames; + QStringList destinationFileNames; + }; + + struct DownloadState : public TransferState { + QString sourceFileName; + QString destinationFileName; + }; + explicit LauncherPrivate(const TrkDevicePtr &d); TrkDevicePtr m_device; @@ -94,10 +103,11 @@ struct LauncherPrivate { Session m_session; // global-ish data (process id, target information) CopyState m_copyState; - CopyState m_downloadState; + DownloadState m_downloadState; QString m_fileName; QStringList m_commandLineArgs; - QString m_installFileName; + QStringList m_installFileNames; + int m_currentInstallFileName; int m_verbose; Launcher::Actions m_startupActions; bool m_closeDevice; @@ -188,10 +198,11 @@ void Launcher::setFileName(const QString &name) d->m_fileName = name; } -void Launcher::setCopyFileName(const QString &srcName, const QString &dstName) +void Launcher::setCopyFileNames(const QStringList &srcNames, const QStringList &dstNames) { - d->m_copyState.sourceFileName = srcName; - d->m_copyState.destinationFileName = dstName; + d->m_copyState.sourceFileNames = srcNames; + d->m_copyState.destinationFileNames = dstNames; + d->m_copyState.currentFileName = 0; } void Launcher::setDownloadFileName(const QString &srcName, const QString &dstName) @@ -200,9 +211,10 @@ void Launcher::setDownloadFileName(const QString &srcName, const QString &dstNam d->m_downloadState.destinationFileName = dstName; } -void Launcher::setInstallFileName(const QString &name) +void Launcher::setInstallFileNames(const QStringList &names) { - d->m_installFileName = name; + d->m_installFileNames = names; + d->m_currentInstallFileName = 0; } void Launcher::setCommandLineArgs(const QStringList &args) @@ -255,28 +267,29 @@ bool Launcher::startServer(QString *errorMessage) str << " Executable=" << d->m_fileName; if (!d->m_commandLineArgs.isEmpty()) str << " Arguments= " << d->m_commandLineArgs.join(QString(QLatin1Char(' '))); - if (!d->m_copyState.sourceFileName.isEmpty()) - str << " Package/Source=" << d->m_copyState.sourceFileName; - if (!d->m_copyState.destinationFileName.isEmpty()) - str << " Remote Package/Destination=" << d->m_copyState.destinationFileName; + for (int i = 0; i < d->m_copyState.sourceFileNames.size(); ++i) { + str << " Package/Source=" << d->m_copyState.sourceFileNames.at(i); + str << " Remote Package/Destination=" << d->m_copyState.destinationFileNames.at(i); + } if (!d->m_downloadState.sourceFileName.isEmpty()) str << " Source=" << d->m_downloadState.sourceFileName; if (!d->m_downloadState.destinationFileName.isEmpty()) str << " Destination=" << d->m_downloadState.destinationFileName; - if (!d->m_installFileName.isEmpty()) - str << " Install file=" << d->m_installFileName; + if (!d->m_installFileNames.isEmpty()) + foreach (const QString &installFileName, d->m_installFileNames) + str << " Install file=" << installFileName; logMessage(msg); } if (d->m_startupActions & ActionCopy) { - if (d->m_copyState.sourceFileName.isEmpty()) { + if (d->m_copyState.sourceFileNames.isEmpty()) { qWarning("No local filename given for copying package."); return false; - } else if (d->m_copyState.destinationFileName.isEmpty()) { + } else if (d->m_copyState.destinationFileNames.isEmpty()) { qWarning("No remote filename given for copying package."); return false; } } - if (d->m_startupActions & ActionInstall && d->m_installFileName.isEmpty()) { + if (d->m_startupActions & ActionInstall && d->m_installFileNames.isEmpty()) { qWarning("No package name given for installing."); return false; } @@ -573,15 +586,15 @@ static inline QString msgCannotOpenLocalFile(const QString &fileName, const QStr void Launcher::handleFileCreation(const TrkResult &result) { if (result.errorCode() || result.data.size() < 6) { - const QString msg = msgCannotOpenRemoteFile(d->m_copyState.destinationFileName, result.errorString()); + const QString msg = msgCannotOpenRemoteFile(d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName), result.errorString()); logMessage(msg); - emit canNotCreateFile(d->m_copyState.destinationFileName, msg); + emit canNotCreateFile(d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName), msg); disconnectTrk(); return; } const char *data = result.data.data(); d->m_copyState.copyFileHandle = extractInt(data + 2); - const QString localFileName = d->m_copyState.sourceFileName; + const QString localFileName = d->m_copyState.sourceFileNames.at(d->m_copyState.currentFileName); QFile file(localFileName); d->m_copyState.position = 0; if (!file.open(QIODevice::ReadOnly)) { @@ -657,7 +670,7 @@ void Launcher::handleCopy(const TrkResult &result) { if (result.errorCode() || result.data.size() < 4) { closeRemoteFile(true); - emit canNotWriteFile(d->m_copyState.destinationFileName, result.errorString()); + emit canNotWriteFile(d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName), result.errorString()); disconnectTrk(); } else { continueCopying(extractShort(result.data.data() + 2)); @@ -693,7 +706,7 @@ void Launcher::closeRemoteFile(bool failed) d->m_device->sendTrkMessage(TrkCloseFile, failed ? TrkCallback() : TrkCallback(this, &Launcher::handleFileCopied), ba); - d->m_copyState.data.reset(); + d->m_copyState.data.reset(0); d->m_copyState.copyFileHandle = 0; d->m_copyState.position = 0; } @@ -701,15 +714,21 @@ void Launcher::closeRemoteFile(bool failed) void Launcher::handleFileCopied(const TrkResult &result) { if (result.errorCode()) - emit canNotCloseFile(d->m_copyState.destinationFileName, result.errorString()); - if (d->m_startupActions & ActionInstall) + emit canNotCloseFile(d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName), result.errorString()); + + ++d->m_copyState.currentFileName; + + if (d->m_startupActions & ActionInstall && d->m_copyState.currentFileName < d->m_copyState.sourceFileNames.size()) { + copyFileToRemote(); + } else if (d->m_startupActions & ActionInstall) { installRemotePackage(); - else if (d->m_startupActions & ActionRun) + } else if (d->m_startupActions & ActionRun) { startInferiorIfNeeded(); - else if (d->m_startupActions & ActionDownload) + } else if (d->m_startupActions & ActionDownload) { copyFileFromRemote(); - else + } else { disconnectTrk(); + } } void Launcher::handleCpuType(const TrkResult &result) @@ -856,7 +875,7 @@ void Launcher::copyFileToRemote() emit copyingStarted(); QByteArray ba; ba.append(char(10)); //kDSFileOpenWrite | kDSFileOpenBinary - appendString(&ba, d->m_copyState.destinationFileName.toLocal8Bit(), TargetByteOrder, false); + appendString(&ba, d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName).toLocal8Bit(), TargetByteOrder, false); d->m_device->sendTrkMessage(TrkOpenFile, TrkCallback(this, &Launcher::handleFileCreation), ba); } @@ -875,7 +894,7 @@ void Launcher::installRemotePackageSilently() d->m_currentInstallationStep = InstallationModeSilent; QByteArray ba; ba.append((char)QChar::toUpper((ushort)d->m_installationDrive)); - appendString(&ba, d->m_installFileName.toLocal8Bit(), TargetByteOrder, false); + appendString(&ba, d->m_installFileNames.at(d->m_currentInstallFileName).toLocal8Bit(), TargetByteOrder, false); d->m_device->sendTrkMessage(TrkInstallFile, TrkCallback(this, &Launcher::handleInstallPackageFinished), ba); } @@ -884,7 +903,7 @@ void Launcher::installRemotePackageByUser() emit installingStarted(); d->m_currentInstallationStep = InstallationModeUser; QByteArray ba; - appendString(&ba, d->m_installFileName.toLocal8Bit(), TargetByteOrder, false); + appendString(&ba, d->m_installFileNames.at(d->m_currentInstallFileName).toLocal8Bit(), TargetByteOrder, false); d->m_device->sendTrkMessage(TrkInstallFile2, TrkCallback(this, &Launcher::handleInstallPackageFinished), ba); } @@ -911,13 +930,19 @@ void Launcher::handleInstallPackageFinished(const TrkResult &result) installRemotePackageByUser(); return; } - emit canNotInstall(d->m_installFileName, result.errorString()); + emit canNotInstall(d->m_installFileNames.at(d->m_currentInstallFileName), result.errorString()); disconnectTrk(); return; - } else { - emit installingFinished(); } - if (d->m_startupActions & ActionRun) { + + ++d->m_currentInstallFileName; + + if (d->m_currentInstallFileName == d->m_installFileNames.size()) + emit installingFinished(); + + if (d->m_startupActions & ActionInstall && d->m_currentInstallFileName < d->m_installFileNames.size()) { + installRemotePackage(); + } else if (d->m_startupActions & ActionRun) { startInferiorIfNeeded(); } else if (d->m_startupActions & ActionDownload) { copyFileFromRemote(); @@ -973,6 +998,7 @@ void Launcher::startInferiorIfNeeded() logMessage("Process already 'started'"); return; } + d->m_device->sendTrkMessage(TrkCreateItem, TrkCallback(this, &Launcher::handleCreateProcess), startProcessMessage(d->m_fileName, d->m_commandLineArgs)); // Create Item } diff --git a/src/shared/symbianutils/launcher.h b/src/shared/symbianutils/launcher.h index c2270f1402fcadea1ff0acc2f1cc4a5042eeb10c..1a822f357bde93de903b4388d7333b7d1f16d330 100644 --- a/src/shared/symbianutils/launcher.h +++ b/src/shared/symbianutils/launcher.h @@ -89,9 +89,9 @@ public: void setTrkServerName(const QString &name); QString trkServerName() const; void setFileName(const QString &name); - void setCopyFileName(const QString &srcName, const QString &dstName); + void setCopyFileNames(const QStringList &srcName, const QStringList &dstName); void setDownloadFileName(const QString &srcName, const QString &dstName); - void setInstallFileName(const QString &name); + void setInstallFileNames(const QStringList &names); void setCommandLineArgs(const QStringList &args); bool startServer(QString *errorMessage); void setInstallationMode(InstallationMode installation);