From ed69c5f9c9e6c57179fd5bd3189c233e31609e1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tobias=20N=C3=A4tterlund?= <tobias.naetterlund.qnx@kdab.com>
Date: Fri, 11 Jan 2013 14:24:43 +0100
Subject: [PATCH] QNX: Add editor for Bar descriptor file

Change-Id: I7ad9bb9448ef467eea353d361b72474fe1b8c8f7
Reviewed-by: Nicolas Arnaud-Cormos <nicolas@kdab.com>
---
 src/plugins/qnx/bardescriptordocument.cpp     | 260 +++++++
 src/plugins/qnx/bardescriptordocument.h       |  92 +++
 .../qnx/bardescriptordocumentnodehandlers.cpp | 671 +++++++++++++++++
 .../qnx/bardescriptordocumentnodehandlers.h   | 287 ++++++++
 src/plugins/qnx/bardescriptoreditor.cpp       | 200 ++++++
 src/plugins/qnx/bardescriptoreditor.h         | 104 +++
 .../qnx/bardescriptoreditorfactory.cpp        |  74 ++
 src/plugins/qnx/bardescriptoreditorfactory.h  |  62 ++
 src/plugins/qnx/bardescriptoreditorwidget.cpp | 674 ++++++++++++++++++
 src/plugins/qnx/bardescriptoreditorwidget.h   | 187 +++++
 src/plugins/qnx/bardescriptoreditorwidget.ui  | 540 ++++++++++++++
 src/plugins/qnx/bardescriptormagicmatcher.cpp |  55 ++
 src/plugins/qnx/bardescriptormagicmatcher.h   |  52 ++
 .../qnx/bardescriptorpermissionsmodel.cpp     | 170 +++++
 .../qnx/bardescriptorpermissionsmodel.h       |  94 +++
 src/plugins/qnx/qnx.pro                       |  23 +-
 src/plugins/qnx/qnx.qbs                       |  15 +
 src/plugins/qnx/qnxconstants.h                |   4 +
 src/plugins/qnx/qnxplugin.cpp                 |  22 +
 19 files changed, 3583 insertions(+), 3 deletions(-)
 create mode 100644 src/plugins/qnx/bardescriptordocument.cpp
 create mode 100644 src/plugins/qnx/bardescriptordocument.h
 create mode 100644 src/plugins/qnx/bardescriptordocumentnodehandlers.cpp
 create mode 100644 src/plugins/qnx/bardescriptordocumentnodehandlers.h
 create mode 100644 src/plugins/qnx/bardescriptoreditor.cpp
 create mode 100644 src/plugins/qnx/bardescriptoreditor.h
 create mode 100644 src/plugins/qnx/bardescriptoreditorfactory.cpp
 create mode 100644 src/plugins/qnx/bardescriptoreditorfactory.h
 create mode 100644 src/plugins/qnx/bardescriptoreditorwidget.cpp
 create mode 100644 src/plugins/qnx/bardescriptoreditorwidget.h
 create mode 100644 src/plugins/qnx/bardescriptoreditorwidget.ui
 create mode 100644 src/plugins/qnx/bardescriptormagicmatcher.cpp
 create mode 100644 src/plugins/qnx/bardescriptormagicmatcher.h
 create mode 100644 src/plugins/qnx/bardescriptorpermissionsmodel.cpp
 create mode 100644 src/plugins/qnx/bardescriptorpermissionsmodel.h

diff --git a/src/plugins/qnx/bardescriptordocument.cpp b/src/plugins/qnx/bardescriptordocument.cpp
new file mode 100644
index 00000000000..b2ad97d9bc8
--- /dev/null
+++ b/src/plugins/qnx/bardescriptordocument.cpp
@@ -0,0 +1,260 @@
+/**************************************************************************
+**
+** Copyright (C) 2011 - 2013 Research In Motion
+**
+** Contact: Research In Motion (blackberry-qt@qnx.com)
+** Contact: KDAB (info@kdab.com)
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "bardescriptordocument.h"
+
+#include "qnxconstants.h"
+#include "bardescriptoreditorwidget.h"
+#include "bardescriptordocumentnodehandlers.h"
+
+#include <coreplugin/editormanager/ieditor.h>
+#include <utils/qtcassert.h>
+
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QTextCodec>
+
+using namespace Qnx;
+using namespace Qnx::Internal;
+
+BarDescriptorDocument::BarDescriptorDocument(BarDescriptorEditorWidget *editorWidget)
+    : Core::TextDocument(editorWidget)
+    , m_nodeHandlers(QList<BarDescriptorDocumentAbstractNodeHandler *>())
+    , m_editorWidget(editorWidget)
+{
+    // 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));
+}
+
+BarDescriptorDocument::~BarDescriptorDocument()
+{
+    while (!m_nodeHandlers.isEmpty()) {
+        BarDescriptorDocumentAbstractNodeHandler *nodeHandler = m_nodeHandlers.takeFirst();
+        delete nodeHandler;
+    }
+}
+
+bool BarDescriptorDocument::open(QString *errorString, const QString &fileName) {
+    QString contents;
+    if (read(fileName, &contents, errorString) != Utils::TextFileFormat::ReadSuccess)
+        return false;
+
+    m_fileName = fileName;
+    m_editorWidget->editor()->setDisplayName(QFileInfo(fileName).fileName());
+
+    bool result = loadContent(contents);
+
+    if (!result)
+        *errorString = tr("%1 does not appear to be a valid application descriptor file").arg(QDir::toNativeSeparators(fileName));
+
+    return result;
+}
+
+bool BarDescriptorDocument::save(QString *errorString, const QString &fileName, bool autoSave)
+{
+    QTC_ASSERT(!autoSave, return false);
+    QTC_ASSERT(fileName.isEmpty(), return false);
+
+    bool result = write(m_fileName, xmlSource(), errorString);
+    if (!result)
+        return false;
+
+    m_editorWidget->setDirty(false);
+    emit changed();
+    return true;
+}
+
+QString BarDescriptorDocument::fileName() const
+{
+    return m_fileName;
+}
+
+QString BarDescriptorDocument::defaultPath() const
+{
+    QFileInfo fi(fileName());
+    return fi.absolutePath();
+}
+
+QString BarDescriptorDocument::suggestedFileName() const
+{
+    QFileInfo fi(fileName());
+    return fi.fileName();
+}
+
+QString BarDescriptorDocument::mimeType() const
+{
+    return QLatin1String(Constants::QNX_BAR_DESCRIPTOR_MIME_TYPE);
+}
+
+bool BarDescriptorDocument::shouldAutoSave() const
+{
+    return false;
+}
+
+bool BarDescriptorDocument::isModified() const
+{
+    return m_editorWidget->isDirty();
+}
+
+bool BarDescriptorDocument::isSaveAsAllowed() const
+{
+    return false;
+}
+
+Core::IDocument::ReloadBehavior BarDescriptorDocument::reloadBehavior(Core::IDocument::ChangeTrigger state, Core::IDocument::ChangeType type) const
+{
+    if (type == TypeRemoved || type == TypePermissions)
+        return BehaviorSilent;
+    if (type == TypeContents && state == TriggerInternal && !isModified())
+        return BehaviorSilent;
+    return BehaviorAsk;
+}
+
+bool BarDescriptorDocument::reload(QString *errorString, Core::IDocument::ReloadFlag flag, Core::IDocument::ChangeType type)
+{
+    Q_UNUSED(type);
+
+    if (flag == Core::IDocument::FlagIgnore)
+        return true;
+
+    return open(errorString, m_fileName);
+}
+
+void BarDescriptorDocument::rename(const QString &newName)
+{
+    const QString oldFilename = m_fileName;
+    m_fileName = newName;
+    m_editorWidget->editor()->setDisplayName(QFileInfo(m_fileName).fileName());
+    emit fileNameChanged(oldFilename, newName);
+    emit changed();
+}
+
+QString BarDescriptorDocument::xmlSource() const
+{
+    QDomDocument doc;
+    doc.appendChild(doc.createProcessingInstruction(QLatin1String("xml"), QLatin1String("version='1.0' encoding='") + QLatin1String(codec()->name()) + QLatin1String("' standalone='no'")));
+
+    // QNX
+    QDomElement rootElem = doc.createElement(QLatin1String("qnx"));
+    rootElem.setAttribute(QLatin1String("xmlns"), QLatin1String("http://www.qnx.com/schemas/application/1.0"));
+
+    QMap<int, BarDescriptorDocumentAbstractNodeHandler*> nodeHandlerMap;
+    foreach (BarDescriptorDocumentAbstractNodeHandler *nodeHandler, m_nodeHandlers)
+        nodeHandlerMap.insertMulti(nodeHandler->order(), nodeHandler);
+
+    QList<BarDescriptorDocumentAbstractNodeHandler*> nodeHandlers = nodeHandlerMap.values();
+    foreach (BarDescriptorDocumentAbstractNodeHandler *nodeHandler, nodeHandlers)
+        rootElem.appendChild(nodeHandler->toNode(doc));
+
+    doc.appendChild(rootElem);
+
+    return doc.toString(4);
+}
+
+bool BarDescriptorDocument::loadContent(const QString &xmlSource, QString *errorMessage, int *errorLine)
+{
+    QDomDocument doc;
+    bool result = doc.setContent(xmlSource, errorMessage, errorLine);
+    if (!result)
+        return false;
+
+    QDomElement docElem = doc.documentElement();
+    if (docElem.tagName() != QLatin1String("qnx"))
+        return false;
+
+    m_editorWidget->clear();
+
+    removeUnknownNodeHandlers();
+    foreach (BarDescriptorDocumentAbstractNodeHandler *nodeHandler, m_nodeHandlers)
+        nodeHandler->clear();
+
+    QDomNode node = docElem.firstChildElement();
+    while (!node.isNull()) {
+        BarDescriptorDocumentAbstractNodeHandler *nodeHandler = nodeHandlerForDomNode(node);
+        if (!nodeHandler) {
+            nodeHandler = new BarDescriptorDocumentUnknownNodeHandler(m_editorWidget);
+            registerNodeHandler(nodeHandler);
+        }
+
+        if (!nodeHandler->handle(node))
+            return false;
+
+        node = node.nextSibling();
+    }
+
+    m_editorWidget->setXmlSource(xmlSource);
+
+    return true;
+}
+
+void BarDescriptorDocument::registerNodeHandler(BarDescriptorDocumentAbstractNodeHandler *nodeHandler)
+{
+    m_nodeHandlers << nodeHandler;
+}
+
+BarDescriptorDocumentAbstractNodeHandler *BarDescriptorDocument::nodeHandlerForDomNode(const QDomNode &node)
+{
+    foreach (BarDescriptorDocumentAbstractNodeHandler *handler, m_nodeHandlers) {
+        if (handler->canHandle(node) && !dynamic_cast<BarDescriptorDocumentUnknownNodeHandler*>(handler))
+            return handler;
+    }
+
+    return 0;
+}
+
+void BarDescriptorDocument::removeUnknownNodeHandlers()
+{
+    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;
+        }
+    }
+}
diff --git a/src/plugins/qnx/bardescriptordocument.h b/src/plugins/qnx/bardescriptordocument.h
new file mode 100644
index 00000000000..ca767458bd6
--- /dev/null
+++ b/src/plugins/qnx/bardescriptordocument.h
@@ -0,0 +1,92 @@
+/**************************************************************************
+**
+** Copyright (C) 2011 - 2013 Research In Motion
+**
+** Contact: Research In Motion (blackberry-qt@qnx.com)
+** Contact: KDAB (info@kdab.com)
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QNX_INTERNAL_BARDESCRIPTORDOCUMENT_H
+#define QNX_INTERNAL_BARDESCRIPTORDOCUMENT_H
+
+#include <coreplugin/textdocument.h>
+
+#include <QDomNode>
+
+namespace Qnx {
+namespace Internal {
+
+struct BarDescriptorAsset {
+    QString source;
+    QString destination;
+    bool entry;
+};
+
+class BarDescriptorEditorWidget;
+class BarDescriptorDocumentAbstractNodeHandler;
+
+class BarDescriptorDocument : public Core::TextDocument
+{
+    Q_OBJECT
+public:
+    explicit BarDescriptorDocument(BarDescriptorEditorWidget *editorWidget);
+    ~BarDescriptorDocument();
+
+    bool open(QString *errorString, const QString &fileName);
+    bool save(QString *errorString, const QString &fileName = QString(), bool autoSave = false);
+    QString fileName() const;
+
+    QString defaultPath() const;
+    QString suggestedFileName() const;
+    QString mimeType() const;
+
+    bool shouldAutoSave() const;
+    bool isModified() const;
+    bool isSaveAsAllowed() const;
+
+    ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const;
+    bool reload(QString *errorString, ReloadFlag flag, ChangeType type);
+    void rename(const QString &newName);
+
+    QString xmlSource() const;
+    bool loadContent(const QString &xmlSource, QString *errorMessage = 0, int *errorLine = 0);
+
+private:
+    void registerNodeHandler(BarDescriptorDocumentAbstractNodeHandler *nodeHandler);
+    BarDescriptorDocumentAbstractNodeHandler *nodeHandlerForDomNode(const QDomNode &node);
+    void removeUnknownNodeHandlers();
+
+    QList<BarDescriptorDocumentAbstractNodeHandler *> m_nodeHandlers;
+
+    QString m_fileName;
+
+    BarDescriptorEditorWidget *m_editorWidget;
+};
+
+} // namespace Internal
+} // namespace Qnx
+
+#endif // QNX_INTERNAL_BARDESCRIPTORDOCUMENT_H
diff --git a/src/plugins/qnx/bardescriptordocumentnodehandlers.cpp b/src/plugins/qnx/bardescriptordocumentnodehandlers.cpp
new file mode 100644
index 00000000000..a547fbf16db
--- /dev/null
+++ b/src/plugins/qnx/bardescriptordocumentnodehandlers.cpp
@@ -0,0 +1,671 @@
+/**************************************************************************
+**
+** Copyright (C) 2011 - 2013 Research In Motion
+**
+** Contact: Research In Motion (blackberry-qt@qnx.com)
+** Contact: KDAB (info@kdab.com)
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "bardescriptordocumentnodehandlers.h"
+#include "bardescriptoreditorwidget.h"
+
+#include <utils/environment.h>
+#include <utils/qtcassert.h>
+
+#include <QDomNode>
+
+using namespace Qnx;
+using namespace Qnx::Internal;
+
+BarDescriptorDocumentAbstractNodeHandler::BarDescriptorDocumentAbstractNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : m_editorWidget(editorWidget)
+    , m_order(0xFFFF)
+{
+}
+
+BarDescriptorDocumentAbstractNodeHandler::~BarDescriptorDocumentAbstractNodeHandler()
+{
+}
+
+bool BarDescriptorDocumentAbstractNodeHandler::handle(const QDomNode &node)
+{
+    if (m_order == 0xFFFF)
+        m_order = node.lineNumber();
+
+    return fromNode(node);
+}
+
+void BarDescriptorDocumentAbstractNodeHandler::clear()
+{
+    m_order = 0xFFFF;
+}
+
+int BarDescriptorDocumentAbstractNodeHandler::order() const
+{
+    return m_order;
+}
+
+BarDescriptorEditorWidget *BarDescriptorDocumentAbstractNodeHandler::editorWidget() const
+{
+    return m_editorWidget;
+}
+
+bool BarDescriptorDocumentAbstractNodeHandler::canHandleSimpleTextElement(const QDomNode &node, const QString &tagName) const
+{
+    QDomElement element = node.toElement();
+    if (element.isNull())
+        return false;
+
+    if (element.tagName().toLower() != tagName.toLower())
+        return false;
+
+    QDomText textNode = element.firstChild().toText();
+    if (textNode.isNull())
+        return false;
+
+    return true;
+}
+
+QString BarDescriptorDocumentAbstractNodeHandler::loadSimpleTextElement(const QDomNode &node)
+{
+    QDomElement element = node.toElement();
+    QDomText textNode = element.firstChild().toText();
+    return textNode.data();
+}
+
+QDomElement BarDescriptorDocumentAbstractNodeHandler::createSimpleTextElement(QDomDocument &doc, const QString &tagName, const QString &textValue) const
+{
+    if (textValue.isEmpty())
+        return QDomElement();
+
+    QDomElement elem = doc.createElement(tagName);
+    elem.appendChild(doc.createTextNode(textValue));
+    return elem;
+}
+
+// ----------------------------------------------------------------------------
+
+BarDescriptorDocumentIdNodeHandler::BarDescriptorDocumentIdNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentIdNodeHandler::canHandle(const QDomNode &node) const
+{
+    return canHandleSimpleTextElement(node, QLatin1String("id"));
+}
+
+bool BarDescriptorDocumentIdNodeHandler::fromNode(const QDomNode &node)
+{
+    if (!canHandle(node))
+        return false;
+
+    editorWidget()->setPackageId(loadSimpleTextElement(node));
+    return true;
+}
+
+QDomNode BarDescriptorDocumentIdNodeHandler::toNode(QDomDocument &doc) const
+{
+    return createSimpleTextElement(doc, QLatin1String("id"), editorWidget()->packageId());
+}
+
+// ----------------------------------------------------------------------------
+
+BarDescriptorDocumentVersionNumberNodeHandler::BarDescriptorDocumentVersionNumberNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentVersionNumberNodeHandler::canHandle(const QDomNode &node) const
+{
+    return canHandleSimpleTextElement(node, QLatin1String("versionNumber"));
+}
+
+bool BarDescriptorDocumentVersionNumberNodeHandler::fromNode(const QDomNode &node)
+{
+    if (!canHandle(node))
+        return false;
+
+    editorWidget()->setPackageVersion(loadSimpleTextElement(node));
+    return true;
+}
+
+QDomNode BarDescriptorDocumentVersionNumberNodeHandler::toNode(QDomDocument &doc) const
+{
+    return createSimpleTextElement(doc, QLatin1String("versionNumber"), editorWidget()->packageVersion());
+}
+
+// ----------------------------------------------------------------------------
+
+BarDescriptorDocumentBuildIdNodeHandler::BarDescriptorDocumentBuildIdNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentBuildIdNodeHandler::canHandle(const QDomNode &node) const
+{
+    return canHandleSimpleTextElement(node, QLatin1String("buildId"));
+}
+
+bool BarDescriptorDocumentBuildIdNodeHandler::fromNode(const QDomNode &node)
+{
+    if (!canHandle(node))
+        return false;
+
+    editorWidget()->setPackageBuildId(loadSimpleTextElement(node));
+    return true;
+}
+
+QDomNode BarDescriptorDocumentBuildIdNodeHandler::toNode(QDomDocument &doc) const
+{
+    return createSimpleTextElement(doc, QLatin1String("buildId"), editorWidget()->packageBuildId());
+}
+
+// ----------------------------------------------------------------------------
+
+BarDescriptorDocumentApplicationNameNodeHandler::BarDescriptorDocumentApplicationNameNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentApplicationNameNodeHandler::canHandle(const QDomNode &node) const
+{
+    return canHandleSimpleTextElement(node, QLatin1String("name"));
+}
+
+bool BarDescriptorDocumentApplicationNameNodeHandler::fromNode(const QDomNode &node)
+{
+    // TODO: Add support for localization
+
+    if (!canHandle(node))
+        return false;
+
+    editorWidget()->setApplicationName(loadSimpleTextElement(node));
+    return true;
+}
+
+QDomNode BarDescriptorDocumentApplicationNameNodeHandler::toNode(QDomDocument &doc) const
+{
+    // TODO: Add support for localization
+
+    return createSimpleTextElement(doc, QLatin1String("name"), editorWidget()->applicationName());
+}
+
+// ----------------------------------------------------------------------------
+
+BarDescriptorDocumentApplicationDescriptionNodeHandler::BarDescriptorDocumentApplicationDescriptionNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentApplicationDescriptionNodeHandler::canHandle(const QDomNode &node) const
+{
+    return canHandleSimpleTextElement(node, QLatin1String("description"));
+}
+
+bool BarDescriptorDocumentApplicationDescriptionNodeHandler::fromNode(const QDomNode &node)
+{
+    // TODO: Add support for localization
+
+    if (!canHandle(node))
+        return false;
+
+    editorWidget()->setApplicationDescription(loadSimpleTextElement(node));
+    return true;
+}
+
+QDomNode BarDescriptorDocumentApplicationDescriptionNodeHandler::toNode(QDomDocument &doc) const
+{
+    return createSimpleTextElement(doc, QLatin1String("description"), editorWidget()->applicationDescription());
+}
+
+// ----------------------------------------------------------------------------
+
+BarDescriptorDocumentApplicationIconNodeHandler::BarDescriptorDocumentApplicationIconNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentApplicationIconNodeHandler::canHandle(const QDomNode &node) const
+{
+    QDomElement element = node.toElement();
+    if (element.isNull())
+        return false;
+
+    if (element.tagName() != QLatin1String("icon"))
+        return false;
+
+    QDomElement imageElement = element.firstChild().toElement();
+    if (imageElement.isNull())
+        return false;
+
+    if (imageElement.tagName() != QLatin1String("image"))
+        return false;
+
+    QDomText imageTextNode = imageElement.firstChild().toText();
+    if (imageTextNode.isNull())
+        return false;
+
+    return true;
+}
+
+bool BarDescriptorDocumentApplicationIconNodeHandler::fromNode(const QDomNode &node)
+{
+    // TODO: Add support for localization
+
+    if (!canHandle(node))
+        return false;
+
+    QDomNode imageNode = node.firstChild();
+    QDomText imageTextNode = imageNode.firstChild().toText();
+    editorWidget()->setApplicationIcon(imageTextNode.data());
+    return true;
+}
+
+QDomNode BarDescriptorDocumentApplicationIconNodeHandler::toNode(QDomDocument &doc) const
+{
+    // TODO: Add support for localization
+    const QString iconFileName = editorWidget()->applicationIconFileName();
+    if (iconFileName.isEmpty())
+        return QDomElement();
+
+    QDomElement iconElement = doc.createElement(QLatin1String("icon"));
+    iconElement.appendChild(createSimpleTextElement(doc, QLatin1String("image"), iconFileName));
+    return iconElement;
+}
+
+// ----------------------------------------------------------------------------
+
+BarDescriptorDocumentSplashScreenNodeHandler::BarDescriptorDocumentSplashScreenNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentSplashScreenNodeHandler::canHandle(const QDomNode &node) const
+{
+    QDomElement element = node.toElement();
+    if (element.isNull())
+        return false;
+
+    if (element.tagName().toLower() != QLatin1String("splashscreens"))
+        return false;
+
+    QDomElement imageElement = element.firstChild().toElement();
+    if (imageElement.isNull())
+        return false;
+
+    if (imageElement.tagName().toLower() != QLatin1String("image"))
+        return false;
+
+    QDomText imageTextNode = imageElement.firstChild().toText();
+    if (imageTextNode.isNull())
+        return false;
+
+    return true;
+}
+
+bool BarDescriptorDocumentSplashScreenNodeHandler::fromNode(const QDomNode &node)
+{
+    if (!canHandle(node))
+        return false;
+
+    QDomElement imageNode = node.firstChildElement();
+    while (!imageNode.isNull()) {
+        if (imageNode.tagName().toLower() == QLatin1String("image")) {
+            QDomText imageTextNode = imageNode.firstChild().toText();
+            editorWidget()->appendSplashScreen(imageTextNode.data());
+        }
+        imageNode = imageNode.nextSiblingElement();
+    }
+    return true;
+}
+
+QDomNode BarDescriptorDocumentSplashScreenNodeHandler::toNode(QDomDocument &doc) const
+{
+    QStringList splashScreens = editorWidget()->splashScreens();
+    if (splashScreens.isEmpty())
+        return QDomElement();
+
+    QDomElement splashScreenElement = doc.createElement(QLatin1String("splashscreens"));
+    foreach (const QString &splashScreen, splashScreens)
+        splashScreenElement.appendChild(createSimpleTextElement(doc, QLatin1String("image"), splashScreen));
+
+    return splashScreenElement;
+}
+
+// ----------------------------------------------------------------------------
+
+BarDescriptorDocumentAssetNodeHandler::BarDescriptorDocumentAssetNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentAssetNodeHandler::canHandle(const QDomNode &node) const
+{
+    return canHandleSimpleTextElement(node, QLatin1String("asset"));
+}
+
+bool BarDescriptorDocumentAssetNodeHandler::fromNode(const QDomNode &node)
+{
+    if (!canHandle(node))
+        return false;
+
+    QDomElement element = node.toElement();
+
+    QString path = element.attribute(QLatin1String("path"));
+    QString entry = element.attribute(QLatin1String("entry"));
+    QDomText destNode = element.firstChild().toText();
+    QString dest = destNode.data();
+
+    BarDescriptorAsset asset;
+    asset.source = path;
+    asset.destination = dest;
+    asset.entry = entry == QLatin1String("true");
+
+    editorWidget()->addAsset(asset);
+    return true;
+}
+
+QDomNode BarDescriptorDocumentAssetNodeHandler::toNode(QDomDocument &doc) const
+{
+    QDomDocumentFragment fragment = doc.createDocumentFragment();
+
+    QList<BarDescriptorAsset> assets = editorWidget()->assets();
+    foreach (const BarDescriptorAsset &asset, assets) {
+        QDomElement assetElem = doc.createElement(QLatin1String("asset"));
+        assetElem.setAttribute(QLatin1String("path"), asset.source);
+        if (asset.entry) {
+            assetElem.setAttribute(QLatin1String("type"), QLatin1String("Qnx/Elf"));
+            assetElem.setAttribute(QLatin1String("entry"), QLatin1String("true"));
+        }
+        assetElem.appendChild(doc.createTextNode(asset.destination));
+        fragment.appendChild(assetElem);
+    }
+
+    return fragment;
+}
+
+// ----------------------------------------------------------------------------
+
+BarDescriptorDocumentInitialWindowNodeHandler::BarDescriptorDocumentInitialWindowNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentInitialWindowNodeHandler::canHandle(const QDomNode &node) const
+{
+    QDomElement element = node.toElement();
+    if (element.isNull())
+        return false;
+
+    if (element.tagName() != QLatin1String("initialWindow"))
+        return false;
+
+    return true;
+}
+
+bool BarDescriptorDocumentInitialWindowNodeHandler::fromNode(const QDomNode &node)
+{
+    if (!canHandle(node))
+        return false;
+
+    QDomElement child = node.firstChildElement();
+    while (!child.isNull()) {
+        if (child.tagName() == QLatin1String("aspectRatio")) {
+            editorWidget()->setOrientation(loadSimpleTextElement(child));
+        } else if (child.tagName() == QLatin1String("autoOrients")) {
+            if (loadSimpleTextElement(child) == QLatin1String("true"))
+                editorWidget()->setOrientation(QLatin1String("auto-orient"));
+        } else if (child.tagName() == QLatin1String("systemChrome")) {
+            editorWidget()->setChrome(loadSimpleTextElement(child));
+        } else if (child.tagName() == QLatin1String("transparent")) {
+            const QString transparent = loadSimpleTextElement(child);
+            editorWidget()->setTransparent(transparent == QLatin1String("true"));
+        }
+        child = child.nextSiblingElement();
+    }
+
+    return true;
+}
+
+QDomNode BarDescriptorDocumentInitialWindowNodeHandler::toNode(QDomDocument &doc) const
+{
+    QDomElement element = doc.createElement(QLatin1String("initialWindow"));
+
+    if (editorWidget()->orientation() == QLatin1String("auto-orient")) {
+        element.appendChild(createSimpleTextElement(doc, QLatin1String("autoOrients"), QLatin1String("true")));
+    } else if (!editorWidget()->orientation().isEmpty()) {
+        element.appendChild(createSimpleTextElement(doc, QLatin1String("aspectRatio"), editorWidget()->orientation()));
+        element.appendChild(createSimpleTextElement(doc, QLatin1String("autoOrients"), QLatin1String("false")));
+    }
+    element.appendChild(createSimpleTextElement(doc, QLatin1String("systemChrome"), editorWidget()->chrome()));
+    element.appendChild(createSimpleTextElement(doc, QLatin1String("transparent"), editorWidget()->transparent() ? QLatin1String("true") : QLatin1String("false")));
+
+    return element;
+}
+
+// ----------------------------------------------------------------------------
+
+
+BarDescriptorDocumentActionNodeHandler::BarDescriptorDocumentActionNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentActionNodeHandler::canHandle(const QDomNode &node) const
+{
+    return canHandleSimpleTextElement(node, QLatin1String("action"));
+}
+
+bool BarDescriptorDocumentActionNodeHandler::fromNode(const QDomNode &node)
+{
+    if (!canHandle(node))
+        return false;
+
+    QString value = loadSimpleTextElement(node);
+    if (value != QLatin1String("run_native")) // This has no representation in the GUI, and is always added
+        editorWidget()->checkPermission(value);
+
+    return true;
+}
+
+QDomNode BarDescriptorDocumentActionNodeHandler::toNode(QDomDocument &doc) const
+{
+    QDomDocumentFragment frag = doc.createDocumentFragment();
+
+    QDomElement runNativeElement = doc.createElement(QLatin1String("action"));
+    runNativeElement.setAttribute(QLatin1String("system"), QLatin1String("true"));
+    runNativeElement.appendChild(doc.createTextNode(QLatin1String("run_native")));
+    frag.appendChild(runNativeElement);
+
+    QStringList checkedIdentifiers = editorWidget()->checkedPermissions();
+    foreach (const QString &identifier, checkedIdentifiers)
+        frag.appendChild(createSimpleTextElement(doc, QLatin1String("action"), identifier));
+
+    return frag;
+}
+
+// ----------------------------------------------------------------------------
+
+BarDescriptorDocumentArgNodeHandler::BarDescriptorDocumentArgNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentArgNodeHandler::canHandle(const QDomNode &node) const
+{
+    return canHandleSimpleTextElement(node, QLatin1String("arg"));
+}
+
+bool BarDescriptorDocumentArgNodeHandler::fromNode(const QDomNode &node)
+{
+    if (!canHandle(node))
+        return false;
+
+    editorWidget()->appendApplicationArgument(loadSimpleTextElement(node));
+    return true;
+}
+
+QDomNode BarDescriptorDocumentArgNodeHandler::toNode(QDomDocument &doc) const
+{
+    QDomDocumentFragment frag = doc.createDocumentFragment();
+
+    QStringList arguments = editorWidget()->applicationArguments();
+    foreach (const QString &argument, arguments)
+        frag.appendChild(createSimpleTextElement(doc, QLatin1String("arg"), argument));
+
+    return frag;
+}
+
+// ----------------------------------------------------------------------------
+
+BarDescriptorDocumentEnvNodeHandler::BarDescriptorDocumentEnvNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentEnvNodeHandler::canHandle(const QDomNode &node) const
+{
+    QDomElement element = node.toElement();
+    if (element.isNull())
+        return false;
+
+    if (element.tagName() != QLatin1String("env"))
+        return false;
+
+    if (!element.hasAttribute(QLatin1String("var")) || !element.hasAttribute(QLatin1String("value")))
+        return false;
+
+    return true;
+}
+
+bool BarDescriptorDocumentEnvNodeHandler::fromNode(const QDomNode &node)
+{
+    if (!canHandle(node))
+        return false;
+
+    QDomElement element = node.toElement();
+
+    QString var = element.attribute(QLatin1String("var"));
+    QString value = element.attribute(QLatin1String("value"));
+
+    Utils::EnvironmentItem item(var, value);
+    editorWidget()->appendEnvironmentItem(item);
+    return true;
+}
+
+QDomNode BarDescriptorDocumentEnvNodeHandler::toNode(QDomDocument &doc) const
+{
+    QDomDocumentFragment frag = doc.createDocumentFragment();
+    QList<Utils::EnvironmentItem> environmentItems = editorWidget()->environment();
+
+    foreach (const Utils::EnvironmentItem &item, environmentItems) {
+        QDomElement element = doc.createElement(QLatin1String("env"));
+        element.setAttribute(QLatin1String("var"), item.name);
+        element.setAttribute(QLatin1String("value"), item.value);
+        frag.appendChild(element);
+    }
+
+    return frag;
+}
+
+// ----------------------------------------------------------------------------
+
+BarDescriptorDocumentAuthorNodeHandler::BarDescriptorDocumentAuthorNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentAuthorNodeHandler::canHandle(const QDomNode &node) const
+{
+    return canHandleSimpleTextElement(node, QLatin1String("author"))
+            || canHandleSimpleTextElement(node, QLatin1String("publisher"));
+}
+
+bool BarDescriptorDocumentAuthorNodeHandler::fromNode(const QDomNode &node)
+{
+    if (!canHandle(node))
+        return false;
+
+    editorWidget()->setAuthor(loadSimpleTextElement(node));
+    return true;
+}
+
+QDomNode BarDescriptorDocumentAuthorNodeHandler::toNode(QDomDocument &doc) const
+{
+    return createSimpleTextElement(doc, QLatin1String("author"), editorWidget()->author());
+}
+
+// ----------------------------------------------------------------------------
+
+BarDescriptorDocumentAuthorIdNodeHandler::BarDescriptorDocumentAuthorIdNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentAuthorIdNodeHandler::canHandle(const QDomNode &node) const
+{
+    return canHandleSimpleTextElement(node, QLatin1String("authorId"));
+}
+
+bool BarDescriptorDocumentAuthorIdNodeHandler::fromNode(const QDomNode &node)
+{
+    if (!canHandle(node))
+        return false;
+
+    editorWidget()->setAuthorId(loadSimpleTextElement(node));
+    return true;
+}
+
+QDomNode BarDescriptorDocumentAuthorIdNodeHandler::toNode(QDomDocument &doc) const
+{
+    return createSimpleTextElement(doc, QLatin1String("authorId"), editorWidget()->authorId());
+}
+
+// ----------------------------------------------------------------------------
+
+BarDescriptorDocumentUnknownNodeHandler::BarDescriptorDocumentUnknownNodeHandler(BarDescriptorEditorWidget *editorWidget)
+    : BarDescriptorDocumentAbstractNodeHandler(editorWidget)
+{
+}
+
+bool BarDescriptorDocumentUnknownNodeHandler::canHandle(const QDomNode &node) const
+{
+    Q_UNUSED(node);
+    return true;
+}
+
+bool BarDescriptorDocumentUnknownNodeHandler::fromNode(const QDomNode &node)
+{
+    m_node = node.cloneNode();
+    return true;
+}
+
+QDomNode BarDescriptorDocumentUnknownNodeHandler::toNode(QDomDocument &doc) const
+{
+    Q_UNUSED(doc);
+    return m_node;
+}
diff --git a/src/plugins/qnx/bardescriptordocumentnodehandlers.h b/src/plugins/qnx/bardescriptordocumentnodehandlers.h
new file mode 100644
index 00000000000..ad9db9bcf48
--- /dev/null
+++ b/src/plugins/qnx/bardescriptordocumentnodehandlers.h
@@ -0,0 +1,287 @@
+/**************************************************************************
+**
+** Copyright (C) 2011 - 2013 Research In Motion
+**
+** Contact: Research In Motion (blackberry-qt@qnx.com)
+** Contact: KDAB (info@kdab.com)
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QNX_INTERNAL_BARDESCRIPTORDOCUMENTNODEHANDLERS_H
+#define QNX_INTERNAL_BARDESCRIPTORDOCUMENTNODEHANDLERS_H
+
+#include <QDomNode>
+#include <QSharedPointer>
+
+namespace Qnx {
+namespace Internal {
+
+class BarDescriptorEditorWidget;
+
+class BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentAbstractNodeHandler(BarDescriptorEditorWidget *editorWidget);
+    virtual ~BarDescriptorDocumentAbstractNodeHandler();
+
+    virtual bool canHandle(const QDomNode &node) const = 0;
+    bool handle(const QDomNode &node);
+    virtual QDomNode toNode(QDomDocument &doc) const = 0;
+
+    void clear();
+    int order() const;
+
+protected:
+    BarDescriptorEditorWidget *editorWidget() const;
+
+    virtual bool fromNode(const QDomNode &node) = 0;
+
+    bool canHandleSimpleTextElement(const QDomNode &node, const QString &tagName) const;
+    QString loadSimpleTextElement(const QDomNode &node);
+    QDomElement createSimpleTextElement(QDomDocument &doc, const QString &tagName, const QString &textValue) const;
+
+private:
+    BarDescriptorEditorWidget *m_editorWidget;
+
+    int m_order;
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentIdNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentIdNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentVersionNumberNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentVersionNumberNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentBuildIdNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentBuildIdNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentApplicationNameNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentApplicationNameNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentApplicationDescriptionNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentApplicationDescriptionNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentApplicationIconNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentApplicationIconNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentSplashScreenNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentSplashScreenNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentAssetNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentAssetNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentInitialWindowNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentInitialWindowNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentActionNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentActionNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentArgNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentArgNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentEnvNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentEnvNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentAuthorNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentAuthorNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentAuthorIdNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentAuthorIdNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+};
+
+// ----------------------------------------------------------------------------
+
+class BarDescriptorDocumentUnknownNodeHandler : public BarDescriptorDocumentAbstractNodeHandler
+{
+public:
+    BarDescriptorDocumentUnknownNodeHandler(BarDescriptorEditorWidget *editorWidget);
+
+    bool canHandle(const QDomNode &node) const;
+    QDomNode toNode(QDomDocument &doc) const;
+
+protected:
+    bool fromNode(const QDomNode &node);
+
+private:
+    QDomNode m_node;
+};
+
+} // namespace Internal
+} // namespace Qnx
+
+#endif // QNX_INTERNAL_BARDESCRIPTORDOCUMENTNODEHANDLERS_H
diff --git a/src/plugins/qnx/bardescriptoreditor.cpp b/src/plugins/qnx/bardescriptoreditor.cpp
new file mode 100644
index 00000000000..371cd5037bc
--- /dev/null
+++ b/src/plugins/qnx/bardescriptoreditor.cpp
@@ -0,0 +1,200 @@
+/**************************************************************************
+**
+** Copyright (C) 2011 - 2013 Research In Motion
+**
+** Contact: Research In Motion (blackberry-qt@qnx.com)
+** Contact: KDAB (info@kdab.com)
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "bardescriptoreditor.h"
+
+#include "qnxconstants.h"
+#include "bardescriptoreditorwidget.h"
+#include "bardescriptordocument.h"
+
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/task.h>
+#include <projectexplorer/taskhub.h>
+#include <utils/qtcassert.h>
+
+#include <QtGui/QAction>
+#include <QtGui/QToolBar>
+
+using namespace Qnx;
+using namespace Qnx::Internal;
+
+BarDescriptorEditor::BarDescriptorEditor(BarDescriptorEditorWidget *editorWidget)
+    : Core::IEditor()
+    , m_taskHub(0)
+{
+    setWidget(editorWidget);
+
+    m_file = new BarDescriptorDocument(editorWidget);
+
+    m_toolBar = new QToolBar(editorWidget);
+
+    m_actionGroup = new QActionGroup(this);
+    connect(m_actionGroup, SIGNAL(triggered(QAction*)), this, SLOT(changeEditorPage(QAction*)));
+
+    QAction *generalAction = m_toolBar->addAction(tr("General"));
+    generalAction->setData(General);
+    generalAction->setCheckable(true);
+    m_actionGroup->addAction(generalAction);
+
+    QAction *applicationAction = m_toolBar->addAction(tr("Application"));
+    applicationAction->setData(Application);
+    applicationAction->setCheckable(true);
+    m_actionGroup->addAction(applicationAction);
+
+    QAction *assetsAction = m_toolBar->addAction(tr("Assets"));
+    assetsAction->setData(Assets);
+    assetsAction->setCheckable(true);
+    m_actionGroup->addAction(assetsAction);
+
+    QAction *sourceAction = m_toolBar->addAction(tr("XML Source"));
+    sourceAction->setData(Source);
+    sourceAction->setCheckable(true);
+    m_actionGroup->addAction(sourceAction);
+
+    generalAction->setChecked(true);
+}
+
+bool BarDescriptorEditor::createNew(const QString &contents)
+{
+    Q_UNUSED(contents);
+    return false;
+}
+
+bool BarDescriptorEditor::open(QString *errorString, const QString &fileName, const QString &realFileName)
+{
+    QTC_ASSERT(fileName == realFileName, return false);
+    return m_file->open(errorString, fileName);
+}
+
+Core::IDocument *BarDescriptorEditor::document()
+{
+    return m_file;
+}
+
+Core::Id BarDescriptorEditor::id() const
+{
+    return Constants::QNX_BAR_DESCRIPTOR_EDITOR_ID;
+}
+
+QString BarDescriptorEditor::displayName() const
+{
+    return m_displayName;
+}
+
+void BarDescriptorEditor::setDisplayName(const QString &title)
+{
+    if (title == m_displayName)
+        return;
+
+    m_displayName = title;
+    emit changed();
+}
+
+bool BarDescriptorEditor::duplicateSupported() const
+{
+    return false;
+}
+
+Core::IEditor *BarDescriptorEditor::duplicate(QWidget *parent)
+{
+    Q_UNUSED(parent);
+    return 0;
+}
+
+QByteArray BarDescriptorEditor::saveState() const
+{
+    return QByteArray(); // Not supported
+}
+
+bool BarDescriptorEditor::restoreState(const QByteArray &state)
+{
+    Q_UNUSED(state);
+    return false; // Not supported
+}
+
+bool BarDescriptorEditor::isTemporary() const
+{
+    return false;
+}
+
+QWidget *BarDescriptorEditor::toolBar()
+{
+    return m_toolBar;
+}
+
+void BarDescriptorEditor::changeEditorPage(QAction *action)
+{
+    setActivePage(static_cast<EditorPage>(action->data().toInt()));
+}
+
+ProjectExplorer::TaskHub *BarDescriptorEditor::taskHub()
+{
+    if (m_taskHub == 0) {
+        m_taskHub = ProjectExplorer::ProjectExplorerPlugin::instance()->taskHub();
+        m_taskHub->addCategory(Constants::QNX_TASK_CATEGORY_BARDESCRIPTOR, tr("Bar Descriptor"));
+    }
+
+    return m_taskHub;
+}
+
+void BarDescriptorEditor::setActivePage(BarDescriptorEditor::EditorPage page)
+{
+    BarDescriptorEditorWidget *editorWidget = qobject_cast<BarDescriptorEditorWidget *>(widget());
+    QTC_ASSERT(editorWidget, return);
+
+    int prevPage = editorWidget->currentIndex();
+
+    if (prevPage == page)
+        return;
+
+    if (page == Source) {
+        editorWidget->setXmlSource(m_file->xmlSource());
+    } else if (prevPage == Source) {
+        taskHub()->clearTasks(Constants::QNX_TASK_CATEGORY_BARDESCRIPTOR);
+        QString errorMsg;
+        int errorLine;
+        if (!m_file->loadContent(editorWidget->xmlSource(), &errorMsg, &errorLine)) {
+            const ProjectExplorer::Task task(ProjectExplorer::Task::Error, errorMsg, Utils::FileName::fromString(m_file->fileName()),
+                                       errorLine, Constants::QNX_TASK_CATEGORY_BARDESCRIPTOR);
+            taskHub()->addTask(task);
+            taskHub()->requestPopup();
+
+            foreach (QAction *action, m_actionGroup->actions())
+                if (action->data().toInt() == Source)
+                    action->setChecked(true);
+
+            return;
+        }
+    }
+
+    editorWidget->setCurrentIndex(page);
+}
diff --git a/src/plugins/qnx/bardescriptoreditor.h b/src/plugins/qnx/bardescriptoreditor.h
new file mode 100644
index 00000000000..5220aad9664
--- /dev/null
+++ b/src/plugins/qnx/bardescriptoreditor.h
@@ -0,0 +1,104 @@
+/**************************************************************************
+**
+** Copyright (C) 2011 - 2013 Research In Motion
+**
+** Contact: Research In Motion (blackberry-qt@qnx.com)
+** Contact: KDAB (info@kdab.com)
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QNX_INTERNAL_BARDESCRIPTOREDITOR_H
+#define QNX_INTERNAL_BARDESCRIPTOREDITOR_H
+
+#include <coreplugin/editormanager/ieditor.h>
+
+QT_BEGIN_NAMESPACE
+class QActionGroup;
+class QToolBar;
+QT_END_NAMESPACE
+
+namespace ProjectExplorer {
+    class TaskHub;
+}
+
+namespace Qnx {
+namespace Internal {
+
+class BarDescriptorDocument;
+
+class BarDescriptorEditorWidget;
+
+class BarDescriptorEditor : public Core::IEditor
+{
+    Q_OBJECT
+public:
+    explicit BarDescriptorEditor(BarDescriptorEditorWidget *editorWidget);
+
+    bool createNew(const QString &contents = QString());
+    bool open(QString *errorString, const QString &fileName, const QString &realFileName);
+    Core::IDocument *document();
+    Core::Id id() const;
+    QString displayName() const;
+    void setDisplayName(const QString &title);
+
+    bool duplicateSupported() const;
+    Core::IEditor *duplicate(QWidget *parent);
+
+    QByteArray saveState() const;
+    bool restoreState(const QByteArray &state);
+
+    bool isTemporary() const;
+
+    QWidget *toolBar();
+
+private slots:
+    void changeEditorPage(QAction *action);
+
+private:
+    enum EditorPage {
+        General = 0,
+        Application,
+        Assets,
+        Source
+    };
+
+    ProjectExplorer::TaskHub *taskHub();
+
+    void setActivePage(EditorPage page);
+
+    BarDescriptorDocument *m_file;
+
+    QString m_displayName;
+
+    QToolBar *m_toolBar;
+    QActionGroup *m_actionGroup;
+
+    ProjectExplorer::TaskHub *m_taskHub;
+};
+
+} // namespace Internal
+} // namespace Qnx
+
+#endif // QNX_INTERNAL_BARDESCRIPTOREDITOR_H
diff --git a/src/plugins/qnx/bardescriptoreditorfactory.cpp b/src/plugins/qnx/bardescriptoreditorfactory.cpp
new file mode 100644
index 00000000000..da3a933dcee
--- /dev/null
+++ b/src/plugins/qnx/bardescriptoreditorfactory.cpp
@@ -0,0 +1,74 @@
+/**************************************************************************
+**
+** Copyright (C) 2011 - 2013 Research In Motion
+**
+** Contact: Research In Motion (blackberry-qt@qnx.com)
+** Contact: KDAB (info@kdab.com)
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "bardescriptoreditorfactory.h"
+
+#include "qnxconstants.h"
+#include "bardescriptoreditorwidget.h"
+
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/ieditor.h>
+
+using namespace Qnx;
+using namespace Qnx::Internal;
+
+BarDescriptorEditorFactory::BarDescriptorEditorFactory(QObject *parent)
+    : Core::IEditorFactory(parent)
+    , m_mimeTypes(QStringList() << QLatin1String(Constants::QNX_BAR_DESCRIPTOR_MIME_TYPE))
+{
+}
+
+QStringList BarDescriptorEditorFactory::mimeTypes() const
+{
+    return m_mimeTypes;
+}
+
+Core::Id BarDescriptorEditorFactory::id() const
+{
+    return Constants::QNX_BAR_DESCRIPTOR_EDITOR_ID;
+}
+
+QString BarDescriptorEditorFactory::displayName() const
+{
+    return tr("Bar descriptor editor");
+}
+
+Core::IDocument *BarDescriptorEditorFactory::open(const QString &fileName)
+{
+    Core::IEditor *iface = Core::EditorManager::instance()->openEditor(fileName, id());
+    return iface ? iface->document() : 0;
+}
+
+Core::IEditor *BarDescriptorEditorFactory::createEditor(QWidget *parent)
+{
+    BarDescriptorEditorWidget *editorWidget = new BarDescriptorEditorWidget(parent);
+    return editorWidget->editor();
+}
diff --git a/src/plugins/qnx/bardescriptoreditorfactory.h b/src/plugins/qnx/bardescriptoreditorfactory.h
new file mode 100644
index 00000000000..1e49ac3247b
--- /dev/null
+++ b/src/plugins/qnx/bardescriptoreditorfactory.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** Copyright (C) 2011 - 2013 Research In Motion
+**
+** Contact: Research In Motion (blackberry-qt@qnx.com)
+** Contact: KDAB (info@kdab.com)
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QNX_INTERNAL_BARDESCRIPTOREDITORFACTORY_H
+#define QNX_INTERNAL_BARDESCRIPTOREDITORFACTORY_H
+
+#include <coreplugin/editormanager/ieditorfactory.h>
+
+#include <QtCore/QStringList>
+
+namespace Qnx {
+namespace Internal {
+
+class BarDescriptorEditorFactory : public Core::IEditorFactory
+{
+    Q_OBJECT
+public:
+    explicit BarDescriptorEditorFactory(QObject *parent = 0);
+
+    QStringList mimeTypes() const;
+    Core::Id id() const;
+    QString displayName() const;
+    Core::IDocument *open(const QString &fileName);
+
+    Core::IEditor *createEditor(QWidget *parent);
+
+private:
+    QStringList m_mimeTypes;
+};
+
+} // namespace Internal
+} // namespace Qnx
+
+#endif // QNX_INTERNAL_BARDESCRIPTOREDITORFACTORY_H
diff --git a/src/plugins/qnx/bardescriptoreditorwidget.cpp b/src/plugins/qnx/bardescriptoreditorwidget.cpp
new file mode 100644
index 00000000000..e875d7e0584
--- /dev/null
+++ b/src/plugins/qnx/bardescriptoreditorwidget.cpp
@@ -0,0 +1,674 @@
+/**************************************************************************
+**
+** Copyright (C) 2011 - 2013 Research In Motion
+**
+** Contact: Research In Motion (blackberry-qt@qnx.com)
+** Contact: KDAB (info@kdab.com)
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "bardescriptoreditorwidget.h"
+#include "ui_bardescriptoreditorwidget.h"
+
+#include "qnxconstants.h"
+#include "bardescriptoreditor.h"
+#include "bardescriptorpermissionsmodel.h"
+
+#include <qtsupport/qtversionmanager.h>
+#include <texteditor/plaintexteditor.h>
+#include <utils/qtcassert.h>
+
+#include <QFileDialog>
+#include <QItemSelection>
+#include <QStandardItemModel>
+#include <QStringListModel>
+
+using namespace Qnx;
+using namespace Qnx::Internal;
+
+namespace {
+void setTextBlocked(QLineEdit *lineEdit, const QString &value)
+{
+    bool blocked = lineEdit->blockSignals(true);
+    lineEdit->setText(value);
+    lineEdit->blockSignals(blocked);
+}
+
+void setComboBoxDataBlocked(QComboBox *comboBox, const QString &data)
+{
+    int index = comboBox->findData(data);
+    QTC_CHECK(index > -1);
+    bool blocked = comboBox->blockSignals(true);
+    comboBox->setCurrentIndex(index);
+    comboBox->blockSignals(blocked);
+}
+
+void setPathBlocked(Utils::PathChooser *pathChooser, const QString &path)
+{
+    bool blocked = pathChooser->blockSignals(true);
+    pathChooser->setPath(path);
+    pathChooser->blockSignals(blocked);
+}
+
+void setCheckBoxBlocked(QCheckBox *checkBox, bool check)
+{
+    bool blocked = checkBox->blockSignals(true);
+    checkBox->setChecked(check);
+    checkBox->blockSignals(blocked);
+}
+}
+
+BarDescriptorEditorWidget::BarDescriptorEditorWidget(QWidget *parent)
+    : QStackedWidget(parent)
+    , m_editor(0)
+    , m_dirty(false)
+    , m_ui(new Ui::BarDescriptorEditorWidget)
+{
+    m_ui->setupUi(this);
+
+    setCurrentIndex(0);
+
+    initGeneralPage();
+    initApplicationPage();
+    initAssetsPage();
+    initSourcePage();
+}
+
+BarDescriptorEditorWidget::~BarDescriptorEditorWidget()
+{
+    delete m_ui;
+}
+
+void BarDescriptorEditorWidget::initGeneralPage()
+{
+    QRegExp versionNumberRegExp(QLatin1String("(\\d{1,3}\\.)?(\\d{1,3}\\.)?(\\d{1,3})"));
+    QRegExpValidator *versionNumberValidator = new QRegExpValidator(versionNumberRegExp, this);
+    m_ui->packageVersion->setValidator(versionNumberValidator);
+
+    connect(m_ui->packageId, SIGNAL(textChanged(QString)), this, SLOT(setDirty()));
+    connect(m_ui->packageVersion, SIGNAL(textChanged(QString)), this, SLOT(setDirty()));
+    connect(m_ui->packageBuildId, SIGNAL(textChanged(QString)), this, SLOT(setDirty()));
+
+    connect(m_ui->author, SIGNAL(textChanged(QString)), this, SLOT(setDirty()));
+    connect(m_ui->authorId, SIGNAL(textChanged(QString)), this, SLOT(setDirty()));
+}
+
+void BarDescriptorEditorWidget::clearGeneralPage()
+{
+    setTextBlocked(m_ui->packageId, QString());
+    setTextBlocked(m_ui->packageVersion, QString());
+    setTextBlocked(m_ui->packageBuildId, QString());
+
+    setTextBlocked(m_ui->author, QString());
+    setTextBlocked(m_ui->authorId, QString());
+}
+
+void BarDescriptorEditorWidget::initApplicationPage()
+{
+    // General
+    m_ui->orientation->addItem(tr("Default"), QLatin1String(""));
+    m_ui->orientation->addItem(tr("Auto-orient"), QLatin1String("auto-orient"));
+    m_ui->orientation->addItem(tr("Landscape"), QLatin1String("landscape"));
+    m_ui->orientation->addItem(tr("Portrait"), QLatin1String("portrait"));
+
+    m_ui->chrome->addItem(tr("Standard"), QLatin1String("standard"));
+    m_ui->chrome->addItem(tr("None"), QLatin1String("none"));
+
+    connect(m_ui->orientation, SIGNAL(currentIndexChanged(int)), this, SLOT(setDirty()));
+    connect(m_ui->chrome, SIGNAL(currentIndexChanged(int)), this, SLOT(setDirty()));
+    connect(m_ui->transparentMainWindow, SIGNAL(toggled(bool)), this, SLOT(setDirty()));
+    connect(m_ui->applicationArguments, SIGNAL(textChanged(QString)), this, SLOT(setDirty()));
+
+    //Permissions
+    m_permissionsModel = new BarDescriptorPermissionsModel(this);
+    m_ui->permissionsView->setModel(m_permissionsModel);
+
+    connect(m_ui->selectAllPermissions, SIGNAL(clicked()), m_permissionsModel, SLOT(checkAll()));
+    connect(m_ui->deselectAllPermissions, SIGNAL(clicked()), m_permissionsModel, SLOT(uncheckAll()));
+    connect(m_permissionsModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(setDirty()));
+
+    // Environment
+    m_ui->environmentWidget->setBaseEnvironmentText(tr("Device Environment"));
+
+    connect(m_ui->environmentWidget, SIGNAL(userChangesChanged()), this, SLOT(setDirty()));
+
+    // Entry-Point Text and Images
+    m_ui->iconFilePath->setExpectedKind(Utils::PathChooser::File);
+    m_ui->iconFilePath->setPromptDialogFilter(tr("Images (*.jpg *.png)"));
+
+    connect(m_ui->applicationName, SIGNAL(textChanged(QString)), this, SLOT(setDirty()));
+    connect(m_ui->applicationDescription, SIGNAL(textChanged()), this, SLOT(setDirty()));
+
+    connect(m_ui->iconFilePath, SIGNAL(changed(QString)), this, SLOT(setDirty()));
+    connect(m_ui->iconFilePath, SIGNAL(changed(QString)), this, SLOT(addImageAsAsset(QString)));
+    connect(m_ui->iconFilePath, SIGNAL(changed(QString)), this, SLOT(setApplicationIconPreview(QString)));
+    connect(m_ui->iconClearButton, SIGNAL(clicked()), m_ui->iconFilePath->lineEdit(), SLOT(clear()));
+
+    m_splashScreenModel = new QStringListModel(this);
+    m_ui->splashScreensView->setModel(m_splashScreenModel);
+    connect(m_ui->addSplashScreen, SIGNAL(clicked()), this, SLOT(browseForSplashScreen()));
+    connect(m_ui->removeSplashScreen, SIGNAL(clicked()), this, SLOT(removeSelectedSplashScreen()));
+    connect(m_splashScreenModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(setDirty()));
+    connect(m_ui->splashScreensView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(handleSplashScreenSelectionChanged(QItemSelection, QItemSelection)));
+}
+
+void BarDescriptorEditorWidget::clearApplicationPage()
+{
+    // General
+    setComboBoxDataBlocked(m_ui->orientation, QLatin1String(""));
+    setComboBoxDataBlocked(m_ui->chrome, QLatin1String("none"));
+    setCheckBoxBlocked(m_ui->transparentMainWindow, false);
+    setTextBlocked(m_ui->applicationArguments, QString());
+
+    // Permissions
+    disconnect(m_permissionsModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(setDirty()));
+    m_permissionsModel->uncheckAll();
+    connect(m_permissionsModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(setDirty()));
+
+    // Environment
+    disconnect(m_ui->environmentWidget, SIGNAL(userChangesChanged()), this, SLOT(setDirty()));
+    m_ui->environmentWidget->setUserChanges(QList<Utils::EnvironmentItem>());
+    connect(m_ui->environmentWidget, SIGNAL(userChangesChanged()), this, SLOT(setDirty()));
+
+    // Entry-Point Text and Images
+    setPathBlocked(m_ui->iconFilePath, QString());
+    setApplicationIconPreview(QString());
+
+    disconnect(m_splashScreenModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(setDirty()));
+    m_splashScreenModel->setStringList(QStringList());
+    connect(m_splashScreenModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(setDirty()));
+    setImagePreview(m_ui->splashScreenPreviewLabel, QString());
+
+}
+
+void BarDescriptorEditorWidget::initAssetsPage()
+{
+    QStringList headerLabels;
+    headerLabels << tr("Path") << tr("Destination") << tr("Entry-Point");
+    m_assetsModel = new QStandardItemModel(this);
+    m_assetsModel->setHorizontalHeaderLabels(headerLabels);
+    m_ui->assets->setModel(m_assetsModel);
+
+    connect(m_ui->addAsset, SIGNAL(clicked()), this, SLOT(addNewAsset()));
+    connect(m_ui->removeAsset, SIGNAL(clicked()), this, SLOT(removeSelectedAsset()));
+    connect(m_assetsModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updateEntryCheckState(QStandardItem*)));
+    connect(m_assetsModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(setDirty()));
+}
+
+void BarDescriptorEditorWidget::clearAssetsPage()
+{
+    disconnect(m_assetsModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(setDirty()));
+    m_assetsModel->removeRows(0, m_assetsModel->rowCount());
+    connect(m_assetsModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(setDirty()));
+}
+
+void BarDescriptorEditorWidget::initSourcePage()
+{
+    connect(m_ui->xmlSourceView, SIGNAL(changed()), this, SLOT(setDirty()));
+    m_ui->xmlSourceView->configure(QLatin1String(Constants::QNX_BAR_DESCRIPTOR_MIME_TYPE));
+}
+
+void BarDescriptorEditorWidget::clearSourcePage()
+{
+    disconnect(m_ui->xmlSourceView, SIGNAL(changed()), this, SLOT(setDirty()));
+    m_ui->xmlSourceView->clear();
+    connect(m_ui->xmlSourceView, SIGNAL(changed()), this, SLOT(setDirty()));
+}
+
+Core::IEditor *BarDescriptorEditorWidget::editor() const
+{
+    if (!m_editor) {
+        m_editor = const_cast<BarDescriptorEditorWidget *>(this)->createEditor();
+        connect(this, SIGNAL(changed()), m_editor, SIGNAL(changed()));
+    }
+
+    return m_editor;
+}
+
+QString BarDescriptorEditorWidget::packageId() const
+{
+    return m_ui->packageId->text();
+}
+
+void BarDescriptorEditorWidget::setPackageId(const QString &packageId)
+{
+    setTextBlocked(m_ui->packageId, packageId);
+}
+
+QString BarDescriptorEditorWidget::packageVersion() const
+{
+    QString version = m_ui->packageVersion->text();
+    int pos = 0;
+    if (m_ui->packageVersion->validator()->validate(version, pos) == QValidator::Intermediate) {
+        if (version.endsWith(QLatin1Char('.')))
+            version = version.left(version.size() - 1);
+    }
+    return version;
+}
+
+void BarDescriptorEditorWidget::setPackageVersion(const QString &packageVersion)
+{
+    setTextBlocked(m_ui->packageVersion, packageVersion);
+}
+
+QString BarDescriptorEditorWidget::packageBuildId() const
+{
+    return m_ui->packageBuildId->text();
+}
+
+void BarDescriptorEditorWidget::setPackageBuildId(const QString &packageBuildId)
+{
+    setTextBlocked(m_ui->packageBuildId, packageBuildId);
+}
+
+QString BarDescriptorEditorWidget::author() const
+{
+    return m_ui->author->text();
+}
+
+void BarDescriptorEditorWidget::setAuthor(const QString &author)
+{
+    setTextBlocked(m_ui->author, author);
+}
+
+QString BarDescriptorEditorWidget::authorId() const
+{
+    return m_ui->authorId->text();
+}
+
+void BarDescriptorEditorWidget::setAuthorId(const QString &authorId)
+{
+    setTextBlocked(m_ui->authorId, authorId);
+}
+
+QString BarDescriptorEditorWidget::orientation() const
+{
+    return m_ui->orientation->itemData(m_ui->orientation->currentIndex()).toString();
+}
+
+void BarDescriptorEditorWidget::setOrientation(const QString &orientation)
+{
+    setComboBoxDataBlocked(m_ui->orientation, orientation);
+}
+
+QString BarDescriptorEditorWidget::chrome() const
+{
+    return m_ui->chrome->itemData(m_ui->chrome->currentIndex()).toString();
+}
+
+void BarDescriptorEditorWidget::setChrome(const QString &chrome)
+{
+    setComboBoxDataBlocked(m_ui->chrome, chrome);
+}
+
+bool BarDescriptorEditorWidget::transparent() const
+{
+    return m_ui->transparentMainWindow->isChecked();
+}
+
+void BarDescriptorEditorWidget::setTransparent(bool transparent)
+{
+    setCheckBoxBlocked(m_ui->transparentMainWindow, transparent);
+}
+
+void BarDescriptorEditorWidget::appendApplicationArgument(const QString &argument)
+{
+    QString completeArguments = m_ui->applicationArguments->text();
+    if (!completeArguments.isEmpty())
+        completeArguments.append(QLatin1Char(' '));
+    completeArguments.append(argument);
+
+    setTextBlocked(m_ui->applicationArguments, completeArguments);
+}
+
+QStringList BarDescriptorEditorWidget::applicationArguments() const
+{
+    // TODO: Should probably handle "argument with spaces within quotes"
+    return m_ui->applicationArguments->text().split(QLatin1Char(' '));
+}
+
+QStringList BarDescriptorEditorWidget::checkedPermissions() const
+{
+    return m_permissionsModel->checkedIdentifiers();
+}
+
+void BarDescriptorEditorWidget::checkPermission(const QString &identifier)
+{
+    disconnect(m_permissionsModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(setDirty()));
+    m_permissionsModel->checkPermission(identifier);
+    connect(m_permissionsModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(setDirty()));
+}
+
+QList<Utils::EnvironmentItem> BarDescriptorEditorWidget::environment() const
+{
+    return m_ui->environmentWidget->userChanges();
+}
+
+void BarDescriptorEditorWidget::appendEnvironmentItem(const Utils::EnvironmentItem &envItem)
+{
+    disconnect(m_ui->environmentWidget, SIGNAL(userChangesChanged()), this, SLOT(setDirty()));
+    QList<Utils::EnvironmentItem> items = m_ui->environmentWidget->userChanges();
+    items.append(envItem);
+    m_ui->environmentWidget->setUserChanges(items);
+    connect(m_ui->environmentWidget, SIGNAL(userChangesChanged()), this, SLOT(setDirty()));
+}
+
+QString BarDescriptorEditorWidget::applicationName() const
+{
+    return m_ui->applicationName->text();
+}
+
+void BarDescriptorEditorWidget::setApplicationName(const QString &applicationName)
+{
+    setTextBlocked(m_ui->applicationName, applicationName);
+}
+
+QString BarDescriptorEditorWidget::applicationDescription() const
+{
+    return m_ui->applicationDescription->toPlainText();
+}
+
+void BarDescriptorEditorWidget::setApplicationDescription(const QString &applicationDescription)
+{
+    bool blocked = m_ui->applicationDescription->blockSignals(true);
+    m_ui->applicationDescription->setPlainText(applicationDescription);
+    m_ui->applicationDescription->blockSignals(blocked);
+}
+
+QString BarDescriptorEditorWidget::applicationIconFileName() const
+{
+    return QFileInfo(m_ui->iconFilePath->path()).fileName();
+}
+
+void BarDescriptorEditorWidget::setApplicationIcon(const QString &iconPath)
+{
+    // During file loading, the assets might not have been read yet
+    QMetaObject::invokeMethod(this, "setApplicationIconDelayed", Qt::QueuedConnection, Q_ARG(QString, iconPath));
+}
+
+QStringList BarDescriptorEditorWidget::splashScreens() const
+{
+    QStringList result;
+
+    foreach (const QString &splashScreen, m_splashScreenModel->stringList())
+        result << QFileInfo(splashScreen).fileName();
+
+    return result;
+}
+
+void BarDescriptorEditorWidget::appendSplashScreen(const QString &splashScreenPath)
+{
+    // During file loading, the assets might not have been read yet
+    QMetaObject::invokeMethod(this, "appendSplashScreenDelayed", Qt::QueuedConnection, Q_ARG(QString, splashScreenPath));
+}
+
+void BarDescriptorEditorWidget::setApplicationIconDelayed(const QString &iconPath)
+{
+    const QString fullIconPath = localAssetPathFromDestination(iconPath);
+    setPathBlocked(m_ui->iconFilePath, fullIconPath);
+    setApplicationIconPreview(fullIconPath);
+}
+
+void BarDescriptorEditorWidget::setImagePreview(QLabel *previewLabel, const QString &path)
+{
+    if (path.isEmpty()) {
+        previewLabel->clear();
+        return;
+    }
+
+    QPixmap originalPixmap(path);
+    if (originalPixmap.isNull()) {
+        previewLabel->clear();
+        return;
+    }
+
+    QSize size = previewLabel->minimumSize();
+    QPixmap scaledPixmap = originalPixmap.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+    if (scaledPixmap.isNull()) {
+        previewLabel->clear();
+        return;
+    }
+
+    previewLabel->setPixmap(scaledPixmap);
+}
+
+void BarDescriptorEditorWidget::setApplicationIconPreview(const QString &path)
+{
+    setImagePreview(m_ui->iconPreviewLabel, path);
+}
+
+void BarDescriptorEditorWidget::appendSplashScreenDelayed(const QString &splashScreenPath)
+{
+    const QString fullSplashScreenPath = localAssetPathFromDestination(splashScreenPath);
+
+    disconnect(m_splashScreenModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(setDirty()));
+    int rowCount = m_splashScreenModel->rowCount();
+    m_splashScreenModel->insertRow(rowCount);
+    m_splashScreenModel->setData(m_splashScreenModel->index(rowCount), fullSplashScreenPath);
+    connect(m_splashScreenModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(setDirty()));
+}
+
+void BarDescriptorEditorWidget::browseForSplashScreen()
+{
+    const QString fileName = QFileDialog::getOpenFileName(this, tr("Select splash screen"), QString(), tr("Images (*.jpg *.png)"));
+    if (fileName.isEmpty())
+        return;
+
+    if (m_splashScreenModel->stringList().contains(fileName))
+        return;
+
+    int rowCount = m_splashScreenModel->rowCount();
+    m_splashScreenModel->insertRow(rowCount);
+    m_splashScreenModel->setData(m_splashScreenModel->index(rowCount), fileName);
+    addImageAsAsset(fileName);
+}
+
+void BarDescriptorEditorWidget::removeSelectedSplashScreen()
+{
+    QModelIndexList selectedIndexes = m_ui->splashScreensView->selectionModel()->selectedRows();
+    if (selectedIndexes.isEmpty())
+        return;
+
+    foreach (const QModelIndex &index, selectedIndexes) {
+        QString path = m_splashScreenModel->data(index, Qt::DisplayRole).toString();
+
+        QList<QStandardItem*> assetItems = m_assetsModel->findItems(path);
+        foreach (QStandardItem *assetItem, assetItems) {
+            QList<QStandardItem*> assetRow = m_assetsModel->takeRow(assetItem->row());
+            while (!assetRow.isEmpty())
+                delete assetRow.takeLast();
+        }
+
+        m_splashScreenModel->removeRow(index.row());
+    }
+}
+
+void BarDescriptorEditorWidget::handleSplashScreenSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
+{
+    Q_UNUSED(deselected);
+
+    const bool emptySelection = selected.indexes().isEmpty();
+    m_ui->removeSplashScreen->setEnabled(!emptySelection);
+
+    if (!emptySelection) {
+        QString path = m_splashScreenModel->data(selected.indexes().at(0), Qt::DisplayRole).toString();
+        setImagePreview(m_ui->splashScreenPreviewLabel, path);
+    } else {
+        setImagePreview(m_ui->splashScreenPreviewLabel, QString());
+    }
+}
+
+void BarDescriptorEditorWidget::addAsset(const BarDescriptorAsset &asset)
+{
+    const QString path = asset.source;
+    const QString dest = asset.destination;
+    QTC_ASSERT(!path.isEmpty(), return);
+    QTC_ASSERT(!dest.isEmpty(), return);
+
+    if (hasAsset(asset))
+        return;
+
+    disconnect(m_assetsModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updateEntryCheckState(QStandardItem*)));
+
+    QList<QStandardItem *> items;
+    items << new QStandardItem(path);
+    items << new QStandardItem(dest);
+
+    QStandardItem *entryItem = new QStandardItem();
+    entryItem->setCheckable(true);
+    entryItem->setCheckState(asset.entry ? Qt::Checked : Qt::Unchecked);
+    items << entryItem;
+    m_assetsModel->appendRow(items);
+
+    connect(m_assetsModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updateEntryCheckState(QStandardItem*)));
+}
+
+bool BarDescriptorEditorWidget::hasAsset(const BarDescriptorAsset &asset)
+{
+    // TODO: Move this to a specific BarDescriptorAssetModel
+    for (int i = 0; i < m_assetsModel->rowCount(); ++i) {
+        QStandardItem *sourceItem = m_assetsModel->item(i, 0);
+        QStandardItem *destItem = m_assetsModel->item(i, 1);
+        if (sourceItem->text() == asset.source && destItem->text() == asset.destination)
+            return true;
+    }
+
+    return false;
+}
+
+QString BarDescriptorEditorWidget::localAssetPathFromDestination(const QString &destination)
+{
+    for (int i = 0; i < m_assetsModel->rowCount(); ++i) {
+        QStandardItem *destItem = m_assetsModel->item(i, 1);
+        if (destItem->text() == destination)
+            return m_assetsModel->item(i, 0)->text();
+    }
+
+    return QString();
+}
+
+QList<BarDescriptorAsset> BarDescriptorEditorWidget::assets() const
+{
+    QList<BarDescriptorAsset> result;
+
+    for (int i = 0; i < m_assetsModel->rowCount(); ++i) {
+        BarDescriptorAsset asset;
+        asset.source = m_assetsModel->item(i, 0)->text();
+        asset.destination = m_assetsModel->item(i, 1)->text();
+        asset.entry = m_assetsModel->item(i, 2)->checkState() == Qt::Checked;
+        result << asset;
+    }
+
+    return result;
+}
+
+QString BarDescriptorEditorWidget::xmlSource() const
+{
+    return m_ui->xmlSourceView->toPlainText();
+}
+
+void BarDescriptorEditorWidget::setXmlSource(const QString &xmlSource)
+{
+    disconnect(m_ui->xmlSourceView, SIGNAL(changed()), this, SLOT(setDirty()));
+    m_ui->xmlSourceView->setPlainText(xmlSource);
+    connect(m_ui->xmlSourceView, SIGNAL(changed()), this, SLOT(setDirty()));
+}
+
+bool BarDescriptorEditorWidget::isDirty() const
+{
+    return m_dirty;
+}
+
+void BarDescriptorEditorWidget::clear()
+{
+    clearGeneralPage();
+    clearApplicationPage();
+    clearAssetsPage();
+    clearSourcePage();
+}
+
+void BarDescriptorEditorWidget::setDirty(bool dirty)
+{
+    m_dirty = dirty;
+    emit changed();
+}
+
+BarDescriptorEditor *BarDescriptorEditorWidget::createEditor()
+{
+    return new BarDescriptorEditor(this);
+}
+
+void BarDescriptorEditorWidget::addNewAsset()
+{
+    const QString fileName = QFileDialog::getOpenFileName(this, tr("Select file to add"));
+    if (fileName.isEmpty())
+        return;
+
+    QFileInfo fi(fileName);
+    BarDescriptorAsset asset;
+    asset.source = fileName;
+    asset.destination = fi.fileName();
+    asset.entry = false; // TODO
+    addAsset(asset);
+}
+
+void BarDescriptorEditorWidget::removeSelectedAsset()
+{
+    QModelIndexList selectedIndexes = m_ui->assets->selectionModel()->selectedRows();
+    if (selectedIndexes.isEmpty())
+        return;
+
+    foreach (const QModelIndex &index, selectedIndexes)
+        m_assetsModel->removeRow(index.row());
+}
+
+void BarDescriptorEditorWidget::updateEntryCheckState(QStandardItem *item)
+{
+    if (item->column() != 2 || item->checkState() == Qt::Unchecked)
+        return;
+
+    disconnect(m_assetsModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updateEntryCheckState(QStandardItem*)));
+    for (int i = 0; i < m_assetsModel->rowCount(); ++i) {
+        QStandardItem *other = m_assetsModel->item(i, 2);
+        if (other == item)
+            continue;
+
+        // Only one asset can be the entry point
+        other->setCheckState(Qt::Unchecked);
+    }
+    connect(m_assetsModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updateEntryCheckState(QStandardItem*)));
+}
+
+void BarDescriptorEditorWidget::addImageAsAsset(const QString &path)
+{
+    if (path.isEmpty())
+        return;
+
+    BarDescriptorAsset asset;
+    asset.source = path;
+    asset.destination = QFileInfo(path).fileName();
+    asset.entry = false;
+    addAsset(asset);
+}
diff --git a/src/plugins/qnx/bardescriptoreditorwidget.h b/src/plugins/qnx/bardescriptoreditorwidget.h
new file mode 100644
index 00000000000..c20a6ab9755
--- /dev/null
+++ b/src/plugins/qnx/bardescriptoreditorwidget.h
@@ -0,0 +1,187 @@
+/**************************************************************************
+**
+** Copyright (C) 2011 - 2013 Research In Motion
+**
+** Contact: Research In Motion (blackberry-qt@qnx.com)
+** Contact: KDAB (info@kdab.com)
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QNX_INTERNAL_BARDESCRIPTOREDITORWIDGET_H
+#define QNX_INTERNAL_BARDESCRIPTOREDITORWIDGET_H
+
+#include "bardescriptordocument.h"
+
+#include <utils/environment.h>
+
+#include <QtGui/QStackedWidget>
+
+QT_BEGIN_NAMESPACE
+class QItemSelection;
+class QLabel;
+class QLineEdit;
+class QStandardItemModel;
+class QStandardItem;
+class QStringListModel;
+QT_END_NAMESPACE
+
+namespace Core {
+class IEditor;
+}
+
+namespace Qnx {
+namespace Internal {
+
+namespace Ui {
+class BarDescriptorEditorWidget;
+}
+
+class BarDescriptorEditor;
+class BarDescriptorPermissionsModel;
+class BarDescriptorQtAssetsModel;
+class BarDescriptorQtAssetsProxyModel;
+
+class BarDescriptorEditorWidget : public QStackedWidget
+{
+    Q_OBJECT
+
+public:
+    explicit BarDescriptorEditorWidget(QWidget *parent = 0);
+    ~BarDescriptorEditorWidget();
+
+    Core::IEditor *editor() const;
+
+    // General
+    QString packageId() const;
+    void setPackageId(const QString &packageId);
+
+    QString packageVersion() const;
+    void setPackageVersion(const QString &packageVersion);
+
+    QString packageBuildId() const;
+    void setPackageBuildId(const QString &packageBuildId);
+
+    QString author() const;
+    void setAuthor(const QString &author);
+
+    QString authorId() const;
+    void setAuthorId(const QString &authorId);
+
+    // Application
+    QString orientation() const;
+    void setOrientation(const QString &orientation);
+
+    QString chrome() const;
+    void setChrome(const QString &chrome);
+
+    bool transparent() const;
+    void setTransparent(bool transparent);
+
+    void appendApplicationArgument(const QString &argument);
+    QStringList applicationArguments() const;
+
+    QStringList checkedPermissions() const;
+    void checkPermission(const QString &identifier);
+
+    QList<Utils::EnvironmentItem> environment() const;
+    void appendEnvironmentItem(const Utils::EnvironmentItem &envItem);
+
+    QString applicationName() const;
+    void setApplicationName(const QString &applicationName);
+
+    QString applicationDescription() const;
+    void setApplicationDescription(const QString &applicationDescription);
+
+    QString applicationIconFileName() const;
+    void setApplicationIcon(const QString &iconPath);
+
+    QStringList splashScreens() const;
+    void appendSplashScreen(const QString &splashScreenPath);
+
+    // Assets
+    void addAsset(const BarDescriptorAsset &asset);
+    QList<BarDescriptorAsset> assets() const;
+
+    QString xmlSource() const;
+    void setXmlSource(const QString &xmlSource);
+
+    bool isDirty() const;
+    void clear();
+
+public slots:
+    void setDirty(bool dirty = true);
+
+signals:
+    void changed();
+
+private slots:
+    void addNewAsset();
+    void removeSelectedAsset();
+    void updateEntryCheckState(QStandardItem *item);
+    void addImageAsAsset(const QString &path);
+
+    void setApplicationIconDelayed(const QString &iconPath);
+    void setApplicationIconPreview(const QString &path);
+
+    void appendSplashScreenDelayed(const QString &splashScreenPath);
+    void browseForSplashScreen();
+    void removeSelectedSplashScreen();
+    void handleSplashScreenSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
+
+private:
+    BarDescriptorEditor *createEditor();
+
+    void initGeneralPage();
+    void clearGeneralPage();
+    void initApplicationPage();
+    void clearApplicationPage();
+    void initAssetsPage();
+    void clearAssetsPage();
+    void initSourcePage();
+    void clearSourcePage();
+
+    bool hasAsset(const BarDescriptorAsset &asset);
+    QString localAssetPathFromDestination(const QString &path);
+
+    void setImagePreview(QLabel *previewLabel, const QString &path);
+
+    mutable Core::IEditor *m_editor;
+
+    bool m_dirty;
+
+    // Application
+    BarDescriptorPermissionsModel *m_permissionsModel;
+    QStringListModel *m_splashScreenModel;
+
+    // Assets
+    QStandardItemModel *m_assetsModel;
+
+    Ui::BarDescriptorEditorWidget *m_ui;
+};
+
+
+} // namespace Internal
+} // namespace Qnx
+#endif // QNX_INTERNAL_BARDESCRIPTOREDITORWIDGET_H
diff --git a/src/plugins/qnx/bardescriptoreditorwidget.ui b/src/plugins/qnx/bardescriptoreditorwidget.ui
new file mode 100644
index 00000000000..17c1c71bd73
--- /dev/null
+++ b/src/plugins/qnx/bardescriptoreditorwidget.ui
@@ -0,0 +1,540 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Qnx::Internal::BarDescriptorEditorWidget</class>
+ <widget class="QStackedWidget" name="Qnx::Internal::BarDescriptorEditorWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1039</width>
+    <height>735</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>StackedWidget</string>
+  </property>
+  <property name="currentIndex">
+   <number>0</number>
+  </property>
+  <widget class="QWidget" name="generalPage">
+   <layout class="QVBoxLayout" name="verticalLayout_6">
+    <item>
+     <widget class="QScrollArea" name="scrollArea">
+      <property name="frameShape">
+       <enum>QFrame::NoFrame</enum>
+      </property>
+      <property name="widgetResizable">
+       <bool>true</bool>
+      </property>
+      <widget class="QWidget" name="scrollAreaWidgetContents">
+       <property name="geometry">
+        <rect>
+         <x>0</x>
+         <y>0</y>
+         <width>1031</width>
+         <height>727</height>
+        </rect>
+       </property>
+       <layout class="QVBoxLayout" name="verticalLayout">
+        <item>
+         <widget class="QGroupBox" name="groupBox_2">
+          <property name="maximumSize">
+           <size>
+            <width>900</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="title">
+           <string>Package Information</string>
+          </property>
+          <layout class="QFormLayout" name="formLayout">
+           <item row="0" column="0">
+            <widget class="QLabel" name="label">
+             <property name="text">
+              <string>Package ID:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="0" column="1">
+            <widget class="QLineEdit" name="packageId">
+             <property name="maxLength">
+              <number>50</number>
+             </property>
+            </widget>
+           </item>
+           <item row="1" column="0">
+            <widget class="QLabel" name="label_2">
+             <property name="text">
+              <string>Package Version:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="1" column="1">
+            <widget class="QLineEdit" name="packageVersion"/>
+           </item>
+           <item row="2" column="0">
+            <widget class="QLabel" name="label_3">
+             <property name="text">
+              <string>Package Build ID:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="2" column="1">
+            <widget class="QLineEdit" name="packageBuildId"/>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="QGroupBox" name="groupBox_6">
+          <property name="maximumSize">
+           <size>
+            <width>900</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="title">
+           <string>Author Information</string>
+          </property>
+          <layout class="QFormLayout" name="formLayout_3">
+           <item row="0" column="0">
+            <widget class="QLabel" name="label_4">
+             <property name="text">
+              <string>Author:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="0" column="1">
+            <widget class="QLineEdit" name="author"/>
+           </item>
+           <item row="1" column="0">
+            <widget class="QLabel" name="label_15">
+             <property name="text">
+              <string>Author ID:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="1" column="1">
+            <widget class="QLineEdit" name="authorId"/>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <spacer name="verticalSpacer_2">
+          <property name="orientation">
+           <enum>Qt::Vertical</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>40</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </widget>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QWidget" name="applicationPage">
+   <layout class="QVBoxLayout" name="verticalLayout_10">
+    <item>
+     <widget class="QScrollArea" name="scrollArea_2">
+      <property name="frameShape">
+       <enum>QFrame::NoFrame</enum>
+      </property>
+      <property name="widgetResizable">
+       <bool>true</bool>
+      </property>
+      <widget class="QWidget" name="scrollAreaWidgetContents_2">
+       <property name="geometry">
+        <rect>
+         <x>0</x>
+         <y>0</y>
+         <width>1014</width>
+         <height>810</height>
+        </rect>
+       </property>
+       <layout class="QVBoxLayout" name="verticalLayout_7">
+        <item>
+         <widget class="QGroupBox" name="groupBox">
+          <property name="maximumSize">
+           <size>
+            <width>900</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="title">
+           <string>Entry-Point Text and Images</string>
+          </property>
+          <layout class="QFormLayout" name="formLayout_2">
+           <item row="1" column="1">
+            <widget class="QLineEdit" name="applicationName"/>
+           </item>
+           <item row="3" column="1">
+            <widget class="QTextEdit" name="applicationDescription">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+            </widget>
+           </item>
+           <item row="5" column="1">
+            <layout class="QVBoxLayout" name="verticalLayout_8">
+             <item>
+              <widget class="QLabel" name="iconPreviewLabel">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="minimumSize">
+                <size>
+                 <width>90</width>
+                 <height>90</height>
+                </size>
+               </property>
+               <property name="frameShape">
+                <enum>QFrame::Panel</enum>
+               </property>
+               <property name="frameShadow">
+                <enum>QFrame::Sunken</enum>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <layout class="QHBoxLayout" name="horizontalLayout_3">
+               <item>
+                <widget class="Utils::PathChooser" name="iconFilePath" native="true"/>
+               </item>
+               <item>
+                <widget class="QPushButton" name="iconClearButton">
+                 <property name="text">
+                  <string>Clear</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </item>
+            </layout>
+           </item>
+           <item row="6" column="0">
+            <widget class="QLabel" name="label_8">
+             <property name="text">
+              <string>Splash screens:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="7" column="0" colspan="2">
+            <layout class="QHBoxLayout" name="horizontalLayout_4">
+             <item>
+              <widget class="QListView" name="splashScreensView"/>
+             </item>
+             <item>
+              <layout class="QVBoxLayout" name="verticalLayout_9">
+               <item>
+                <widget class="QPushButton" name="addSplashScreen">
+                 <property name="text">
+                  <string>Add...</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QPushButton" name="removeSplashScreen">
+                 <property name="enabled">
+                  <bool>false</bool>
+                 </property>
+                 <property name="text">
+                  <string>Remove</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QLabel" name="splashScreenPreviewLabel">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>90</width>
+                   <height>90</height>
+                  </size>
+                 </property>
+                 <property name="frameShape">
+                  <enum>QFrame::Panel</enum>
+                 </property>
+                 <property name="frameShadow">
+                  <enum>QFrame::Sunken</enum>
+                 </property>
+                 <property name="text">
+                  <string/>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <spacer name="verticalSpacer_3">
+                 <property name="orientation">
+                  <enum>Qt::Vertical</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>20</width>
+                   <height>40</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+              </layout>
+             </item>
+            </layout>
+           </item>
+           <item row="5" column="0">
+            <widget class="QLabel" name="label_7">
+             <property name="text">
+              <string>Icon:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="3" column="0">
+            <widget class="QLabel" name="label_5">
+             <property name="text">
+              <string>Description:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="1" column="0">
+            <widget class="QLabel" name="label_6">
+             <property name="text">
+              <string>Name:</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="QGroupBox" name="groupBox_3">
+          <property name="maximumSize">
+           <size>
+            <width>900</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="title">
+           <string>General</string>
+          </property>
+          <layout class="QFormLayout" name="formLayout_4">
+           <property name="fieldGrowthPolicy">
+            <enum>QFormLayout::ExpandingFieldsGrow</enum>
+           </property>
+           <item row="0" column="0">
+            <widget class="QLabel" name="label_12">
+             <property name="text">
+              <string>Orientation:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="0" column="1">
+            <widget class="QComboBox" name="orientation"/>
+           </item>
+           <item row="1" column="0">
+            <widget class="QLabel" name="label_13">
+             <property name="text">
+              <string>Chrome:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="1" column="1">
+            <widget class="QComboBox" name="chrome"/>
+           </item>
+           <item row="2" column="0" colspan="2">
+            <widget class="QCheckBox" name="transparentMainWindow">
+             <property name="text">
+              <string>Transparent main window</string>
+             </property>
+            </widget>
+           </item>
+           <item row="4" column="0">
+            <widget class="QLabel" name="label_14">
+             <property name="text">
+              <string>Application Arguments:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="4" column="1">
+            <widget class="QLineEdit" name="applicationArguments"/>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="QGroupBox" name="groupBox_4">
+          <property name="maximumSize">
+           <size>
+            <width>900</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="title">
+           <string>Permissions</string>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_3">
+           <item>
+            <widget class="QTreeView" name="permissionsView">
+             <property name="rootIsDecorated">
+              <bool>false</bool>
+             </property>
+             <property name="itemsExpandable">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <layout class="QHBoxLayout" name="horizontalLayout_2">
+             <item>
+              <spacer name="horizontalSpacer">
+               <property name="orientation">
+                <enum>Qt::Horizontal</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>40</width>
+                 <height>20</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+             <item>
+              <widget class="QPushButton" name="selectAllPermissions">
+               <property name="text">
+                <string>Select All</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QPushButton" name="deselectAllPermissions">
+               <property name="text">
+                <string>Deselect All</string>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="QGroupBox" name="groupBox_5">
+          <property name="maximumSize">
+           <size>
+            <width>900</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="title">
+           <string>Environment</string>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_11">
+           <item>
+            <widget class="ProjectExplorer::EnvironmentWidget" name="environmentWidget" native="true"/>
+           </item>
+          </layout>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QWidget" name="assetsPage">
+   <property name="maximumSize">
+    <size>
+     <width>900</width>
+     <height>16777215</height>
+    </size>
+   </property>
+   <layout class="QVBoxLayout" name="verticalLayout_5">
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QTreeView" name="assets">
+        <property name="rootIsDecorated">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <layout class="QVBoxLayout" name="verticalLayout_4">
+        <item>
+         <widget class="QPushButton" name="addAsset">
+          <property name="text">
+           <string>Add...</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="removeAsset">
+          <property name="text">
+           <string>Remove</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="verticalSpacer">
+          <property name="orientation">
+           <enum>Qt::Vertical</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>40</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QWidget" name="sourcePage">
+   <layout class="QVBoxLayout" name="verticalLayout_2">
+    <item>
+     <widget class="TextEditor::PlainTextEditorWidget" name="xmlSourceView"/>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>TextEditor::PlainTextEditorWidget</class>
+   <extends>QPlainTextEdit</extends>
+   <header location="global">texteditor/plaintexteditor.h</header>
+  </customwidget>
+  <customwidget>
+   <class>Utils::PathChooser</class>
+   <extends>QWidget</extends>
+   <header location="global">utils/pathchooser.h</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>ProjectExplorer::EnvironmentWidget</class>
+   <extends>QWidget</extends>
+   <header location="global">projectexplorer/environmentwidget.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qnx/bardescriptormagicmatcher.cpp b/src/plugins/qnx/bardescriptormagicmatcher.cpp
new file mode 100644
index 00000000000..8c643fa586f
--- /dev/null
+++ b/src/plugins/qnx/bardescriptormagicmatcher.cpp
@@ -0,0 +1,55 @@
+/**************************************************************************
+**
+** Copyright (C) 2011 - 2013 Research In Motion
+**
+** Contact: Research In Motion (blackberry-qt@qnx.com)
+** Contact: KDAB (info@kdab.com)
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "bardescriptormagicmatcher.h"
+
+#include <QtXml/QXmlStreamReader>
+
+using namespace Qnx;
+using namespace Qnx::Internal;
+
+BarDescriptorMagicMatcher::BarDescriptorMagicMatcher()
+{
+}
+
+bool BarDescriptorMagicMatcher::matches(const QByteArray &data) const
+{
+    QXmlStreamReader reader(data);
+    if (reader.readNextStartElement())
+        return reader.name() == QLatin1String("qnx");
+
+    return false;
+}
+
+int BarDescriptorMagicMatcher::priority() const
+{
+    return Core::MimeGlobPattern::MaxWeight;
+}
diff --git a/src/plugins/qnx/bardescriptormagicmatcher.h b/src/plugins/qnx/bardescriptormagicmatcher.h
new file mode 100644
index 00000000000..661cd3bd08d
--- /dev/null
+++ b/src/plugins/qnx/bardescriptormagicmatcher.h
@@ -0,0 +1,52 @@
+/**************************************************************************
+**
+** Copyright (C) 2011 - 2013 Research In Motion
+**
+** Contact: Research In Motion (blackberry-qt@qnx.com)
+** Contact: KDAB (info@kdab.com)
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QNX_INTERNAL_BARDESCRIPTORMAGICMATCHER_H
+#define QNX_INTERNAL_BARDESCRIPTORMAGICMATCHER_H
+
+#include <coreplugin/mimedatabase.h>
+
+namespace Qnx {
+namespace Internal {
+
+class BarDescriptorMagicMatcher : public Core::IMagicMatcher
+{
+public:
+    BarDescriptorMagicMatcher();
+
+    bool matches(const QByteArray &data) const;
+    int priority() const;
+};
+
+} // namespace Internal
+} // namespace Qnx
+
+#endif // QNX_INTERNAL_BARDESCRIPTORMAGICMATCHER_H
diff --git a/src/plugins/qnx/bardescriptorpermissionsmodel.cpp b/src/plugins/qnx/bardescriptorpermissionsmodel.cpp
new file mode 100644
index 00000000000..ccd700b5455
--- /dev/null
+++ b/src/plugins/qnx/bardescriptorpermissionsmodel.cpp
@@ -0,0 +1,170 @@
+/**************************************************************************
+**
+** Copyright (C) 2011 - 2013 Research In Motion
+**
+** Contact: Research In Motion (blackberry-qt@qnx.com)
+** Contact: KDAB (info@kdab.com)
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "bardescriptorpermissionsmodel.h"
+
+#include <QStringList>
+
+using namespace Qnx;
+using namespace Qnx::Internal;
+
+BarDescriptorPermissionsModel::BarDescriptorPermissionsModel(QObject *parent) :
+    QAbstractTableModel(parent)
+{
+    initModel();
+}
+
+Qt::ItemFlags BarDescriptorPermissionsModel::flags(const QModelIndex &index) const
+{
+    Qt::ItemFlags flags = QAbstractTableModel::flags(index);
+    flags |= Qt::ItemIsUserCheckable;
+    return flags;
+}
+
+int BarDescriptorPermissionsModel::rowCount(const QModelIndex &parent) const
+{
+    Q_UNUSED(parent);
+    return m_permissions.size();
+}
+
+int BarDescriptorPermissionsModel::columnCount(const QModelIndex &parent) const
+{
+    Q_UNUSED(parent);
+    return 1;
+}
+
+QVariant BarDescriptorPermissionsModel::data(const QModelIndex &index, int role) const
+{
+    if (!index.isValid() || index.row() >= m_permissions.size() || index.column() >= 1)
+        return QVariant();
+
+    BarDescriptorPermission perm = m_permissions[index.row()];
+    switch (role) {
+    case Qt::DisplayRole:
+    case Qt::EditRole:
+        return perm.permission;
+    case Qt::CheckStateRole:
+        return perm.checked ? Qt::Checked : Qt::Unchecked;
+    case Qt::ToolTipRole:
+        return perm.description;
+    case IdentifierRole:
+        return perm.identifier;
+    }
+
+    return QVariant();
+}
+
+bool BarDescriptorPermissionsModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+    if (!index.isValid() || index.row() >= m_permissions.size() || index.column() >= 1)
+        return false;
+
+    if (role == Qt::CheckStateRole) {
+        BarDescriptorPermission &perm = m_permissions[index.row()];
+        perm.checked = static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked;
+        emit dataChanged(index, index);
+
+        return true;
+    }
+
+    return false;
+}
+
+QVariant BarDescriptorPermissionsModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+    if (role != Qt::DisplayRole || orientation == Qt::Vertical)
+        return QVariant();
+
+    if (section == 0)
+        return tr("Permission");
+
+    return QVariant();
+}
+
+void BarDescriptorPermissionsModel::uncheckAll()
+{
+    setCheckStateAll(Qt::Unchecked);
+}
+
+void BarDescriptorPermissionsModel::checkAll()
+{
+    setCheckStateAll(Qt::Checked);
+}
+
+void BarDescriptorPermissionsModel::checkPermission(const QString &identifier)
+{
+    for (int i = 0; i < rowCount(); ++i) {
+        QModelIndex idx = index(i, 0);
+        if (data(idx, IdentifierRole).toString() == identifier)
+            setData(idx, Qt::Checked, Qt::CheckStateRole);
+    }
+}
+
+QStringList BarDescriptorPermissionsModel::checkedIdentifiers() const
+{
+    QStringList result;
+    foreach (const BarDescriptorPermission &perm, m_permissions) {
+        if (perm.checked)
+            result << perm.identifier;
+    }
+    return result;
+}
+
+void BarDescriptorPermissionsModel::initModel()
+{
+    beginResetModel();
+    m_permissions << BarDescriptorPermission(tr("Files"), QLatin1String("access_shared"),
+                                             tr("Read and write files that are shared between all applications run by the current user."));
+    m_permissions << BarDescriptorPermission(tr("Microphone"), QLatin1String("record_audio"),
+                                             tr("Access the audio stream from the microphone."));
+    m_permissions << BarDescriptorPermission(tr("GPS Location"), QLatin1String("read_geolocation"),
+                                             tr("Read the current location of the device."));
+    m_permissions << BarDescriptorPermission(tr("Camera"), QLatin1String("use_camera"),
+                                             tr("Capture images and video using the cameras."));
+    m_permissions << BarDescriptorPermission(tr("Internet"), QLatin1String("access_internet"),
+                                             tr("Use a Wi-Fi, wired, or other connection to a destination that is not local."));
+    m_permissions << BarDescriptorPermission(tr("Play Sounds"), QLatin1String("play_audio"),
+                                             tr("Play an audio stream."));
+    m_permissions << BarDescriptorPermission(tr("Post Notifications"), QLatin1String("post_notification"),
+                                             tr("Post a notification to the notifications area of the screen."));
+    m_permissions << BarDescriptorPermission(tr("Set Audio Volume"), QLatin1String("set_audio_volume"),
+                                             tr("Change the volume of an audio stream being played."));
+    m_permissions << BarDescriptorPermission(tr("Device Identifying Information"), QLatin1String("read_device_identifying_information"),
+                                             tr("Access unique device identifying information (e.g. PIN)."));
+    endResetModel();
+}
+
+
+void BarDescriptorPermissionsModel::setCheckStateAll(Qt::CheckState checkState)
+{
+    for (int i = 0; i < rowCount(); ++i)
+        setData(index(i, 0), checkState, Qt::CheckStateRole);
+}
diff --git a/src/plugins/qnx/bardescriptorpermissionsmodel.h b/src/plugins/qnx/bardescriptorpermissionsmodel.h
new file mode 100644
index 00000000000..1d1c60f3a95
--- /dev/null
+++ b/src/plugins/qnx/bardescriptorpermissionsmodel.h
@@ -0,0 +1,94 @@
+/**************************************************************************
+**
+** Copyright (C) 2011 - 2013 Research In Motion
+**
+** Contact: Research In Motion (blackberry-qt@qnx.com)
+** Contact: KDAB (info@kdab.com)
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QNX_INTERNAL_BARDESCRIPTORPERMISSIONSMODEL_H
+#define QNX_INTERNAL_BARDESCRIPTORPERMISSIONSMODEL_H
+
+#include <QAbstractTableModel>
+
+namespace Qnx {
+namespace Internal {
+
+class BarDescriptorPermission {
+public:
+    BarDescriptorPermission(const QString &perm, const QString &ident, const QString &desc)
+        : checked(false)
+        , permission(perm)
+        , identifier(ident)
+        , description(desc)
+    {
+    }
+
+    bool checked;
+    QString permission;
+    QString identifier;
+    QString description;
+};
+
+class BarDescriptorPermissionsModel : public QAbstractTableModel
+{
+    Q_OBJECT
+public:
+    explicit BarDescriptorPermissionsModel(QObject *parent = 0);
+
+    Qt::ItemFlags flags(const QModelIndex &index) const;
+
+    int rowCount(const QModelIndex &parent = QModelIndex()) const;
+    int columnCount(const QModelIndex &parent = QModelIndex()) const;
+
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+
+    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+
+    void checkPermission(const QString &identifier);
+    QStringList checkedIdentifiers() const;
+
+public slots:
+    void uncheckAll();
+    void checkAll();
+
+private:
+    enum DataRole {
+        IdentifierRole = Qt::UserRole
+    };
+
+    void setCheckStateAll(Qt::CheckState checkState);
+
+    void initModel();
+
+    QList<BarDescriptorPermission> m_permissions;
+};
+
+} // namespace Internal
+} // namespace Qnx
+
+#endif // QNX_INTERNAL_BARDESCRIPTORPERMISSIONSMODEL_H
diff --git a/src/plugins/qnx/qnx.pro b/src/plugins/qnx/qnx.pro
index 382635a3f43..01e82f444b9 100644
--- a/src/plugins/qnx/qnx.pro
+++ b/src/plugins/qnx/qnx.pro
@@ -55,7 +55,14 @@ SOURCES += qnxplugin.cpp \
     blackberryabstractdeploystep.cpp \
     blackberryndksettingswidget.cpp \
     blackberryndksettingspage.cpp \
-    blackberryconfiguration.cpp
+    blackberryconfiguration.cpp \
+    bardescriptormagicmatcher.cpp \
+    bardescriptoreditorfactory.cpp \
+    bardescriptoreditor.cpp \
+    bardescriptoreditorwidget.cpp \
+    bardescriptordocument.cpp \
+    bardescriptordocumentnodehandlers.cpp \
+    bardescriptorpermissionsmodel.cpp
 
 HEADERS += qnxplugin.h\
     qnxconstants.h \
@@ -107,7 +114,14 @@ HEADERS += qnxplugin.h\
     blackberryabstractdeploystep.h \
     blackberryndksettingswidget.h \
     blackberryndksettingspage.h \
-    blackberryconfiguration.h
+    blackberryconfiguration.h \
+    bardescriptormagicmatcher.h \
+    bardescriptoreditorfactory.h \
+    bardescriptoreditor.h \
+    bardescriptoreditorwidget.h \
+    bardescriptordocument.h \
+    bardescriptordocumentnodehandlers.h \
+    bardescriptorpermissionsmodel.h
 
 FORMS += \
     blackberrydeviceconfigurationwizardsetuppage.ui \
@@ -117,7 +131,10 @@ FORMS += \
     blackberrydeviceconfigurationwidget.ui \
     qnxbaseqtconfigwidget.ui \
     bardescriptorfileimagewizardpage.ui \
-    blackberryndksettingswidget.ui
+    blackberryndksettingswidget.ui \
+    bardescriptoreditorwidget.ui
+
+DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
 
 RESOURCES += \
     qnx.qrc
diff --git a/src/plugins/qnx/qnx.qbs b/src/plugins/qnx/qnx.qbs
index c420728c297..7cf3b510499 100644
--- a/src/plugins/qnx/qnx.qbs
+++ b/src/plugins/qnx/qnx.qbs
@@ -17,9 +17,24 @@ QtcPlugin {
     cpp.includePaths: base.concat("../../shared")
 
     files: [
+        "bardescriptordocument.cpp",
+        "bardescriptordocument.h",
+        "bardescriptordocumentnodehandlers.cpp",
+        "bardescriptordocumentnodehandlers.h",
+        "bardescriptoreditor.cpp",
+        "bardescriptoreditor.h",
+        "bardescriptoreditorfactory.cpp",
+        "bardescriptoreditorfactory.h",
+        "bardescriptoreditorwidget.cpp",
+        "bardescriptoreditorwidget.h",
+        "bardescriptoreditorwidget.ui",
         "bardescriptorfileimagewizardpage.cpp",
         "bardescriptorfileimagewizardpage.h",
         "bardescriptorfileimagewizardpage.ui",
+        "bardescriptormagicmatcher.cpp",
+        "bardescriptormagicmatcher.h",
+        "bardescriptorpermissionsmodel.cpp",
+        "bardescriptorpermissionsmodel.h",
         "blackberryabstractdeploystep.cpp",
         "blackberryabstractdeploystep.h",
         "blackberryapplicationrunner.cpp",
diff --git a/src/plugins/qnx/qnxconstants.h b/src/plugins/qnx/qnxconstants.h
index 3b428ac3197..f9444a95563 100644
--- a/src/plugins/qnx/qnxconstants.h
+++ b/src/plugins/qnx/qnxconstants.h
@@ -94,6 +94,10 @@ const char QNX_BB_CATEGORY_TR[] = QT_TRANSLATE_NOOP("BlackBerry", "BlackBerry");
 const char QNX_BB_CATEGORY_ICON[] = ":/qnx/images/target.png";
 const char QNX_BB_NDK_SETTINGS_ID[] = "ZZ.BlackBerry NDK Configuration";
 
+const char QNX_BAR_DESCRIPTOR_MIME_TYPE[] = "application/vnd.rim.qnx.bar_descriptor";
+const char QNX_BAR_DESCRIPTOR_EDITOR_ID[] = "Qnx.BarDescriptorEditor";
+
+const char QNX_TASK_CATEGORY_BARDESCRIPTOR[] = "Task.Category.BarDescriptor";
 } // namespace Constants
 } // namespace Qnx
 
diff --git a/src/plugins/qnx/qnxplugin.cpp b/src/plugins/qnx/qnxplugin.cpp
index 82662a1ce08..9f84492d511 100644
--- a/src/plugins/qnx/qnxplugin.cpp
+++ b/src/plugins/qnx/qnxplugin.cpp
@@ -47,6 +47,11 @@
 #include "qnxqtversionfactory.h"
 #include "blackberrywizardextension.h"
 #include "blackberryndksettingspage.h"
+#include "bardescriptoreditorfactory.h"
+#include "bardescriptormagicmatcher.h"
+
+#include <coreplugin/icore.h>
+#include <coreplugin/mimedatabase.h>
 
 #include <QtPlugin>
 
@@ -84,6 +89,23 @@ bool QNXPlugin::initialize(const QStringList &arguments, QString *errorString)
     addAutoReleasedObject(new QnxDeployConfigurationFactory);
     addAutoReleasedObject(new QnxRunConfigurationFactory);
 
+    // bar-descriptor.xml editor
+    Core::MimeGlobPattern barDescriptorGlobPattern(QRegExp(QLatin1String("*.xml"), Qt::CaseInsensitive, QRegExp::Wildcard), Core::MimeGlobPattern::MinWeight + 1);
+    Core::MimeType barDescriptorMimeType;
+    barDescriptorMimeType.setType(QLatin1String(Constants::QNX_BAR_DESCRIPTOR_MIME_TYPE));
+    barDescriptorMimeType.setComment(tr("Bar descriptor file (BlackBerry"));
+    barDescriptorMimeType.setGlobPatterns(QList<Core::MimeGlobPattern>() << barDescriptorGlobPattern);
+    barDescriptorMimeType.addMagicMatcher(QSharedPointer<Core::IMagicMatcher>(new BarDescriptorMagicMatcher));
+    barDescriptorMimeType.setSubClassesOf(QStringList() << QLatin1String("application/xml"));
+
+    Core::ICore *core = Core::ICore::instance();
+    Core::MimeDatabase *mdb = core->mimeDatabase();
+    if (!mdb->addMimeType(barDescriptorMimeType)) {
+        *errorString = tr("Could not add mime-type for bar-descriptor.xml editor");
+        return false;
+    }
+    addAutoReleasedObject(new BarDescriptorEditorFactory);
+
     return true;
 }
 
-- 
GitLab