summaryrefslogtreecommitdiff
path: root/src/plugins/qnx/bardescriptordocument.cpp
diff options
context:
space:
mode:
authorTobias Naetterlund <tobias.naetterlund.qnx@kdab.com>2013-12-23 15:36:42 +0100
committerTobias Nätterlund <tobias.naetterlund@kdab.com>2014-01-27 06:52:23 +0100
commit3994e698cd9c59a2bbc0ab2578df9f322f54cf7f (patch)
treeab6d6455f88cc510cf5c881cbaa4df66171389a3 /src/plugins/qnx/bardescriptordocument.cpp
parent717e384bb58d5522ad17402ecd12a336c389188f (diff)
downloadqt-creator-3994e698cd9c59a2bbc0ab2578df9f322f54cf7f.tar.gz
BlackBerry: Refactored BarDescriptorDocument
The BarDescriptorDocument now operates directly on the underlying QDomDocument, and is much better at keeping the tags on their original lines. Any new values are appended to the end of the document. A generic API is provided for changing the values inside the document, BarDescriptorDocument::setValue(..). BarDescriptorDocument no longer depends on the BarDescriptorEditorWidget, which should make it easier to implement splitting of the editor. Task-number: QTCREATORBUG-11012 Change-Id: Icfd681e3af016ea819b99b8cad2cede46600e910 Reviewed-by: Nicolas Arnaud-Cormos <nicolas@kdab.com> Reviewed-by: Mehdi Fekari <mfekari@blackberry.com> Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com>
Diffstat (limited to 'src/plugins/qnx/bardescriptordocument.cpp')
-rw-r--r--src/plugins/qnx/bardescriptordocument.cpp499
1 files changed, 406 insertions, 93 deletions
diff --git a/src/plugins/qnx/bardescriptordocument.cpp b/src/plugins/qnx/bardescriptordocument.cpp
index bee30de62d..b07c92daee 100644
--- a/src/plugins/qnx/bardescriptordocument.cpp
+++ b/src/plugins/qnx/bardescriptordocument.cpp
@@ -32,47 +32,21 @@
#include "bardescriptordocument.h"
#include "qnxconstants.h"
-#include "bardescriptoreditor.h"
-#include "bardescriptoreditorwidget.h"
-#include "bardescriptordocumentnodehandlers.h"
-#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/editormanager/editormanager.h>
#include <utils/qtcassert.h>
-#include <QFile>
-#include <QFileInfo>
#include <QDir>
+#include <QFileInfo>
+#include <QMetaEnum>
#include <QTextCodec>
using namespace Qnx;
using namespace Qnx::Internal;
-BarDescriptorDocument::BarDescriptorDocument(BarDescriptorEditorWidget *editorWidget)
- : Core::TextDocument(editorWidget)
- , m_nodeHandlers(QList<BarDescriptorDocumentAbstractNodeHandler *>())
- , m_editorWidget(editorWidget)
+BarDescriptorDocument::BarDescriptorDocument(QObject *parent)
+ : Core::TextDocument(parent)
{
- // General
- registerNodeHandler(new BarDescriptorDocumentIdNodeHandler(m_editorWidget));
- registerNodeHandler(new BarDescriptorDocumentVersionNumberNodeHandler(m_editorWidget));
- registerNodeHandler(new BarDescriptorDocumentBuildIdNodeHandler(m_editorWidget));
- registerNodeHandler(new BarDescriptorDocumentAuthorNodeHandler(m_editorWidget));
- registerNodeHandler(new BarDescriptorDocumentAuthorIdNodeHandler(m_editorWidget));
-
- // Application
- registerNodeHandler(new BarDescriptorDocumentApplicationNameNodeHandler(m_editorWidget));
- registerNodeHandler(new BarDescriptorDocumentApplicationDescriptionNodeHandler(m_editorWidget));
- registerNodeHandler(new BarDescriptorDocumentApplicationIconNodeHandler(m_editorWidget));
- registerNodeHandler(new BarDescriptorDocumentSplashScreenNodeHandler(m_editorWidget));
- registerNodeHandler(new BarDescriptorDocumentInitialWindowNodeHandler(m_editorWidget));
- registerNodeHandler(new BarDescriptorDocumentArgNodeHandler(m_editorWidget));
- registerNodeHandler(new BarDescriptorDocumentActionNodeHandler(m_editorWidget));
- registerNodeHandler(new BarDescriptorDocumentEnvNodeHandler(m_editorWidget));
-
- // Assets
- registerNodeHandler(new BarDescriptorDocumentAssetNodeHandler(m_editorWidget));
-
// blackberry-nativepackager requires the XML file to be in UTF-8 encoding,
// force if possible
if (QTextCodec *defaultUTF8 = QTextCodec::codecForName("UTF-8"))
@@ -83,10 +57,6 @@ BarDescriptorDocument::BarDescriptorDocument(BarDescriptorEditorWidget *editorWi
BarDescriptorDocument::~BarDescriptorDocument()
{
- while (!m_nodeHandlers.isEmpty()) {
- BarDescriptorDocumentAbstractNodeHandler *nodeHandler = m_nodeHandlers.takeFirst();
- delete nodeHandler;
- }
}
bool BarDescriptorDocument::open(QString *errorString, const QString &fileName) {
@@ -95,9 +65,8 @@ bool BarDescriptorDocument::open(QString *errorString, const QString &fileName)
return false;
setFilePath(fileName);
- m_editorWidget->setFilePath(fileName);
- bool result = loadContent(contents);
+ const bool result = loadContent(contents, false);
if (!result)
*errorString = tr("%1 does not appear to be a valid application descriptor file").arg(QDir::toNativeSeparators(fileName));
@@ -110,12 +79,12 @@ bool BarDescriptorDocument::save(QString *errorString, const QString &fn, bool a
QTC_ASSERT(!autoSave, return false);
QTC_ASSERT(fn.isEmpty(), return false);
- bool result = write(filePath(), xmlSource(), errorString);
+ const bool result = write(filePath(), xmlSource(), errorString);
if (!result)
return false;
- m_editorWidget->setDirty(false);
- emit changed();
+ m_dirty = false;
+ emit Core::IDocument::changed();
return true;
}
@@ -143,7 +112,7 @@ bool BarDescriptorDocument::shouldAutoSave() const
bool BarDescriptorDocument::isModified() const
{
- return m_editorWidget->isDirty();
+ return m_dirty;
}
bool BarDescriptorDocument::isSaveAsAllowed() const
@@ -172,91 +141,435 @@ bool BarDescriptorDocument::reload(QString *errorString, Core::IDocument::Reload
QString BarDescriptorDocument::xmlSource() const
{
- BarDescriptorEditor *editor = qobject_cast<BarDescriptorEditor*>(m_editorWidget->editor());
- QTC_ASSERT(editor, return QString());
+ const int indent = 4;
+ return m_barDocument.toString(indent);
+}
+
+bool BarDescriptorDocument::loadContent(const QString &xmlCode, bool setDirty, QString *errorMessage, int *errorLine)
+{
+ if (xmlCode == xmlSource())
+ return true;
+
+ bool result = m_barDocument.setContent(xmlCode, errorMessage, errorLine);
+
+ m_dirty = setDirty;
+
+ emitAllChanged();
+ emit Core::IDocument::changed();
+ return result;
+}
+
+QVariant BarDescriptorDocument::value(BarDescriptorDocument::Tag tag) const
+{
+ const QString tagName = QString::fromLatin1(metaObject()->enumerator(metaObject()->enumeratorOffset()).valueToKey(tag));
+
+ switch (tag) {
+ case id:
+ case versionNumber:
+ case buildId:
+ case name:
+ case description:
+ case author:
+ case publisher:
+ case authorId:
+ return stringValue(tagName);
+ case icon:
+ return childStringListValue(tagName, QLatin1String("image")).value(0);
+ case splashScreens:
+ return childStringListValue(tagName, QLatin1String("image"));
+ case asset: {
+ QVariant var;
+ var.setValue(assets());
+ return var;
+ }
+ case aspectRatio:
+ case autoOrients:
+ case systemChrome:
+ return childStringListValue(QLatin1String("initialWindow"), tagName).value(0);
+ case transparent:
+ return childStringListValue(QLatin1String("initialWindow"), tagName).value(0) == QLatin1String("true");
+ case arg:
+ case action:
+ return stringListValue(tagName);
+ case env:
+ QVariant var;
+ var.setValue(environment());
+ return var;
+ }
+
+ return QVariant();
+}
+
+void BarDescriptorDocument::setValue(BarDescriptorDocument::Tag tag, const QVariant &value)
+{
+ const QMetaEnum tagEnum = metaObject()->enumerator(metaObject()->enumeratorOffset());
+ const QString tagName = QString::fromLatin1(tagEnum.valueToKey(tag));
+
+ switch (tag) {
+ case id:
+ case versionNumber:
+ case buildId:
+ case name:
+ case description:
+ case authorId:
+ setStringValue(tagName, value.toString());
+ break;
+ case icon:
+ case splashScreens:
+ setChildStringListValue(tagName, QLatin1String("image"), value.toStringList());
+ break;
+ case asset:
+ setAssets(value.value<BarDescriptorAssetList>());
+ break;
+ case aspectRatio:
+ case autoOrients:
+ case systemChrome:
+ setChildStringListValue(QLatin1String("initialWindow"), tagName, value.toStringList());
+ break;
+ case transparent:
+ setChildStringListValue(QLatin1String("initialWindow"), tagName, QStringList() << (value.toBool() ? QLatin1String("true") : QLatin1String("false")));
+ break;
+ case arg:
+ case action:
+ setStringListValue(tagName, value.toStringList());
+ break;
+ case env:
+ setEnvironment(value.value<QList<Utils::EnvironmentItem> >());
+ break;
+ case author:
+ case publisher:
+ // Unset <publisher> when setting <author> as only one should be used
+ setStringValue(QString::fromLatin1(tagEnum.valueToKey(author)), value.toString());
+ setStringValue(QString::fromLatin1(tagEnum.valueToKey(publisher)), QLatin1String(""));
+ break;
+ }
+
+ m_dirty = true;
+ emit changed(tag, value);
+ emit Core::IDocument::changed();
+}
+
+QString BarDescriptorDocument::stringValue(const QString &tagName) const
+{
+ QDomNodeList nodes = m_barDocument.elementsByTagName(tagName);
+ if (nodes.isEmpty() || nodes.size() > 1)
+ return QString();
+
+ QDomNode node = nodes.item(0);
+ QDomText textNode = node.firstChild().toText();
+ if (textNode.isNull())
+ return QString();
+
+ return textNode.data();
+}
+
+void BarDescriptorDocument::setStringValue(const QString &tagName, const QString &value)
+{
+ QDomNodeList nodes = m_barDocument.elementsByTagName(tagName);
+
+ if (nodes.size() > 1)
+ return;
- if (editor->activePage() == BarDescriptorEditor::Source) {
- return m_editorWidget->xmlSource();
+ QDomNode existingNode = nodes.item(0);
+ if (existingNode.isNull() && value.isEmpty())
+ return;
+
+ if (!existingNode.isNull() && value.isEmpty()) {
+ m_barDocument.documentElement().removeChild(existingNode);
+ } else if (existingNode.isNull()) {
+ QDomElement newNode = m_barDocument.createElement(tagName);
+ newNode.appendChild(m_barDocument.createTextNode(value));
+ m_barDocument.documentElement().appendChild(newNode);
} else {
- QDomDocument doc;
- doc.appendChild(doc.createProcessingInstruction(QLatin1String("xml"), QLatin1String("version='1.0' encoding='") + QLatin1String(codec()->name()) + QLatin1String("' standalone='no'")));
+ QDomText textNode = existingNode.firstChild().toText();
+ if (textNode.isNull())
+ return;
+ textNode.setData(value);
+ }
+}
- // QNX
- QDomElement rootElem = doc.createElement(QLatin1String("qnx"));
- rootElem.setAttribute(QLatin1String("xmlns"), QLatin1String("http://www.qnx.com/schemas/application/1.0"));
+QStringList BarDescriptorDocument::childStringListValue(const QString &tagName, const QString &childTagName) const
+{
+ QDomNodeList nodes = m_barDocument.elementsByTagName(tagName);
+ if (nodes.isEmpty() || nodes.size() > 1)
+ return QStringList();
- QMap<int, BarDescriptorDocumentAbstractNodeHandler*> nodeHandlerMap;
- foreach (BarDescriptorDocumentAbstractNodeHandler *nodeHandler, m_nodeHandlers)
- nodeHandlerMap.insertMulti(nodeHandler->order(), nodeHandler);
+ QDomNode parentNode = nodes.item(0);
+ QDomElement childElm = parentNode.firstChildElement(childTagName);
+ if (childElm.isNull())
+ return QStringList();
- QList<BarDescriptorDocumentAbstractNodeHandler*> nodeHandlers = nodeHandlerMap.values();
- foreach (BarDescriptorDocumentAbstractNodeHandler *nodeHandler, nodeHandlers)
- rootElem.appendChild(nodeHandler->toNode(doc));
+ QStringList result;
+ while (!childElm.isNull()) {
+ QDomText textNode = childElm.firstChild().toText();
+ if (textNode.isNull())
+ return QStringList();
- doc.appendChild(rootElem);
+ result.append(textNode.data());
- return doc.toString(4);
+ childElm = childElm.nextSiblingElement(childTagName);
}
+
+ return result;
}
-bool BarDescriptorDocument::loadContent(const QString &xmlSource, QString *errorMessage, int *errorLine)
+void BarDescriptorDocument::setChildStringListValue(const QString &tagName, const QString &childTagName, const QStringList &stringList)
{
- QDomDocument doc;
- bool result = doc.setContent(xmlSource, errorMessage, errorLine);
- if (!result)
- return false;
+ QDomNodeList nodes = m_barDocument.elementsByTagName(tagName);
- QDomElement docElem = doc.documentElement();
- if (docElem.tagName() != QLatin1String("qnx"))
- return false;
+ if (nodes.size() > 1)
+ return;
- m_editorWidget->clear();
+ QDomNode existingNode = nodes.item(0);
- removeUnknownNodeHandlers();
- foreach (BarDescriptorDocumentAbstractNodeHandler *nodeHandler, m_nodeHandlers)
- nodeHandler->clear();
+ if (existingNode.isNull()) {
+ QDomElement newParentNode = m_barDocument.createElement(tagName);
- QDomNode node = docElem.firstChildElement();
- while (!node.isNull()) {
- BarDescriptorDocumentAbstractNodeHandler *nodeHandler = nodeHandlerForDomNode(node);
- if (!nodeHandler) {
- nodeHandler = new BarDescriptorDocumentUnknownNodeHandler(m_editorWidget);
- registerNodeHandler(nodeHandler);
+ foreach (const QString &value, stringList) {
+ QDomElement newChildNode = m_barDocument.createElement(childTagName);
+ QDomText newTextNode = m_barDocument.createTextNode(value);
+ newChildNode.appendChild(newTextNode);
+ newParentNode.appendChild(newChildNode);
+ }
+ m_barDocument.documentElement().appendChild(newParentNode);
+ } else {
+ QStringList values = stringList;
+ QDomElement childElm = existingNode.firstChildElement(childTagName);
+ if (!childElm.isNull()) {
+ // Loop through existing elements, remove the existing nodes
+ // that no longer are in "values", and remove from "values"
+ // the existing nodes that don't need re-creation
+ while (!childElm.isNull()) {
+ QDomText textNode = childElm.firstChild().toText();
+ if (textNode.isNull())
+ continue;
+
+ QDomElement toRemove;
+ if (!values.contains(textNode.data()))
+ toRemove = childElm;
+ else
+ values.removeAll(textNode.data());
+
+ childElm = childElm.nextSiblingElement(childTagName);
+
+ if (!toRemove.isNull())
+ existingNode.removeChild(toRemove);
+ }
}
- if (!nodeHandler->handle(node))
- return false;
+ // Add the new elements
+ int newElementCount = 0;
+ foreach (const QString &value, values) {
+ if (value.isEmpty())
+ continue;
+ QDomElement newChildNode = m_barDocument.createElement(childTagName);
+ newChildNode.appendChild(m_barDocument.createTextNode(value));
+ existingNode.appendChild(newChildNode);
+ ++newElementCount;
+ }
- node = node.nextSibling();
+ if (newElementCount == 0)
+ m_barDocument.documentElement().removeChild(existingNode);
}
+}
- m_editorWidget->setXmlSource(xmlSource);
+QStringList BarDescriptorDocument::stringListValue(const QString &tagName) const
+{
+ QStringList result;
- return true;
+ QDomElement childElm = m_barDocument.documentElement().firstChildElement(tagName);
+ while (!childElm.isNull()) {
+ QDomText textNode = childElm.firstChild().toText();
+ if (textNode.isNull())
+ continue;
+
+ result.append(textNode.data());
+
+ childElm = childElm.nextSiblingElement(tagName);
+ }
+
+ return result;
}
-void BarDescriptorDocument::registerNodeHandler(BarDescriptorDocumentAbstractNodeHandler *nodeHandler)
+void BarDescriptorDocument::setStringListValue(const QString &tagName, const QStringList &stringList)
{
- m_nodeHandlers << nodeHandler;
+ QStringList values = stringList;
+ QDomElement childElm = m_barDocument.documentElement().firstChildElement(tagName);
+ if (!childElm.isNull()) {
+ // Loop through existing elements, remove the existing nodes
+ // that no longer are in "values", and remove from "values"
+ // the existing nodes that don't need re-creation
+ while (!childElm.isNull()) {
+ QDomText textNode = childElm.firstChild().toText();
+ if (textNode.isNull())
+ continue;
+
+ QDomElement toRemove;
+ if (!values.contains(textNode.data()))
+ toRemove = childElm;
+ else
+ values.removeAll(textNode.data());
+
+ childElm = childElm.nextSiblingElement(tagName);
+
+ if (!toRemove.isNull())
+ m_barDocument.documentElement().removeChild(toRemove);
+ }
+ }
+
+ // Add the new elements
+ foreach (const QString &value, values) {
+ if (value.isEmpty())
+ continue;
+ QDomElement newChildNode = m_barDocument.createElement(tagName);
+ newChildNode.appendChild(m_barDocument.createTextNode(value));
+ m_barDocument.documentElement().appendChild(newChildNode);
+ }
}
-BarDescriptorDocumentAbstractNodeHandler *BarDescriptorDocument::nodeHandlerForDomNode(const QDomNode &node)
+BarDescriptorAssetList BarDescriptorDocument::assets() const
{
- foreach (BarDescriptorDocumentAbstractNodeHandler *handler, m_nodeHandlers) {
- if (handler->canHandle(node) && !dynamic_cast<BarDescriptorDocumentUnknownNodeHandler*>(handler))
- return handler;
+ BarDescriptorAssetList result;
+ QDomNodeList nodes = m_barDocument.elementsByTagName(QLatin1String("asset"));
+ if (nodes.isEmpty())
+ return result;
+
+ for (int i = 0; i < nodes.size(); ++i) {
+ QDomElement assetElm = nodes.item(i).toElement();
+ if (assetElm.isNull())
+ continue;
+
+ QDomText textNode = assetElm.firstChild().toText();
+ if (textNode.isNull())
+ continue;
+
+ QString path = assetElm.attribute(QLatin1String("path"));
+ QString entry = assetElm.attribute(QLatin1String("entry"));
+ QString dest = textNode.data();
+
+ BarDescriptorAsset asset;
+ asset.source = path;
+ asset.destination = dest;
+ asset.entry = entry == QLatin1String("true");
+ result.append(asset);
}
- return 0;
+ return result;
}
-void BarDescriptorDocument::removeUnknownNodeHandlers()
+void BarDescriptorDocument::setAssets(const BarDescriptorAssetList &assets)
{
- for (int i = m_nodeHandlers.size() - 1; i >= 0; --i) {
- BarDescriptorDocumentUnknownNodeHandler *nodeHandler = dynamic_cast<BarDescriptorDocumentUnknownNodeHandler*>(m_nodeHandlers[i]);
- if (nodeHandler) {
- m_nodeHandlers.removeAt(i);
- delete nodeHandler;
+ QDomNodeList nodes = m_barDocument.elementsByTagName(QLatin1String("asset"));
+
+ BarDescriptorAssetList newAssets = assets;
+ QList<QDomNode> toRemove;
+
+ for (int i = 0; i < nodes.size(); ++i) {
+ QDomElement assetElm = nodes.at(i).toElement();
+ if (assetElm.isNull())
+ continue;
+
+ QDomText textNode = assetElm.firstChild().toText();
+ if (textNode.isNull())
+ continue;
+
+ QString source = assetElm.attribute(QLatin1String("path"));
+ bool found = false;
+ foreach (const BarDescriptorAsset &asset, newAssets) {
+ if (asset.source == source) {
+ found = true;
+ if (asset.entry) {
+ assetElm.setAttribute(QLatin1String("type"), QLatin1String("Qnx/Elf"));
+ assetElm.setAttribute(QLatin1String("entry"), QLatin1String("true"));
+ } else {
+ assetElm.removeAttribute(QLatin1String("type"));
+ assetElm.removeAttribute(QLatin1String("entry"));
+ }
+ textNode.setData(asset.destination);
+
+ newAssets.removeAll(asset);
+ break;
+ }
+ }
+
+ if (!found)
+ toRemove.append(assetElm);
+ }
+
+ foreach (const QDomNode &node, toRemove)
+ m_barDocument.documentElement().removeChild(node);
+
+ foreach (const BarDescriptorAsset &asset, newAssets) {
+ QDomElement assetElm = m_barDocument.createElement(QLatin1String("asset"));
+ assetElm.setAttribute(QLatin1String("path"), asset.source);
+ if (asset.entry) {
+ assetElm.setAttribute(QLatin1String("type"), QLatin1String("Qnx/Elf"));
+ assetElm.setAttribute(QLatin1String("entry"), QLatin1String("true"));
}
+ assetElm.appendChild(m_barDocument.createTextNode(asset.destination));
+ m_barDocument.documentElement().appendChild(assetElm);
+ }
+}
+
+QList<Utils::EnvironmentItem> BarDescriptorDocument::environment() const
+{
+ QList<Utils::EnvironmentItem> result;
+
+ QDomElement envElm = m_barDocument.documentElement().firstChildElement(QLatin1String("env"));
+ while (!envElm.isNull()) {
+ QString var = envElm.attribute(QLatin1String("var"));
+ QString value = envElm.attribute(QLatin1String("value"));
+
+ Utils::EnvironmentItem item(var, value);
+ result.append(item);
+
+ envElm = envElm.nextSiblingElement(QLatin1String("env"));
+ }
+ return result;
+}
+
+void BarDescriptorDocument::setEnvironment(const QList<Utils::EnvironmentItem> &environment)
+{
+ QDomNodeList envNodes = m_barDocument.elementsByTagName(QLatin1String("env"));
+
+ QList<Utils::EnvironmentItem> newEnvironment = environment;
+ QList<QDomElement> toRemove;
+ for (int i = 0; i < envNodes.size(); ++i) {
+ QDomElement elm = envNodes.at(i).toElement();
+ if (elm.isNull())
+ continue;
+
+ QString var = elm.attribute(QLatin1String("var"));
+ bool found = false;
+ foreach (const Utils::EnvironmentItem item, newEnvironment) {
+ if (item.name == var) {
+ found = true;
+ elm.setAttribute(QLatin1String("value"), item.value);
+ newEnvironment.removeAll(item);
+ break;
+ }
+ }
+
+ if (!found)
+ toRemove.append(elm);
+ }
+
+ foreach (const QDomNode &node, toRemove)
+ m_barDocument.documentElement().removeChild(node);
+
+ foreach (const Utils::EnvironmentItem item, newEnvironment) {
+ QDomElement elm = m_barDocument.createElement(QLatin1String("env"));
+ elm.setAttribute(QLatin1String("var"), item.name);
+ elm.setAttribute(QLatin1String("value"), item.value);
+ m_barDocument.documentElement().appendChild(elm);
+ }
+}
+
+void BarDescriptorDocument::emitAllChanged()
+{
+ QMetaEnum tags = metaObject()->enumerator(metaObject()->enumeratorOffset());
+ for (int i = 0; i < tags.keyCount(); ++i) {
+ Tag tag = static_cast<Tag>(tags.value(i));
+ emit changed(tag, value(tag));
}
}