Files
qt-creator/src/plugins/qt4projectmanager/qt-maemo/maemoqemuruntimeparser.cpp

432 lines
17 KiB
C++
Raw Normal View History

/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
2010-12-17 17:14:20 +01:00
** No Commercial Usage
**
2010-12-17 17:14:20 +01:00
** 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.
**
2010-12-17 17:14:20 +01:00
** 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 "maemoqemuruntimeparser.h"
#include "maemoglobal.h"
#include "maemoqemusettings.h"
#include <qt4projectmanager/qtversionmanager.h>
#include <utils/qtcassert.h>
#include <QtCore/QDir>
#include <QtCore/QProcess>
#include <QtCore/QStringList>
#include <QtCore/QTextStream>
namespace Qt4ProjectManager {
namespace Internal {
class MaemoQemuRuntimeParserV1 : public MaemoQemuRuntimeParser
{
public:
MaemoQemuRuntimeParserV1(const QString &madInfoOutput,
const QString &targetName, const QString &maddeRoot);
MaemoQemuRuntime parseRuntime();
private:
void fillRuntimeInformation(MaemoQemuRuntime *runtime) const;
void setEnvironment(MaemoQemuRuntime *runTime, const QString &envSpec) const;
};
class MaemoQemuRuntimeParserV2 : public MaemoQemuRuntimeParser
{
public:
MaemoQemuRuntimeParserV2(const QString &madInfoOutput,
const QString &targetName, const QString &maddeRoot);
MaemoQemuRuntime parseRuntime();
private:
struct Port {
2010-12-03 15:02:26 +01:00
Port() : port(-1), ssh(false) {}
int port;
bool ssh;
};
void handleTargetTag(QString &runtimeName);
MaemoQemuRuntime handleRuntimeTag();
void handleEnvironmentTag(MaemoQemuRuntime &runtime);
void handleVariableTag(MaemoQemuRuntime &runtime);
QList<Port> handleTcpPortListTag();
Port handlePortTag();
MaemoQemuSettings::OpenGlMode openGlTagToEnum(const QString &tag) const;
};
MaemoQemuRuntimeParser::MaemoQemuRuntimeParser(const QString &madInfoOutput,
const QString &targetName, const QString &maddeRoot)
: m_targetName(targetName),
m_maddeRoot(maddeRoot),
m_madInfoReader(madInfoOutput)
{
}
MaemoQemuRuntime MaemoQemuRuntimeParser::parseRuntime(const QtVersion *qtVersion)
{
MaemoQemuRuntime runtime;
const QString maddeRootPath = MaemoGlobal::maddeRoot(qtVersion);
QProcess madProc;
if (!MaemoGlobal::callMad(madProc, QStringList() << QLatin1String("info"), qtVersion))
return runtime;
if (!madProc.waitForStarted() || !madProc.waitForFinished())
return runtime;
const QByteArray &madInfoOutput = madProc.readAllStandardOutput();
const QString &targetName = MaemoGlobal::targetName(qtVersion);
runtime = MaemoQemuRuntimeParserV2(madInfoOutput, targetName, maddeRootPath)
.parseRuntime();
if (!runtime.m_name.isEmpty()) {
runtime.m_root = maddeRootPath + QLatin1String("/runtimes/")
+ runtime.m_name;
} else {
runtime = MaemoQemuRuntimeParserV1(madInfoOutput, targetName,
maddeRootPath).parseRuntime();
}
runtime.m_watchPath = runtime.m_root
.left(runtime.m_root.lastIndexOf(QLatin1Char('/')));
return runtime;
}
MaemoQemuRuntimeParserV1::MaemoQemuRuntimeParserV1(const QString &madInfoOutput,
const QString &targetName, const QString &maddeRoot)
: MaemoQemuRuntimeParser(madInfoOutput, targetName, maddeRoot)
{
}
MaemoQemuRuntime MaemoQemuRuntimeParserV1::parseRuntime()
{
QStringList installedRuntimes;
QString targetRuntime;
while (!m_madInfoReader.atEnd() && !installedRuntimes.contains(targetRuntime)) {
if (m_madInfoReader.readNext() == QXmlStreamReader::StartElement) {
if (targetRuntime.isEmpty()
&& m_madInfoReader.name() == QLatin1String("target")) {
const QXmlStreamAttributes &attrs = m_madInfoReader.attributes();
if (attrs.value(QLatin1String("target_id")) == m_targetName)
targetRuntime = attrs.value("runtime_id").toString();
} else if (m_madInfoReader.name() == QLatin1String("runtime")) {
const QXmlStreamAttributes attrs = m_madInfoReader.attributes();
while (!m_madInfoReader.atEnd()) {
if (m_madInfoReader.readNext() == QXmlStreamReader::EndElement
&& m_madInfoReader.name() == QLatin1String("runtime"))
break;
if (m_madInfoReader.tokenType() == QXmlStreamReader::StartElement
&& m_madInfoReader.name() == QLatin1String("installed")) {
if (m_madInfoReader.readNext() == QXmlStreamReader::Characters
&& m_madInfoReader.text() == QLatin1String("true")) {
if (attrs.hasAttribute(QLatin1String("runtime_id")))
installedRuntimes << attrs.value(QLatin1String("runtime_id")).toString();
else if (attrs.hasAttribute(QLatin1String("id"))) {
// older MADDE seems to use only id
installedRuntimes << attrs.value(QLatin1String("id")).toString();
}
}
break;
}
}
}
}
}
MaemoQemuRuntime runtime;
if (installedRuntimes.contains(targetRuntime)) {
runtime.m_name = targetRuntime;
runtime.m_root = m_maddeRoot + QLatin1String("/runtimes/")
+ targetRuntime;
fillRuntimeInformation(&runtime);
}
return runtime;
}
void MaemoQemuRuntimeParserV1::fillRuntimeInformation(MaemoQemuRuntime *runtime) const
{
const QStringList files = QDir(runtime->m_root).entryList(QDir::Files
| QDir::NoSymLinks | QDir::NoDotAndDotDot);
const QLatin1String infoFile("information");
if (files.contains(infoFile)) {
QFile file(runtime->m_root + QLatin1Char('/') + infoFile);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QMap<QString, QString> map;
QTextStream stream(&file);
while (!stream.atEnd()) {
const QString &line = stream.readLine().trimmed();
const int index = line.indexOf(QLatin1Char('='));
map.insert(line.mid(0, index).remove(QLatin1Char('\'')),
line.mid(index + 1).remove(QLatin1Char('\'')));
}
runtime->m_bin = map.value(QLatin1String("qemu"));
runtime->m_args = map.value(QLatin1String("qemu_args"));
setEnvironment(runtime, map.value(QLatin1String("libpath")));
runtime->m_sshPort = map.value(QLatin1String("sshport"));
runtime->m_freePorts = MaemoPortList();
int i = 2;
while (true) {
const QString port = map.value(QLatin1String("redirport")
+ QString::number(i++));
if (port.isEmpty())
break;
runtime->m_freePorts.addPort(port.toInt());
}
// This is complex because of extreme MADDE weirdness.
const QString root = m_maddeRoot + QLatin1Char('/');
const bool pathIsRelative = QFileInfo(runtime->m_bin).isRelative();
runtime->m_bin =
#ifdef Q_OS_WIN
root + (pathIsRelative
? QLatin1String("madlib/") + runtime->m_bin // Fremantle.
: runtime->m_bin) // Harmattan.
+ QLatin1String(".exe");
#else
pathIsRelative
? root + QLatin1String("madlib/") + runtime->m_bin // Fremantle.
: runtime->m_bin; // Harmattan.
#endif
}
}
}
void MaemoQemuRuntimeParserV1::setEnvironment(MaemoQemuRuntime *runTime,
const QString &envSpec) const
{
QString remainingEnvSpec = envSpec;
QString currentKey;
while (true) {
const int nextEqualsSignPos
= remainingEnvSpec.indexOf(QLatin1Char('='));
if (nextEqualsSignPos == -1) {
if (!currentKey.isEmpty())
runTime->m_normalVars << MaemoQemuRuntime::Variable(currentKey,
remainingEnvSpec);
break;
}
const int keyStartPos
= remainingEnvSpec.lastIndexOf(QRegExp(QLatin1String("\\s")),
nextEqualsSignPos) + 1;
if (!currentKey.isEmpty()) {
const int valueEndPos
= remainingEnvSpec.lastIndexOf(QRegExp(QLatin1String("\\S")),
qMax(0, keyStartPos - 1)) + 1;
runTime->m_normalVars << MaemoQemuRuntime::Variable(currentKey,
remainingEnvSpec.left(valueEndPos));
}
currentKey = remainingEnvSpec.mid(keyStartPos,
nextEqualsSignPos - keyStartPos);
remainingEnvSpec.remove(0, nextEqualsSignPos + 1);
}
}
MaemoQemuRuntimeParserV2::MaemoQemuRuntimeParserV2(const QString &madInfoOutput,
const QString &targetName, const QString &maddeRoot)
: MaemoQemuRuntimeParser(madInfoOutput, targetName, maddeRoot)
{
}
MaemoQemuRuntime MaemoQemuRuntimeParserV2::parseRuntime()
{
QString runtimeName;
QList<MaemoQemuRuntime> runtimes;
while (m_madInfoReader.readNextStartElement()) {
if (m_madInfoReader.name() == QLatin1String("madde")) {
while (m_madInfoReader.readNextStartElement()) {
if (m_madInfoReader.name() == QLatin1String("targets")) {
while (m_madInfoReader.readNextStartElement())
handleTargetTag(runtimeName);
} else if (m_madInfoReader.name() == QLatin1String("runtimes")) {
while (m_madInfoReader.readNextStartElement()) {
const MaemoQemuRuntime &rt = handleRuntimeTag();
if (!rt.m_name.isEmpty() && !rt.m_bin.isEmpty()
&& !rt.m_args.isEmpty()) {
runtimes << rt;
}
}
} else {
m_madInfoReader.skipCurrentElement();
}
}
}
}
foreach (const MaemoQemuRuntime &rt, runtimes) {
if (rt.m_name == runtimeName)
return rt;
}
return MaemoQemuRuntime();
}
void MaemoQemuRuntimeParserV2::handleTargetTag(QString &runtimeName)
{
const QXmlStreamAttributes &attrs = m_madInfoReader.attributes();
if (m_madInfoReader.name() == QLatin1String("target") && runtimeName.isEmpty()
&& attrs.value(QLatin1String("name")) == m_targetName
&& attrs.value(QLatin1String("installed")) == QLatin1String("true")) {
while (m_madInfoReader.readNextStartElement()) {
if (m_madInfoReader.name() == QLatin1String("runtime"))
runtimeName = m_madInfoReader.readElementText();
else
m_madInfoReader.skipCurrentElement();
}
} else {
m_madInfoReader.skipCurrentElement();
}
}
MaemoQemuRuntime MaemoQemuRuntimeParserV2::handleRuntimeTag()
{
MaemoQemuRuntime runtime;
const QXmlStreamAttributes &attrs = m_madInfoReader.attributes();
if (m_madInfoReader.name() != QLatin1String("runtime")
|| attrs.value(QLatin1String("installed")) != QLatin1String("true")) {
m_madInfoReader.skipCurrentElement();
return runtime;
}
runtime.m_name = attrs.value(QLatin1String("name")).toString();
while (m_madInfoReader.readNextStartElement()) {
if (m_madInfoReader.name() == QLatin1String("exec-path")) {
runtime.m_bin = m_madInfoReader.readElementText();
} else if (m_madInfoReader.name() == QLatin1String("args")) {
runtime.m_args = m_madInfoReader.readElementText();
} else if (m_madInfoReader.name() == QLatin1String("environment")) {
handleEnvironmentTag(runtime);
} else if (m_madInfoReader.name() == QLatin1String("tcpportmap")) {
const QList<Port> &ports = handleTcpPortListTag();
foreach (const Port &port, ports) {
if (port.ssh)
runtime.m_sshPort = QString::number(port.port);
else
runtime.m_freePorts.addPort(port.port);
}
} else {
m_madInfoReader.skipCurrentElement();
}
}
return runtime;
}
void MaemoQemuRuntimeParserV2::handleEnvironmentTag(MaemoQemuRuntime &runtime)
{
while (m_madInfoReader.readNextStartElement())
handleVariableTag(runtime);
#ifdef Q_OS_WIN
const QString root = QDir::toNativeSeparators(m_maddeRoot)
+ QLatin1Char('/');
const QLatin1Char colon(';');
const QLatin1String key("PATH");
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
runtime.m_normalVars << MaemoQemuRuntime::Variable(key,
root + QLatin1String("bin") + colon + env.value(key));
runtime.m_normalVars << MaemoQemuRuntime::Variable(key,
root + QLatin1String("madlib") + colon + env.value(key));
#endif
}
void MaemoQemuRuntimeParserV2::handleVariableTag(MaemoQemuRuntime &runtime)
{
if (m_madInfoReader.name() != QLatin1String("variable")) {
m_madInfoReader.skipCurrentElement();
return;
}
const bool isGlBackend = m_madInfoReader.attributes().value(QLatin1String("purpose"))
== QLatin1String("glbackend");
QString varName;
QString varValue;
while (m_madInfoReader.readNextStartElement()) {
const QXmlStreamAttributes &attrs = m_madInfoReader.attributes();
if (m_madInfoReader.name() == QLatin1String("name")) {
varName = m_madInfoReader.readElementText();
} else if (m_madInfoReader.name() == QLatin1String("value")
&& attrs.value(QLatin1String("set")) != QLatin1String("false")) {
varValue = m_madInfoReader.readElementText();
if (isGlBackend) {
MaemoQemuSettings::OpenGlMode openGlMode
= openGlTagToEnum(attrs.value(QLatin1String("option")).toString());
runtime.m_openGlBackendVarValues.insert(openGlMode, varValue);
}
} else {
m_madInfoReader.skipCurrentElement();
}
}
if (varName.isEmpty())
return;
if (isGlBackend) {
runtime.m_openGlBackendVarName = varName;
} else {
runtime.m_normalVars << MaemoQemuRuntime::Variable(varName, varValue);
}
}
QList<MaemoQemuRuntimeParserV2::Port> MaemoQemuRuntimeParserV2::handleTcpPortListTag()
{
QList<Port> ports;
while (m_madInfoReader.readNextStartElement()) {
const Port &port = handlePortTag();
if (port.port != -1)
ports << port;
}
return ports;
}
MaemoQemuRuntimeParserV2::Port MaemoQemuRuntimeParserV2::handlePortTag()
{
Port port;
if (m_madInfoReader.name() == QLatin1String("port")) {
const QXmlStreamAttributes &attrs = m_madInfoReader.attributes();
port.ssh = attrs.value(QLatin1String("service")) == QLatin1String("ssh");
while (m_madInfoReader.readNextStartElement()) {
if (m_madInfoReader.name() == QLatin1String("host"))
port.port = m_madInfoReader.readElementText().toInt();
else
m_madInfoReader.skipCurrentElement();
}
}
return port;
}
MaemoQemuSettings::OpenGlMode MaemoQemuRuntimeParserV2::openGlTagToEnum(const QString &tag) const
{
if (tag == QLatin1String("hardware-acceleration"))
return MaemoQemuSettings::HardwareAcceleration;
if (tag == QLatin1String("software-rendering"))
return MaemoQemuSettings::SoftwareRendering;
if (tag == QLatin1String("autodetect"))
return MaemoQemuSettings::AutoDetect;
QTC_ASSERT(false, return MaemoQemuSettings::AutoDetect);
}
} // namespace Internal
} // namespace Qt4ProjectManager