Commit a97242e3 authored by Frantisek Vacek's avatar Frantisek Vacek Committed by Fanda Vacek
Browse files

Qnx: Momentics Cascades project importer



Change-Id: I232d97cd1570b37f694540337b1075800e330e97
Reviewed-by: Nicolas Arnaud-Cormos's avatarNicolas Arnaud-Cormos <nicolas@kdab.com>
parent 9a97c424
......@@ -187,15 +187,18 @@ BaseFileWizard::~BaseFileWizard()
{
}
BaseFileWizard::ExtensionList BaseFileWizard::selectExtensions()
{
return ExtensionSystem::PluginManager::getObjects<IFileWizardExtension>();
}
void BaseFileWizard::runWizard(const QString &path, QWidget *parent, const QString &platform, const QVariantMap &extraValues)
{
QTC_ASSERT(!path.isEmpty(), return);
typedef QList<IFileWizardExtension*> ExtensionList;
QString errorMessage;
// Compile extension pages, purge out unused ones
ExtensionList extensions = ExtensionSystem::PluginManager::getObjects<IFileWizardExtension>();
ExtensionList extensions = selectExtensions();
WizardPageList allExtensionPages;
for (ExtensionList::iterator it = extensions.begin(); it != extensions.end(); ) {
const WizardPageList extensionPages = (*it)->extensionPages(this);
......
......@@ -52,6 +52,8 @@ namespace Utils { class Wizard; }
namespace Core {
class IFileWizardExtension;
class CORE_EXPORT WizardDialogParameters
{
public:
......@@ -117,9 +119,12 @@ public:
protected:
typedef QList<QWizardPage *> WizardPageList;
typedef QList<Core::IFileWizardExtension*> ExtensionList;
explicit BaseFileWizard(QObject *parent = 0);
virtual ExtensionList selectExtensions();
virtual QWizard *createWizardDialog(QWidget *parent,
const WizardDialogParameters &wizardDialogParameters) const = 0;
......
/****************************************************************************
**
** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: BlackBerry Limited (blackberry-qt@qnx.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 "bardescriptorconverter.h"
#include <coreplugin/generatedfile.h>
#include <utils/qtcassert.h>
#include <QDomDocument>
namespace Qnx {
namespace Internal {
//////////////////////////////////////////////////////////////////////////////
//
// BarDescriptorConverter
//
//////////////////////////////////////////////////////////////////////////////
static const char S_ASSET[] = "asset";
static const char S_PATH[] = "path";
static const char S_SRC_DIR[] = "%SRC_DIR%/";
BarDescriptorConverter::BarDescriptorConverter(ConvertedProjectContext &ctx)
: FileConverter(ctx)
{
}
QString BarDescriptorConverter::projectName() const
{
return convertedProjectContext().projectName();
}
QString BarDescriptorConverter::applicationBinaryName() const
{
return projectName();
}
QString BarDescriptorConverter::applicationBinaryPath() const
{
return projectName();
}
QDomElement BarDescriptorConverter::findElement(QDomDocument &doc, const QString &tagName,
const QString &attributeName, const QString &attributeValue)
{
QDomElement ret;
QTC_ASSERT(!tagName.isEmpty(), return ret);
QDomElement rootElement = doc.documentElement();
static const QLatin1String elementTextFakeAttributeNameString("S_ELEMENT_TEXT_FAKE_ATTRIBUTE_NAME");
bool isFindText = (attributeName == elementTextFakeAttributeNameString);
QRegExp rxAttrValue;
if (!isFindText && !attributeValue.isEmpty())
rxAttrValue = QRegExp(attributeValue, Qt::CaseSensitive, QRegExp::Wildcard);
for (QDomElement el = rootElement.firstChildElement(tagName);
!el.isNull(); el = el.nextSiblingElement(tagName)) {
if (attributeName.isEmpty()) {
// take first matching tag name
ret = el;
break;
} else if (isFindText) {
QString s = el.text();
if (s == attributeValue) {
ret = el;
break;
}
} else if (el.hasAttribute(attributeName)) {
if (attributeValue.isEmpty() || rxAttrValue.exactMatch(el.attribute(attributeName))) {
ret = el;
break;
}
}
}
return ret;
}
QDomElement BarDescriptorConverter::ensureElement(QDomDocument &doc, const QString &tagName,
const QString &attributeName, const QString &attributeValue)
{
QDomElement ret = findElement(doc, tagName, attributeName, attributeValue);
if (ret.isNull()) {
QDomElement rootElement = doc.documentElement();
ret = rootElement.appendChild(doc.createElement(tagName)).toElement();
QTC_ASSERT(!ret.isNull(), return ret);
}
if (!attributeName.isEmpty()) {
ret.setAttribute(attributeName, attributeValue);
}
return ret;
}
QDomElement BarDescriptorConverter::removeElement(QDomDocument &doc, const QString &tagName,
const QString &attributeName, const QString &attributeValue)
{
QDomElement ret = findElement(doc, tagName, attributeName, attributeValue);
if (!ret.isNull()) {
QDomNode nd = ret.parentNode();
QTC_ASSERT(!nd.isNull(), return ret);
nd.removeChild(ret);
}
return ret;
}
void BarDescriptorConverter::setEnv(QDomDocument &doc, const QString &name, const QString &value)
{
QDomElement el = ensureElement(doc, QLatin1String("env"), QLatin1String("var"), name);
QTC_ASSERT(!el.isNull(), return);
el.setAttribute(QString::fromLatin1("value"), value);
}
void BarDescriptorConverter::setAsset(QDomDocument &doc, const QString &srcPath,
const QString &destPath, const QString &type, bool isEntry)
{
ImportLog &log = convertedProjectContext().importLog();
log.logInfo(tr("Setting asset path: %1 to %2 type: %3 entry point: %4")
.arg(srcPath).arg(destPath).arg(type).arg(isEntry));
QDomElement assetElement = ensureElement(doc, QLatin1String(S_ASSET), QLatin1String(S_PATH), srcPath);
QTC_ASSERT(!assetElement.isNull(), return);
while (assetElement.hasChildNodes()) {
QDomNode nd = assetElement.firstChild();
assetElement.removeChild(nd);
}
assetElement.appendChild(doc.createTextNode(destPath));
const QString typeString = QLatin1String("type");
QString s = assetElement.attribute(typeString);
if (s != type)
assetElement.setAttribute(typeString, type);
const QString entryString = QLatin1String("entry");
s = assetElement.attribute(entryString);
bool b = (s.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0)
|| (s.compare(QLatin1String("1")) == 0);
if (b != isEntry)
assetElement.setAttribute(entryString, QVariant(isEntry).toString());
}
void BarDescriptorConverter::removeAsset(QDomDocument &doc, const QString &srcPath)
{
ImportLog &log = convertedProjectContext().importLog();
log.logInfo(tr("Removing asset path: %1").arg(srcPath));
removeElement(doc, QLatin1String(S_ASSET), QLatin1String(S_PATH), srcPath);
}
void BarDescriptorConverter::replaceAssetSourcePath(QDomDocument &doc, const QString &oldSrcPath,
const QString &newSrcPath)
{
ImportLog &log = convertedProjectContext().importLog();
QDomElement el = ensureElement(doc, QLatin1String(S_ASSET), QLatin1String(S_PATH), oldSrcPath);
if (!el.isNull()) {
log.logInfo(tr("Replacing asset source path: %1 -> %2").arg(oldSrcPath).arg(newSrcPath));
el.setAttribute(QLatin1String(S_PATH), newSrcPath);
}
}
void BarDescriptorConverter::fixImageAsset(QDomDocument &doc, const QString &definitionElementName)
{
ImportLog &log = convertedProjectContext().importLog();
QString target;
QDomElement el = findElement(doc, definitionElementName, QString(), QString());
if (!el.isNull()) {
const QString imageString = QLatin1String("image");
for (QDomElement imageElement = el.firstChildElement(imageString); !imageElement.isNull();
imageElement = imageElement.nextSiblingElement(imageString)) {
target = imageElement.text();
if (!target.isEmpty())
replaceAssetSourcePath(doc, target, QLatin1String(S_SRC_DIR) % target);
}
} else {
log.logWarning(tr("Cannot find image asset definition: <%1>").arg(definitionElementName));
}
}
void BarDescriptorConverter::fixIconAsset(QDomDocument &doc)
{
const QString iconString = QString::fromLatin1("icon");
fixImageAsset(doc, iconString);
}
void BarDescriptorConverter::fixSplashScreensAsset(QDomDocument &doc)
{
const QString splashScreensString = QString::fromLatin1("splashScreens");
fixImageAsset(doc, splashScreensString);
}
bool BarDescriptorConverter::convertFile(Core::GeneratedFile &file, QString &errorMessage)
{
FileConverter::convertFile(file, errorMessage);
if (errorMessage.isEmpty()) {
QDomDocument doc;
if (!doc.setContent(file.binaryContents(), &errorMessage)) {
errorMessage = tr("Error parsing XML file '%1': %2").arg(file.path()).arg(errorMessage);
return false;
}
// remove <configuration> elements, since they are Momentics specific
QDomElement rootElement = doc.documentElement();
const QString configurationString = QLatin1String("configuration");
while (true) {
QDomElement el = rootElement.firstChildElement(configurationString);
if (el.isNull())
break;
rootElement.removeChild(el);
}
// remove obsolete assets
removeAsset(doc, QLatin1String("translations"));
removeAsset(doc, QLatin1String("translations/*"));
// assets
setAsset(doc, applicationBinaryPath(), applicationBinaryName(),
QLatin1String("Qnx/Elf"), true);
const QString assetsString = QLatin1String("assets");
replaceAssetSourcePath(doc, assetsString, QLatin1String(S_SRC_DIR) % assetsString);
fixIconAsset(doc);
fixSplashScreensAsset(doc);
file.setBinaryContents(doc.toByteArray(4));
}
return errorMessage.isEmpty();
}
} // namespace Internal
} // namespace Qnx
/****************************************************************************
**
** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: BlackBerry Limited (blackberry-qt@qnx.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_BLACKBERRY_CASCADESPROJECTIMPORT_BARDESCRIPTORCONVERTER_H
#define QNX_BLACKBERRY_CASCADESPROJECTIMPORT_BARDESCRIPTORCONVERTER_H
#include "fileconverter.h"
#include <QCoreApplication>
class QDomElement;
class QDomDocument;
namespace Qnx {
namespace Internal {
class BarDescriptorConverter : public FileConverter
{
Q_DECLARE_TR_FUNCTIONS(BarDescriptorConverter);
public:
BarDescriptorConverter(ConvertedProjectContext &ctx);
virtual ~BarDescriptorConverter() {}
bool convertFile(Core::GeneratedFile &file, QString &errorMessage);
private:
QString projectName() const;
QString applicationBinaryName() const;
QString applicationBinaryPath() const;
QDomElement findElement(QDomDocument &doc, const QString &tagName,
const QString &attributeName, const QString &attributeValue);
QDomElement ensureElement(QDomDocument &doc, const QString &tagName,
const QString &attributeName, const QString &attributeValue);
QDomElement removeElement(QDomDocument &doc, const QString &tagName,
const QString &attributeName, const QString &attributeValue);
void fixImageAsset(QDomDocument &doc, const QString &definitionElementName);
void fixIconAsset(QDomDocument &doc);
void fixSplashScreensAsset(QDomDocument &doc);
void setEnv(QDomDocument &doc, const QString &name, const QString &value);
void setAsset(QDomDocument &doc, const QString &srcPath, const QString &destPath, const QString &type = QString(), bool isEntry = false);
void removeAsset(QDomDocument &doc, const QString &srcPath);
void replaceAssetSourcePath(QDomDocument &doc, const QString &oldSrcPath, const QString &newSrcPath);
};
} // namespace Internal
} // namespace Qnx
#endif // QNX_BLACKBERRY_CASCADESPROJECTIMPORT_BARDESCRIPTORCONVERTER_H
SOURCES += \
$$PWD/cascadesimportwizard.cpp \
$$PWD/srcprojectwizardpage.cpp \
$$PWD/fileconverter.cpp \
$$PWD/bardescriptorconverter.cpp \
$$PWD/projectfileconverter.cpp \
$$PWD/importlogconverter.cpp \
$$PWD/importlog.cpp \
HEADERS += \
$$PWD/cascadesimportwizard.h \
$$PWD/srcprojectwizardpage.h \
$$PWD/fileconverter.h \
$$PWD/bardescriptorconverter.h \
$$PWD/projectfileconverter.h \
$$PWD/importlogconverter.h \
$$PWD/importlog.h \
FORMS += \
$$PWD/srcprojectwizardpage.ui \
RESOURCES += \
$$PWD/cascadesimport.qrc \
<RCC>
<qresource prefix="/qnx/cascadesimport">
<file>resources/templates/project.pro</file>
</qresource>
</RCC>
/****************************************************************************
**
** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: BlackBerry Limited (blackberry-qt@qnx.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 "cascadesimportwizard.h"
#include "srcprojectwizardpage.h"
#include "bardescriptorconverter.h"
#include "importlogconverter.h"
#include "projectfileconverter.h"
#include <qnxconstants.h>
#include <coreplugin/icore.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/customwizard/customwizard.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/documentmanager.h>
#include <utils/projectintropage.h>
#include <utils/qtcassert.h>
#include <QDir>
#include <QFileInfo>
#include <QPainter>
#include <QPixmap>
#include <QIcon>
#include <QStringBuilder>
#include <QDirIterator>
namespace Qnx {
namespace Internal {
//////////////////////////////////////////////////////////////////////////////
//
// CascadesImportWizardDialog
//
//////////////////////////////////////////////////////////////////////////////
CascadesImportWizardDialog::CascadesImportWizardDialog(QWidget *parent)
: Utils::Wizard(parent)
{
setWindowTitle(tr("Import Existing Momentics Cascades Project"));
m_srcProjectPage = new SrcProjectWizardPage(this);
m_srcProjectPage->setTitle(tr("Momentics Cascades Project Name and Location"));
m_destProjectPage = new Utils::ProjectIntroPage(this);
m_destProjectPage->setTitle(tr("Project Name and Location"));
m_destProjectPage->setPath(Core::DocumentManager::projectsDirectory());
const int srcProjectPageId = addPage(m_srcProjectPage);
wizardProgress()->item(srcProjectPageId)->setTitle(tr("Momentics"));
const int destProjectPageId = addPage(m_destProjectPage);
wizardProgress()->item(destProjectPageId)->setTitle(tr("QtCreator"));
connect(m_srcProjectPage, SIGNAL(validPathChanged(QString)), this, SLOT(onSrcProjectPathChanged(QString)));
}
QString CascadesImportWizardDialog::srcProjectPath() const
{
return m_srcProjectPage->path();
}
QString CascadesImportWizardDialog::destProjectPath() const
{
return m_destProjectPage->path() % QLatin1Char('/') % projectName();
}
QString CascadesImportWizardDialog::projectName() const
{
return m_destProjectPage->projectName();
}
void CascadesImportWizardDialog::onSrcProjectPathChanged(const QString &path)
{
Q_UNUSED(path);
m_destProjectPage->setProjectName(m_srcProjectPage->projectName());
}
//////////////////////////////////////////////////////////////////////////////
//
// Wizard
//
//////////////////////////////////////////////////////////////////////////////
static const char IMPORT_LOG_FILE_NAME[] = "import.log";
CascadesImportWizard::CascadesImportWizard(QObject *parent)
: Core::BaseFileWizard(parent)
{
setWizardKind(ProjectWizard);
setIcon(QPixmap(QLatin1String(Qnx::Constants::QNX_BB_CATEGORY_ICON)));
setDisplayName(tr("Momentics Cascades Project"));
setId(QLatin1String("Q.QnxBlackBerryCascadesApp"));
setRequiredFeatures(Core::FeatureSet(Constants::QNX_BB_FEATURE));
setDescription(tr("Imports existing Cascades projects created within QNX Momentics IDE. "
"This allows you to use the project in QtCreator."));
setCategory(QLatin1String(ProjectExplorer::Constants::IMPORT_WIZARD_CATEGORY));
setDisplayCategory(QLatin1String(ProjectExplorer::Constants::IMPORT_WIZARD_CATEGORY_DISPLAY));
}
CascadesImportWizard::~CascadesImportWizard()
{
}
Core::FeatureSet CascadesImportWizard::requiredFeatures() const
{
return Core::FeatureSet(Constants::QNX_BB_FEATURE);
}
Core::BaseFileWizard::ExtensionList CascadesImportWizard::selectExtensions()
{
return Core::BaseFileWizard::ExtensionList();
}
QWizard *CascadesImportWizard::createWizardDialog(QWidget *parent,
const Core::WizardDialogParameters &wizardDialogParameters) const
{
CascadesImportWizardDialog *wizard = new CascadesImportWizardDialog(parent);
setupWizard(wizard);
foreach (QWizardPage *p, wizardDialogParameters.extensionPages())
BaseFileWizard::applyExtensionPageShortTitle(wizard, wizard->addPage(p));
return wizard;
}
bool CascadesImportWizard::convertFile(Core::GeneratedFile &file,
ConvertedProjectContext &projectContext, QString &errorMessage) const
{
bool ret = false;
if (convertFileContent(file, projectContext, errorMessage))
if (convertFilePath(file, projectContext, errorMessage))
ret = true;
return ret;
}
bool CascadesImportWizard::convertFileContent(Core::GeneratedFile &file,
ConvertedProjectContext &projectContext, QString &errorMessage) const
{
QString filePath = file.path();
QString fileName = filePath.section(QLatin1Char('/'), -1);
bool isRootFile = (fileName == filePath);
QString fileExtension = fileName.section(QLatin1Char('.'), -1).toLower();
bool useFileConverter = true;
if (isRootFile) {
if (fileName == QLatin1String("bar-descriptor.xml")) {
BarDescriptorConverter conv(projectContext);
conv.convertFile(file, errorMessage);
useFileConverter = false;
} else if (fileName == QLatin1String(IMPORT_LOG_FILE_NAME)) {
ImportLogConverter conv(projectContext);
conv.convertFile(file, errorMessage);
useFileConverter = false;