Commit 2964f7a9 authored by Feetu Nyrhinen's avatar Feetu Nyrhinen Committed by Alessandro Portale
Browse files

Qt Quick Components Wizard

Selection of Qt Quick component set
and use of specific QML template files (Qt Quick 1.0 and
com.nokia.symbian 1.0) based on the user selections.

Change-Id: I93cfa8735dcf285c76ff04a6186a4eca1f90a361
Reviewed-on: http://codereview.qt.nokia.com/567

Reviewed-by: default avatarQt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: default avatarAlessandro Portale <alessandro.portale@nokia.com>
parent c98e7c2b
......@@ -28,6 +28,10 @@ symbian:TARGET.CAPABILITY += NetworkServices
# CONFIG += mobility
# MOBILITY +=
# Add dependency to symbian components
# QTQUICKCOMPONENTS #
# CONFIG += qtquickcomponents
# The .cpp file which was generated for your project. Feel free to hack it.
SOURCES += main.cpp
......
import QtQuick 1.0
import com.nokia.symbian 1.0
Page {
id: mainPage
Text {
anchors.centerIn: parent
text: qsTr("Hello world!")
color: platformStyle.colorNormalLight
font.pixelSize: 20
}
}
import QtQuick 1.0
import com.nokia.symbian 1.0
Window {
id: window
StatusBar {
id: statusBar
anchors.top: window.top
}
PageStack {
id: pageStack
anchors { left: parent.left; right: parent.right; top: statusBar.bottom; bottom: toolBar.top }
}
ToolBar {
id: toolBar
anchors.bottom: window.bottom
tools: ToolBarLayout {
id: toolBarLayout
ToolButton {
flat: true
iconSource: "toolbar-back"
onClicked: pageStack.depth <= 1 ? Qt.quit() : pageStack.pop()
}
}
}
Component.onCompleted: {
pageStack.push(Qt.resolvedUrl("MainPage.qml"))
}
}
......@@ -142,7 +142,8 @@ FORMS += makestep.ui \
wizards/mobilelibrarywizardoptionpage.ui \
wizards/mobileappwizardgenericoptionspage.ui \
wizards/mobileappwizardsymbianoptionspage.ui \
wizards/mobileappwizardmaemooptionspage.ui
wizards/mobileappwizardmaemooptionspage.ui \
wizards/qtquickcomponentsetoptionspage.ui
RESOURCES += qt4projectmanager.qrc \
wizards/wizards.qrc
......
......@@ -238,6 +238,9 @@ QByteArray AbstractMobileApp::generateMainCpp(QString *errorMessage) const
case ScreenOrientationAuto:
orientationString = "ScreenOrientationAuto";
break;
case ScreenOrientationImplicit:
default:
continue; // omit line
}
insertParameter(line, mainWindowClassName() + QLatin1String("::")
+ QLatin1String(orientationString));
......
......@@ -89,7 +89,8 @@ public:
enum ScreenOrientation {
ScreenOrientationLockLandscape,
ScreenOrientationLockPortrait,
ScreenOrientationAuto
ScreenOrientationAuto,
ScreenOrientationImplicit // Don't set in application at all (used by Symbian components)
};
enum FileType {
......
......@@ -51,22 +51,39 @@ namespace Qt4ProjectManager {
AbstractMobileAppWizardDialog::AbstractMobileAppWizardDialog(QWidget *parent, const QtSupport::QtVersionNumber &minimumQtVersionNumber)
: ProjectExplorer::BaseProjectWizardDialog(parent)
, m_genericOptionsPageId(-1)
, m_symbianOptionsPageId(-1)
, m_maemoOptionsPageId(-1)
, m_harmattanOptionsPageId(-1)
, m_targetsPageId(-1)
, m_ignoreGeneralOptions(false)
, m_targetItem(0)
, m_genericItem(0)
, m_symbianItem(0)
, m_maemoItem(0)
, m_harmattanItem(0)
{
m_targetsPage = new TargetSetupPage;
m_targetsPage->setPreferMobile(true);
m_targetsPage->setMinimumQtVersion(minimumQtVersionNumber);
resize(900, 450);
m_targetsPageId = addPageWithTitle(m_targetsPage, tr("Qt Versions"));
m_genericOptionsPage = new Internal::MobileAppWizardGenericOptionsPage;
m_symbianOptionsPage = new Internal::MobileAppWizardSymbianOptionsPage;
m_maemoOptionsPage = new Internal::MobileAppWizardMaemoOptionsPage(64);
m_harmattanOptionsPage = new Internal::MobileAppWizardMaemoOptionsPage(80);
}
void AbstractMobileAppWizardDialog::addMobilePages()
{
m_targetsPageId = addPageWithTitle(m_targetsPage, tr("Qt Versions"));
m_genericOptionsPageId = addPageWithTitle(m_genericOptionsPage,
tr("Mobile Options"));
m_symbianOptionsPage = new Internal::MobileAppWizardSymbianOptionsPage;
m_symbianOptionsPageId = addPageWithTitle(m_symbianOptionsPage,
QLatin1String(" ") + tr("Symbian Specific"));
m_maemoOptionsPage = new Internal::MobileAppWizardMaemoOptionsPage(64);
m_maemoOptionsPageId = addPageWithTitle(m_maemoOptionsPage,
QLatin1String(" ") + tr("Maemo5 And Meego Specific"));
m_harmattanOptionsPage = new Internal::MobileAppWizardMaemoOptionsPage(80);
m_harmattanOptionsPageId = addPageWithTitle(m_harmattanOptionsPage,
QLatin1String(" ") + tr("Harmattan Specific"));
......@@ -76,7 +93,6 @@ AbstractMobileAppWizardDialog::AbstractMobileAppWizardDialog(QWidget *parent, co
m_maemoItem = wizardProgress()->item(m_maemoOptionsPageId);
m_harmattanItem = wizardProgress()->item(m_harmattanOptionsPageId);
m_targetItem->setNextShownItem(0);
m_genericItem->setNextShownItem(0);
m_symbianItem->setNextShownItem(0);
}
......@@ -96,8 +112,11 @@ int AbstractMobileAppWizardDialog::addPageWithTitle(QWizardPage *page, const QSt
int AbstractMobileAppWizardDialog::nextId() const
{
if (currentPage() == m_targetsPage) {
if (isSymbianTargetSelected() || isFremantleTargetSelected())
if (isSymbianTargetSelected() && !m_ignoreGeneralOptions || isFremantleTargetSelected())
return m_genericOptionsPageId;
// If Symbian target and Qt Quick components for Symbian, skip the mobile options page.
else if (isSymbianTargetSelected() && m_ignoreGeneralOptions)
return m_symbianOptionsPageId;
else if (isMeegoTargetSelected())
return m_maemoOptionsPageId;
else if (isHarmattanTargetSelected())
......@@ -163,6 +182,16 @@ void AbstractMobileAppWizardDialog::cleanupPage(int id)
BaseProjectWizardDialog::cleanupPage(id);
}
void AbstractMobileAppWizardDialog::setIgnoreGenericOptionsPage(bool ignore)
{
m_ignoreGeneralOptions = ignore;
}
Utils::WizardProgressItem *AbstractMobileAppWizardDialog::targetsPageItem() const
{
return m_targetItem;
}
int AbstractMobileAppWizardDialog::idOfNextGenericPage() const
{
return pageIds().at(pageIds().indexOf(m_harmattanOptionsPageId) + 1);
......@@ -222,7 +251,6 @@ QWizard *AbstractMobileAppWizard::createWizardDialog(QWidget *parent,
Core::GeneratedFiles AbstractMobileAppWizard::generateFiles(const QWizard *wizard,
QString *errorMessage) const
{
prepareGenerateFiles(wizard, errorMessage);
const AbstractMobileAppWizardDialog *wdlg
= qobject_cast<const AbstractMobileAppWizardDialog*>(wizard);
app()->setOrientation(wdlg->m_genericOptionsPage->orientation());
......@@ -231,6 +259,7 @@ Core::GeneratedFiles AbstractMobileAppWizard::generateFiles(const QWizard *wizar
app()->setNetworkEnabled(wdlg->m_symbianOptionsPage->networkEnabled());
app()->setMaemoPngIcon64(wdlg->m_maemoOptionsPage->pngIcon());
app()->setMaemoPngIcon80(wdlg->m_harmattanOptionsPage->pngIcon());
prepareGenerateFiles(wizard, errorMessage);
return app()->generateFiles(errorMessage);
}
......
......@@ -37,6 +37,7 @@
#include <qtsupport/qtversionmanager.h>
#include <coreplugin/basefilewizard.h>
#include <projectexplorer/baseprojectwizarddialog.h>
#include <qt4projectmanager/wizards/abstractmobileapp.h>
namespace Qt4ProjectManager {
......@@ -56,6 +57,7 @@ class QT4PROJECTMANAGER_EXPORT AbstractMobileAppWizardDialog : public ProjectExp
protected:
explicit AbstractMobileAppWizardDialog(QWidget *parent, const QtSupport::QtVersionNumber &minimumQtVersionNumber);
void addMobilePages();
public:
TargetSetupPage *targetsPage() const;
......@@ -64,11 +66,12 @@ protected:
int addPageWithTitle(QWizardPage *page, const QString &title);
virtual void initializePage(int id);
virtual void cleanupPage(int id);
private:
virtual void setIgnoreGenericOptionsPage(bool);
virtual int nextId() const;
Utils::WizardProgressItem *targetsPageItem() const;
private:
int idOfNextGenericPage() const;
Utils::WizardProgressItem *itemOfNextGenericPage() const;
bool isSymbianTargetSelected() const;
......@@ -87,6 +90,7 @@ private:
int m_maemoOptionsPageId;
int m_harmattanOptionsPageId;
int m_targetsPageId;
bool m_ignoreGeneralOptions; // If true, do not show generic mobile options page.
Utils::WizardProgressItem *m_targetItem;
Utils::WizardProgressItem *m_genericItem;
Utils::WizardProgressItem *m_symbianItem;
......
......@@ -66,6 +66,7 @@ Html5AppWizardDialog::Html5AppWizardDialog(QWidget *parent)
m_htmlOptionsPage = new Html5AppWizardOptionsPage;
addPageWithTitle(m_htmlOptionsPage, tr("HTML Options"));
addMobilePages();
}
......
......@@ -64,6 +64,7 @@ public:
{
setWindowTitle(DisplayName);
setIntroDescription(Description);
addMobilePages();
}
};
......
......@@ -100,6 +100,7 @@ QmlCppPlugin::QmlCppPlugin(const QString &name, const QFileInfo &path,
QtQuickApp::QtQuickApp()
: AbstractMobileApp()
, m_mainQmlMode(ModeGenerate)
, m_componentSet(QtQuick10Components)
{
}
......@@ -108,6 +109,16 @@ QtQuickApp::~QtQuickApp()
clearModulesAndPlugins();
}
void QtQuickApp::setComponentSet(ComponentSet componentSet)
{
m_componentSet = componentSet;
}
QtQuickApp::ComponentSet QtQuickApp::componentSet() const
{
return m_componentSet;
}
void QtQuickApp::setMainQml(Mode mode, const QString &file)
{
Q_ASSERT(mode != ModeGenerate || file.isEmpty());
......@@ -169,16 +180,24 @@ QString QtQuickApp::pathExtended(int fileType) const
+ (importQmlFile ? m_mainQmlFile.dir().dirName() : cleanProjectName)
+ QLatin1Char('/');
const QString appViewerTargetSubDir = appViewerOriginsSubDir;
const QString mainQml = QLatin1String("main.qml");
const QString mainQmlFile = QLatin1String("main.qml");
const QString mainPageQmlFile = QLatin1String("MainPage.qml");
const QString qmlOriginDir = originsRoot() + QLatin1String("qml/app/")
+ componentSetDir(componentSet()) + QLatin1Char('/');
const QString pathBase = outputPathBase();
const QDir appProFilePath(pathBase);
switch (fileType) {
case MainQml: return importQmlFile ? m_mainQmlFile.canonicalFilePath()
: pathBase + qmlSubDir + mainQml;
case MainQml:
return importQmlFile ? m_mainQmlFile.canonicalFilePath() : pathBase + qmlSubDir + mainQmlFile;
case MainQmlDeployed: return importQmlFile ? qmlSubDir + m_mainQmlFile.fileName()
: QString(qmlSubDir + mainQml);
case MainQmlOrigin: return originsRoot() + QLatin1String("qml/app/") + mainQml;
: QString(qmlSubDir + mainQmlFile);
case MainQmlOrigin: return qmlOriginDir + mainQmlFile;
case MainPageQml: return pathBase + qmlSubDir + mainPageQmlFile;
case MainPageQmlOrigin: return qmlOriginDir + mainPageQmlFile;
case AppViewerPri: return pathBase + appViewerTargetSubDir + appViewerPriFileName;
case AppViewerPriOrigin: return originsRoot() + appViewerOriginsSubDir + appViewerPriFileName;
case AppViewerCpp: return pathBase + appViewerTargetSubDir + appViewerCppFileName;
......@@ -239,6 +258,11 @@ void QtQuickApp::handleCurrentProFileTemplateLine(const QString &line,
}
proFile << endl;
} else if (line.contains(QLatin1String("# QTQUICKCOMPONENTS"))) {
QString nextLine = proFileTemplate.readLine(); // eats '# CONFIG += qtquickcomponents'
if (componentSet() == Symbian10Components)
nextLine.remove(0, 2); // remove comment
proFile << nextLine << endl;
}
}
......@@ -325,6 +349,8 @@ Core::GeneratedFiles QtQuickApp::generateFiles(QString *errorMessage) const
Core::GeneratedFiles files = AbstractMobileApp::generateFiles(errorMessage);
if (!useExistingMainQml()) {
files.append(file(generateFile(QtQuickAppGeneratedFileInfo::MainQmlFile, errorMessage), path(MainQml)));
if (componentSet() == QtQuickApp::Symbian10Components)
files.append(file(generateFile(QtQuickAppGeneratedFileInfo::MainPageQmlFile, errorMessage), path(MainPageQml)));
files.last().setAttributes(Core::GeneratedFile::OpenEditorAttribute);
}
......@@ -354,6 +380,9 @@ QByteArray QtQuickApp::generateFileExtended(int fileType,
case QtQuickAppGeneratedFileInfo::MainQmlFile:
data = readBlob(path(MainQmlOrigin), errorMessage);
break;
case QtQuickAppGeneratedFileInfo::MainPageQmlFile:
data = readBlob(path(MainPageQmlOrigin), errorMessage);
break;
case QtQuickAppGeneratedFileInfo::AppViewerPriFile:
data = readBlob(path(AppViewerPriOrigin), errorMessage);
data.append(readBlob(path(DeploymentPriOrigin), errorMessage));
......@@ -417,6 +446,17 @@ QList<DeploymentFolder> QtQuickApp::deploymentFolders() const
return result;
}
QString QtQuickApp::componentSetDir(ComponentSet componentSet) const
{
switch (componentSet) {
case Symbian10Components:
return QLatin1String("symbian10");
case QtQuick10Components:
default:
return QLatin1String("qtquick10");
}
}
const int QtQuickApp::StubVersion = 12;
} // namespace Internal
......
......@@ -81,6 +81,7 @@ struct QtQuickAppGeneratedFileInfo : public AbstractGeneratedFileInfo
{
enum ExtendedFileType {
MainQmlFile = ExtendedFile,
MainPageQmlFile,
AppViewerPriFile,
AppViewerCppFile,
AppViewerHFile
......@@ -104,7 +105,9 @@ public:
AppViewerHOrigin,
QmlDir,
QmlDirProFileRelative,
ModulesDir
ModulesDir,
MainPageQml,
MainPageQmlOrigin
};
enum Mode {
......@@ -112,9 +115,17 @@ public:
ModeImport
};
enum ComponentSet {
QtQuick10Components,
Symbian10Components
};
QtQuickApp();
virtual ~QtQuickApp();
void setComponentSet(ComponentSet componentSet);
ComponentSet componentSet() const;
void setMainQml(Mode mode, const QString &file = QString());
Mode mainQmlMode() const;
bool setExternalModules(const QStringList &uris, const QStringList &importPaths);
......@@ -148,12 +159,14 @@ private:
bool addCppPlugins(QmlModule *module);
bool addCppPlugin(const QString &qmldirLine, QmlModule *module);
void clearModulesAndPlugins();
QString componentSetDir(ComponentSet componentSet) const;
QFileInfo m_mainQmlFile;
Mode m_mainQmlMode;
QStringList m_importPaths;
QList<QmlModule *> m_modules;
QList<QmlCppPlugin *> m_cppPlugins;
ComponentSet m_componentSet;
};
} // namespace Internal
......
......@@ -53,22 +53,49 @@ class QtQuickAppWizardDialog : public AbstractMobileAppWizardDialog
public:
explicit QtQuickAppWizardDialog(QWidget *parent = 0);
protected:
bool validateCurrentPage();
private:
class QtQuickAppWizardSourcesPage *m_qmlSourcesPage;
class QtQuickComponentSetOptionsPage *m_componentOptionsPage;
int m_componentOptionsPageId;
Utils::WizardProgressItem *m_componentItem;
friend class QtQuickAppWizard;
};
QtQuickAppWizardDialog::QtQuickAppWizardDialog(QWidget *parent)
: AbstractMobileAppWizardDialog(parent, QtSupport::QtVersionNumber(4, 7, 0))
: AbstractMobileAppWizardDialog(parent, QtSupport::QtVersionNumber(4, 7, 1))
, m_qmlSourcesPage(0)
{
setWindowTitle(tr("New Qt Quick Application"));
setIntroDescription(tr("This wizard generates a Qt Quick application project."));
m_componentOptionsPage = new Internal::QtQuickComponentSetOptionsPage;
m_componentOptionsPageId = addPageWithTitle(m_componentOptionsPage, tr("Component Set"));
m_componentItem = wizardProgress()->item(m_componentOptionsPageId);
AbstractMobileAppWizardDialog::addMobilePages();
m_componentItem->setNextItems(QList<Utils::WizardProgressItem *>()
<< targetsPageItem());
m_qmlSourcesPage = new QtQuickAppWizardSourcesPage;
addPageWithTitle(m_qmlSourcesPage, tr("QML Sources"));
}
bool QtQuickAppWizardDialog::validateCurrentPage()
{
if (currentPage() == m_componentOptionsPage) {
if (m_componentOptionsPage->componentSet() == QtQuickApp::Symbian10Components) {
setIgnoreGenericOptionsPage(true);
targetsPage()->setMinimumQtVersion(QtSupport::QtVersionNumber(4, 7, 3));
}
}
return AbstractMobileAppWizardDialog::validateCurrentPage();
}
class QtQuickAppWizardPrivate
{
......@@ -102,7 +129,9 @@ Core::BaseFileWizardParameters QtQuickAppWizard::parameters()
"You can build the application and deploy it on desktop and "
"mobile target platforms. For example, you can create signed "
"Symbian Installation System (SIS) packages for this type of "
"projects."));
"projects. Moreover, you can select to use a set of premade "
"UI components in your Qt Quick application. "
"To utilize the components, Qt 4.7.3 or newer is required."));
parameters.setCategory(QLatin1String(QtSupport::Constants::QML_WIZARD_CATEGORY));
parameters.setDisplayCategory(QCoreApplication::translate(QtSupport::Constants::QML_WIZARD_TR_SCOPE,
QtSupport::Constants::QML_WIZARD_TR_CATEGORY));
......@@ -112,6 +141,7 @@ Core::BaseFileWizardParameters QtQuickAppWizard::parameters()
AbstractMobileAppWizardDialog *QtQuickAppWizard::createWizardDialogInternal(QWidget *parent) const
{
m_d->wizardDialog = new QtQuickAppWizardDialog(parent);
m_d->wizardDialog->m_componentOptionsPage->setComponentSet(m_d->app->componentSet());
return m_d->wizardDialog;
}
......@@ -131,6 +161,9 @@ void QtQuickAppWizard::prepareGenerateFiles(const QWizard *w,
const QString mainQmlFile = wizard->m_qmlSourcesPage->mainQmlFile();
m_d->app->setMainQml(QtQuickApp::ModeImport, mainQmlFile);
}
m_d->app->setComponentSet(wizard->m_componentOptionsPage->componentSet());
if (m_d->app->componentSet() == QtQuickApp::Symbian10Components)
m_d->app->setOrientation(AbstractMobileApp::ScreenOrientationImplicit);
}
QString QtQuickAppWizard::fileToOpenPostGeneration() const
......
......@@ -31,6 +31,7 @@
**************************************************************************/
#include "qtquickappwizardpages.h"
#include "ui_qtquickcomponentsetoptionspage.h"
#include "ui_qtquickappwizardsourcespage.h"
#include <coreplugin/coreconstants.h>
......@@ -42,12 +43,58 @@
namespace Qt4ProjectManager {
namespace Internal {
class QtQuickComponentSetOptionsPagePrivate
{
Ui::QtQuickComponentSetOptionsPage ui;
friend class QtQuickComponentSetOptionsPage;
};
class QtQuickAppWizardSourcesPagePrivate
{
Ui::QtQuickAppWizardSourcesPage ui;
friend class QtQuickAppWizardSourcesPage;
};
QtQuickComponentSetOptionsPage::QtQuickComponentSetOptionsPage(QWidget *parent)
: QWizardPage(parent)
, m_d(new QtQuickComponentSetOptionsPagePrivate)
{
m_d->ui.setupUi(this);
m_d->ui.buttonGroup->setId(m_d->ui.qtquick10RadioButton, 0);
m_d->ui.buttonGroup->setId(m_d->ui.symbian10RadioButton, 1);
connect(m_d->ui.buttonGroup, SIGNAL(buttonClicked(int)), this, SLOT(radioButtonChecked(int)));
}
QtQuickComponentSetOptionsPage::~QtQuickComponentSetOptionsPage()
{
delete m_d;
}
QtQuickApp::ComponentSet QtQuickComponentSetOptionsPage::componentSet() const
{
switch (m_d->ui.buttonGroup->checkedId()) {
case 1: return QtQuickApp::Symbian10Components;
case 0:
default: return QtQuickApp::QtQuick10Components;
}
}
void QtQuickComponentSetOptionsPage::setComponentSet(QtQuickApp::ComponentSet componentSet)
{
switch (componentSet) {
case QtQuickApp::Symbian10Components: m_d->ui.symbian10RadioButton->click(); break;
case QtQuickApp::QtQuick10Components:
default: m_d->ui.qtquick10RadioButton->click(); break;
}
}
void QtQuickComponentSetOptionsPage::radioButtonChecked(int index)
{
m_d->ui.descriptionStackedWidget->setCurrentIndex(index);
}
QtQuickAppWizardSourcesPage::QtQuickAppWizardSourcesPage(QWidget *parent)
: QWizardPage(parent)
, m_d(new QtQuickAppWizardSourcesPagePrivate)
......
......@@ -39,6 +39,25 @@
namespace Qt4ProjectManager {
namespace Internal {
class QtQuickComponentSetOptionsPage : public QWizardPage
{
Q_OBJECT
Q_DISABLE_COPY(QtQuickComponentSetOptionsPage)
public:
explicit QtQuickComponentSetOptionsPage(QWidget *parent = 0);
virtual ~QtQuickComponentSetOptionsPage();
QtQuickApp::ComponentSet componentSet() const;
void setComponentSet(QtQuickApp::ComponentSet componentSet);
private slots:
void radioButtonChecked(int index);
private:
class QtQuickComponentSetOptionsPagePrivate *m_d;
};
class QtQuickAppWizardSourcesPage : public QWizardPage
{
Q_OBJECT
......
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QtQuickComponentSetOptionsPage</class>
<widget class="QWizardPage" name="QtQuickComponentSetOptionsPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">