Commit b254313c authored by Frantisek Vacek's avatar Frantisek Vacek Committed by Fanda Vacek

QNX: Use BarDescriptorDocument API to prepare bar-descriptor for deployment

Patch is refactoring create package step to use new BarDescriptorDocument
class when bar-descriptor.xml is prepared for deployment.

BarDescriptorDocument API is extended to allow this.

Change-Id: If00fba3310c5acf1cc8feefe0cf919aa2a05637e
Reviewed-by: default avatarTobias Nätterlund <tobias.naetterlund@kdab.com>
Reviewed-by: default avatarMehdi Fekari <mfekari@blackberry.com>
Reviewed-by: Nicolas Arnaud-Cormos's avatarNicolas Arnaud-Cormos <nicolas@kdab.com>
parent e24b5c17
......@@ -40,6 +40,7 @@
#include <QFileInfo>
#include <QMetaEnum>
#include <QTextCodec>
#include <QSet>
using namespace Qnx;
using namespace Qnx::Internal;
......@@ -573,3 +574,122 @@ void BarDescriptorDocument::emitAllChanged()
emit changed(tag, value(tag));
}
}
QString BarDescriptorDocument::bannerComment() const
{
QDomNode nd = m_barDocument.firstChild();
QDomProcessingInstruction pi = nd.toProcessingInstruction();
if (!pi.isNull())
nd = pi.nextSibling();
return nd.toComment().data();
}
void BarDescriptorDocument::setBannerComment(const QString &commentText)
{
QDomNode nd = m_barDocument.firstChild();
QDomProcessingInstruction pi = nd.toProcessingInstruction();
if (!pi.isNull())
nd = pi.nextSibling();
bool oldDirty = m_dirty;
QDomComment cnd = nd.toComment();
if (cnd.isNull()) {
if (!commentText.isEmpty()) {
cnd = m_barDocument.createComment(commentText);
m_barDocument.insertBefore(cnd, nd);
m_dirty = true;
}
} else {
if (commentText.isEmpty()) {
m_barDocument.removeChild(cnd);
m_dirty = true;
} else {
if (cnd.data() != commentText) {
cnd.setData(commentText);
m_dirty = true;
}
}
}
if (m_dirty != oldDirty)
emit Core::IDocument::changed();
}
int BarDescriptorDocument::tagForElement(const QDomElement &element)
{
QMetaEnum tags = metaObject()->enumerator(metaObject()->enumeratorOffset());
QDomElement el = element;
while (!el.isNull()) {
bool ok;
int n = tags.keyToValue(el.tagName().toLatin1().constData(), &ok);
if (ok)
return n;
el = el.parentNode().toElement();
}
return -1;
}
bool BarDescriptorDocument::expandPlaceHolder_helper(const QDomElement &el,
const QString &placeholderKey,
const QString &placeholderText,
QSet<BarDescriptorDocument::Tag> &changedTags)
{
// replace attributes
bool elementChanged = false;
QDomNamedNodeMap attrs = el.attributes();
for (int i = 0; i < attrs.count(); ++i) {
QDomAttr attr = attrs.item(i).toAttr();
if (!attr.isNull()) {
QString s = attr.value();
s.replace(placeholderKey, placeholderText);
if (s != attr.value()) {
attr.setValue(s);
elementChanged = true;
}
}
}
bool documentChanged = false;
// replace text
for (QDomNode nd = el.firstChild(); !nd.isNull(); nd = nd.nextSibling()) {
QDomText txtnd = nd.toText();
if (!txtnd.isNull()) {
QString s = txtnd.data();
s.replace(placeholderKey, placeholderText);
if (s != txtnd.data()) {
txtnd.setData(s);
elementChanged = true;
}
}
QDomElement child = nd.toElement();
if (!child.isNull()) {
bool hit = expandPlaceHolder_helper(child, placeholderKey, placeholderText, changedTags);
documentChanged = documentChanged || hit;
}
}
if (elementChanged) {
int n = tagForElement(el);
if (n >= 0)
changedTags << static_cast<Tag>(n);
}
documentChanged = documentChanged || elementChanged;
return documentChanged;
}
void BarDescriptorDocument::expandPlaceHolders(const QHash<QString, QString> &placeholdersKeyVals)
{
QSet<Tag> changedTags;
QHashIterator<QString, QString> it(placeholdersKeyVals);
bool docChanged = false;
while (it.hasNext()) {
it.next();
bool expanded = expandPlaceHolder_helper(m_barDocument.documentElement(),
it.key(), it.value(), changedTags);
docChanged = docChanged || expanded;
}
m_dirty = m_dirty || docChanged;
foreach (Tag tag, changedTags)
emit changed(tag, value(tag));
if (docChanged)
emit Core::IDocument::changed();
}
......@@ -105,12 +105,16 @@ public:
QVariant value(Tag tag) const;
void expandPlaceHolders(const QHash<QString, QString> &placeholdersKeyVals);
QString bannerComment() const;
void setBannerComment(const QString &commentText);
signals:
void changed(BarDescriptorDocument::Tag tag, const QVariant &value);
public slots:
void setValue(BarDescriptorDocument::Tag tag, const QVariant &value);
private:
QString stringValue(const QString &tagName) const;
void setStringValue(const QString &tagName, const QString &value);
......@@ -127,6 +131,11 @@ private:
QList<Utils::EnvironmentItem> environment() const;
void setEnvironment(const QList<Utils::EnvironmentItem> &environment);
int tagForElement(const QDomElement &element);
bool expandPlaceHolder_helper(const QDomElement &el, const QString &placeholderKey,
const QString &placeholderText,
QSet<BarDescriptorDocument::Tag> &changedTags);
void emitAllChanged();
bool m_dirty;
......
......@@ -39,6 +39,7 @@
#include "blackberrydeviceconfiguration.h"
#include "blackberrydeployinformation.h"
#include "blackberrysigningpasswordsdialog.h"
#include "bardescriptordocument.h"
#include <debugger/debuggerrunconfigurationaspect.h>
#include <projectexplorer/projectexplorerconstants.h>
......@@ -50,24 +51,12 @@
#include <qtsupport/qtkitinformation.h>
#include <utils/qtcassert.h>
#include <QFile>
using namespace Qnx;
using namespace Qnx::Internal;
namespace {
const char PACKAGER_CMD[] = "blackberry-nativepackager";
const char QT_INSTALL_LIBS[] = "QT_INSTALL_LIBS";
const char QT_INSTALL_LIBS_VAR[] = "%QT_INSTALL_LIBS%";
const char QT_INSTALL_PLUGINS[] = "QT_INSTALL_PLUGINS";
const char QT_INSTALL_PLUGINS_VAR[] = "%QT_INSTALL_PLUGINS%";
const char QT_INSTALL_IMPORTS[] = "QT_INSTALL_IMPORTS";
const char QT_INSTALL_IMPORTS_VAR[] = "%QT_INSTALL_IMPORTS%";
const char QT_INSTALL_QML[] = "QT_INSTALL_QML";
const char QT_INSTALL_QML_VAR[] = "%QT_INSTALL_QML%";
const char SRC_DIR_VAR[] = "%SRC_DIR%";
const char PACKAGE_MODE_KEY[] = "Qt4ProjectManager.BlackBerryCreatePackageStep.PackageMode";
const char CSK_PASSWORD_KEY[] = "Qt4ProjectManager.BlackBerryCreatePackageStep.CskPassword";
const char KEYSTORE_PASSWORD_KEY[] = "Qt4ProjectManager.BlackBerryCreatePackageStep.KeystorePassword";
......@@ -253,6 +242,13 @@ void BlackBerryCreatePackageStep::setSavePasswords(bool savePasswords)
m_savePasswords = savePasswords;
}
static void addQtInfoPlaceHolderToHash(QHash<QString, QString> &hash,
const BlackBerryQtVersion *qtVersion, const char *key)
{
hash[QLatin1Char('%') + QString::fromLatin1(key) + QLatin1Char('%')] =
qtVersion->versionInfo().value(QLatin1String(key));
}
bool BlackBerryCreatePackageStep::prepareAppDescriptorFile(const QString &appDescriptorPath, const QString &preparedFilePath)
{
BlackBerryQtVersion *qtVersion = dynamic_cast<BlackBerryQtVersion *>(QtSupport::QtKitInformation::qtVersion(target()->kit()));
......@@ -261,54 +257,62 @@ bool BlackBerryCreatePackageStep::prepareAppDescriptorFile(const QString &appDes
return false;
}
QFile file(appDescriptorPath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
raiseError(tr("Could not open '%1' for reading").arg(appDescriptorPath));
BarDescriptorDocument doc;
QString errorString;
if (!doc.open(&errorString, appDescriptorPath)) {
raiseError(tr("Error opening application descriptor file '%1' - %2")
.arg(QDir::toNativeSeparators(appDescriptorPath))
.arg(errorString));
return false;
}
QFile preparedFile(preparedFilePath);
QByteArray fileContent = file.readAll();
// Add Warning text
const QString warningText = QString::fromLatin1("<!-- This file is autogenerated;"
" any changes will get overwritten if deploying with Qt Creator -->\n<qnx");
fileContent.replace("<qnx", warningText.toLatin1());
const QString warningText = QString::fromLatin1("This file is autogenerated,"
" any changes will get overwritten if deploying with Qt Creator");
doc.setBannerComment(warningText);
// Replace Qt path placeholders
if (fileContent.contains(QT_INSTALL_LIBS_VAR))
fileContent.replace(QT_INSTALL_LIBS_VAR, qtVersion->versionInfo().value(QLatin1String(QT_INSTALL_LIBS)).toLatin1());
if (fileContent.contains(QT_INSTALL_PLUGINS_VAR))
fileContent.replace(QT_INSTALL_PLUGINS_VAR, qtVersion->versionInfo().value(QLatin1String(QT_INSTALL_PLUGINS)).toLatin1());
if (fileContent.contains(QT_INSTALL_IMPORTS_VAR))
fileContent.replace(QT_INSTALL_IMPORTS_VAR, qtVersion->versionInfo().value(QLatin1String(QT_INSTALL_IMPORTS)).toLatin1());
if (fileContent.contains(QT_INSTALL_QML_VAR))
fileContent.replace(QT_INSTALL_QML_VAR, qtVersion->versionInfo().value(QLatin1String(QT_INSTALL_QML)).toLatin1());
QHash<QString, QString> placeHoldersHash;
addQtInfoPlaceHolderToHash(placeHoldersHash, qtVersion, "QT_INSTALL_LIBS");
addQtInfoPlaceHolderToHash(placeHoldersHash, qtVersion, "QT_INSTALL_PLUGINS");
addQtInfoPlaceHolderToHash(placeHoldersHash, qtVersion, "QT_INSTALL_IMPORTS");
addQtInfoPlaceHolderToHash(placeHoldersHash, qtVersion, "QT_INSTALL_QML");
//Replace Source path placeholder
if (fileContent.contains(SRC_DIR_VAR))
fileContent.replace(SRC_DIR_VAR, QDir::toNativeSeparators(target()->project()->projectDirectory()).toLatin1());
placeHoldersHash[QLatin1String("%SRC_DIR%")] =
QDir::toNativeSeparators(target()->project()->projectDirectory());
doc.expandPlaceHolders(placeHoldersHash);
QStringList commandLineArguments = doc.value(BarDescriptorDocument::arg).toStringList();
QStringList extraCommandLineArguments;
// Add parameter for QML debugging (if enabled)
Debugger::DebuggerRunConfigurationAspect *aspect
= target()->activeRunConfiguration()->extraAspect<Debugger::DebuggerRunConfigurationAspect>();
if (aspect->useQmlDebugger()) {
if (!fileContent.contains("-qmljsdebugger")) {
const QString argString = QString::fromLatin1("<arg>-qmljsdebugger=port:%1</arg>\n</qnx>")
.arg(aspect->qmlDebugServerPort());
fileContent.replace("</qnx>", argString.toLatin1());
bool qmljsdebuggerExists = false;
foreach (const QString &s, commandLineArguments) {
if (s.startsWith(QLatin1String("-qmljsdebugger="))) {
qmljsdebuggerExists = true;
break;
}
}
if (!qmljsdebuggerExists) {
extraCommandLineArguments << QString::fromLatin1("-qmljsdebugger=port:%1")
.arg(aspect->qmlDebugServerPort());
}
}
if (!preparedFile.open(QIODevice::WriteOnly)) {
const QString buildDir = target()->activeBuildConfiguration()->buildDirectory().toUserOutput();
raiseError(tr("Could not create prepared application descriptor file in '%1'").arg(buildDir));
return false;
if (extraCommandLineArguments.count()) {
commandLineArguments << extraCommandLineArguments;
doc.setValue(BarDescriptorDocument::arg, commandLineArguments);
}
preparedFile.write(fileContent);
preparedFile.close();
doc.setFilePath(preparedFilePath);
if (!doc.save(&errorString)) {
raiseError(tr("Error saving prepared application descriptor file '%1' - %2")
.arg(QDir::toNativeSeparators(preparedFilePath))
.arg(errorString));
return false;
}
return true;
}
......
......@@ -331,6 +331,67 @@ void QNXPlugin::testBarDescriptorDocumentSetValue()
QCOMPARE(doc.value(tag), value);
}
void QNXPlugin::testBarDescriptorDocumentSetBannerComment_data()
{
QTest::addColumn<QString>("comment");
QTest::addColumn<QString>("baseXml");
QTest::addColumn<QString>("xml");
QString procInstr = QString::fromLatin1("<?xml version='1.0' encoding='UTF-8' standalone='no'?>");
QString comment = QString::fromLatin1("This file is autogenerated, any change will be ...");
QString xmlComment = QString::fromLatin1("<!--%1-->").arg(comment);
QString oldXmlComment = QString::fromLatin1("<!-- Some old banner comment -->");
QString docRoot = QString::fromLatin1("<qnx xmlns=\"http://www.qnx.com/schemas/application/1.0\"/>");
QChar lf = QChar::fromLatin1('\n');
QTest::newRow("new-comment")
<< comment
<< QString(procInstr + lf + docRoot + lf)
<< QString(procInstr + lf + xmlComment + lf + docRoot + lf);
QTest::newRow("new-comment-noproc")
<< comment
<< QString(docRoot + lf)
<< QString(xmlComment + lf + docRoot + lf);
QTest::newRow("replace-comment")
<< comment
<< QString(procInstr + lf + oldXmlComment + lf + docRoot + lf)
<< QString(procInstr + lf + xmlComment + lf + docRoot + lf);
QTest::newRow("replace-comment-noproc")
<< comment
<< QString(oldXmlComment + lf + docRoot + lf)
<< QString(xmlComment + lf + docRoot + lf);
QTest::newRow("remove-comment")
<< QString()
<< QString(procInstr + lf + oldXmlComment + lf + docRoot + lf)
<< QString(procInstr + lf + docRoot + lf);
QTest::newRow("remove-comment-noproc")
<< QString()
<< QString(oldXmlComment + lf + docRoot + lf)
<< QString(docRoot + lf);
}
void QNXPlugin::testBarDescriptorDocumentSetBannerComment()
{
QFETCH(QString, comment);
QFETCH(QString, baseXml);
QFETCH(QString, xml);
BarDescriptorDocument doc;
doc.loadContent(baseXml, false);
QCOMPARE(doc.xmlSource(), baseXml);
doc.setBannerComment(comment);
QCOMPARE(doc.xmlSource(), xml);
QCOMPARE(doc.isModified(), true);
QCOMPARE(doc.bannerComment(), comment);
}
#endif
Q_EXPORT_PLUGIN2(QNX, QNXPlugin)
......@@ -54,6 +54,9 @@ public:
private slots:
void testBarDescriptorDocumentSetValue_data();
void testBarDescriptorDocumentSetValue();
void testBarDescriptorDocumentSetBannerComment_data();
void testBarDescriptorDocumentSetBannerComment();
#endif
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment