From 8d6566b68b6cfa0c6f45cf7022f2d6a70888a978 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Tue, 4 Sep 2012 18:03:47 +0200 Subject: [PATCH] QtQuick 2 Application Wizard This patch adds a new variant of the good old ugly QmlApplicationViewer wizard. The new one is QQuickView based, and thus targets QtQuick2 Change-Id: I049223f644029e75bd15120b003c0ce4907a547a Reviewed-by: Thomas Hartmann Reviewed-by: Alessandro Portale --- share/qtcreator/templates/qtquick2app/app.pro | 24 ++++++ .../qtcreator/templates/qtquick2app/main.cpp | 13 ++++ .../qtquick2app/qml/app/qtquick20/main.qml | 16 ++++ .../qtquick2applicationviewer.cpp | 75 +++++++++++++++++++ .../qtquick2applicationviewer.h | 32 ++++++++ .../qtquick2applicationviewer.pri | 11 +++ .../qt4projectmanager/qt4projectmanager.cpp | 4 +- .../qt4projectmanager/wizards/qtquickapp.cpp | 59 +++++++++------ .../qt4projectmanager/wizards/qtquickapp.h | 8 +- .../wizards/qtquickappwizard.cpp | 22 +++++- .../wizards/qtquickappwizard.h | 5 +- tests/manual/appwizards/main.cpp | 9 +++ 12 files changed, 249 insertions(+), 29 deletions(-) create mode 100644 share/qtcreator/templates/qtquick2app/app.pro create mode 100644 share/qtcreator/templates/qtquick2app/main.cpp create mode 100644 share/qtcreator/templates/qtquick2app/qml/app/qtquick20/main.qml create mode 100644 share/qtcreator/templates/qtquick2app/qtquick2applicationviewer/qtquick2applicationviewer.cpp create mode 100644 share/qtcreator/templates/qtquick2app/qtquick2applicationviewer/qtquick2applicationviewer.h create mode 100644 share/qtcreator/templates/qtquick2app/qtquick2applicationviewer/qtquick2applicationviewer.pri diff --git a/share/qtcreator/templates/qtquick2app/app.pro b/share/qtcreator/templates/qtquick2app/app.pro new file mode 100644 index 00000000000..df37cf767b2 --- /dev/null +++ b/share/qtcreator/templates/qtquick2app/app.pro @@ -0,0 +1,24 @@ +# Add more folders to ship with the application, here +# DEPLOYMENTFOLDERS # +folder_01.source = qml/app +folder_01.target = qml +DEPLOYMENTFOLDERS = folder_01 +# DEPLOYMENTFOLDERS_END # + +# Additional import path used to resolve QML modules in Creator's code model +# QML_IMPORT_PATH # +QML_IMPORT_PATH = + +# If your application uses the Qt Mobility libraries, uncomment the following +# lines and add the respective components to the MOBILITY variable. +# CONFIG += mobility +# MOBILITY += + +# The .cpp file which was generated for your project. Feel free to hack it. +SOURCES += main.cpp + +# Please do not modify the following two lines. Required for deployment. +include(qtquick2applicationviewer/qtquick2applicationviewer.pri) +# REMOVE_NEXT_LINE (wizard will remove the include and append deployment.pri to qmlapplicationviewer.pri, instead) # +include(../shared/deployment.pri) +qtcAddDeployment() diff --git a/share/qtcreator/templates/qtquick2app/main.cpp b/share/qtcreator/templates/qtquick2app/main.cpp new file mode 100644 index 00000000000..fb3846ec627 --- /dev/null +++ b/share/qtcreator/templates/qtquick2app/main.cpp @@ -0,0 +1,13 @@ +#include +#include "qtquick2applicationviewer.h" + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QtQuick2ApplicationViewer viewer; + viewer.setMainQmlFile(QStringLiteral("qml/app/qtquick20/main.qml")); // MAINQML + viewer.showExpanded(); + + return app.exec(); +} diff --git a/share/qtcreator/templates/qtquick2app/qml/app/qtquick20/main.qml b/share/qtcreator/templates/qtquick2app/qml/app/qtquick20/main.qml new file mode 100644 index 00000000000..897812a6cb4 --- /dev/null +++ b/share/qtcreator/templates/qtquick2app/qml/app/qtquick20/main.qml @@ -0,0 +1,16 @@ +import QtQuick 2.0 + +Rectangle { + width: 360 + height: 360 + Text { + text: qsTr("Hello World") + anchors.centerIn: parent + } + MouseArea { + anchors.fill: parent + onClicked: { + Qt.quit(); + } + } +} diff --git a/share/qtcreator/templates/qtquick2app/qtquick2applicationviewer/qtquick2applicationviewer.cpp b/share/qtcreator/templates/qtquick2app/qtquick2applicationviewer/qtquick2applicationviewer.cpp new file mode 100644 index 00000000000..4288f1c26ec --- /dev/null +++ b/share/qtcreator/templates/qtquick2app/qtquick2applicationviewer/qtquick2applicationviewer.cpp @@ -0,0 +1,75 @@ +/* + This file was generated by the Qt Quick 2 Application wizard of Qt Creator. + QtQuick2ApplicationViewer is a convenience class containing mobile device specific + code such as screen orientation handling. Also QML paths and debugging are + handled here. + It is recommended not to modify this file, since newer versions of Qt Creator + may offer an updated version of it. +*/ + +#include "qtquick2applicationviewer.h" + +#include +#include +#include + +class QtQuick2ApplicationViewerPrivate +{ + QString mainQmlFile; + friend class QtQuick2ApplicationViewer; + static QString adjustPath(const QString &path); +}; + +QString QtQuick2ApplicationViewerPrivate::adjustPath(const QString &path) +{ +#ifdef Q_OS_UNIX +#ifdef Q_OS_MAC + if (!QDir::isAbsolutePath(path)) + return QString::fromLatin1("%1/../Resources/%2") + .arg(QCoreApplication::applicationDirPath(), path); +#elif !defined(Q_OS_ANDROID) + const QString pathInInstallDir = + QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path); + if (QFileInfo(pathInInstallDir).exists()) + return pathInInstallDir; +#endif +#endif + return path; +} + +QtQuick2ApplicationViewer::QtQuick2ApplicationViewer(QWindow *parent) + : QQuickView(parent) + , d(new QtQuick2ApplicationViewerPrivate()) +{ + connect(engine(), SIGNAL(quit()), SLOT(close())); + setResizeMode(QQuickView::SizeRootObjectToView); + +#ifdef Q_OS_ANDROID + engine()->setBaseUrl(QUrl::fromLocalFile("/")); +#endif +} + +QtQuick2ApplicationViewer::~QtQuick2ApplicationViewer() +{ + delete d; +} + +void QtQuick2ApplicationViewer::setMainQmlFile(const QString &file) +{ + d->mainQmlFile = QtQuick2ApplicationViewerPrivate::adjustPath(file); + setSource(QUrl::fromLocalFile(d->mainQmlFile)); +} + +void QtQuick2ApplicationViewer::addImportPath(const QString &path) +{ + engine()->addImportPath(QtQuick2ApplicationViewerPrivate::adjustPath(path)); +} + +void QtQuick2ApplicationViewer::showExpanded() +{ +#if defined(Q_WS_SIMULATOR) + showFullScreen(); +#else + show(); +#endif +} diff --git a/share/qtcreator/templates/qtquick2app/qtquick2applicationviewer/qtquick2applicationviewer.h b/share/qtcreator/templates/qtquick2app/qtquick2applicationviewer/qtquick2applicationviewer.h new file mode 100644 index 00000000000..6eee3c89b9b --- /dev/null +++ b/share/qtcreator/templates/qtquick2app/qtquick2applicationviewer/qtquick2applicationviewer.h @@ -0,0 +1,32 @@ +/* + This file was generated by the Qt Quick 2 Application wizard of Qt Creator. + QtQuick2ApplicationViewer is a convenience class containing mobile device specific + code such as screen orientation handling. Also QML paths and debugging are + handled here. + It is recommended not to modify this file, since newer versions of Qt Creator + may offer an updated version of it. +*/ + +#ifndef QTQUICK2APPLICATIONVIEWER_H +#define QTQUICK2APPLICATIONVIEWER_H + +#include + +class QtQuick2ApplicationViewer : public QQuickView +{ + Q_OBJECT + +public: + explicit QtQuick2ApplicationViewer(QWindow *parent = 0); + virtual ~QtQuick2ApplicationViewer(); + + void setMainQmlFile(const QString &file); + void addImportPath(const QString &path); + + void showExpanded(); + +private: + class QtQuick2ApplicationViewerPrivate *d; +}; + +#endif // QTQUICK2APPLICATIONVIEWER_H diff --git a/share/qtcreator/templates/qtquick2app/qtquick2applicationviewer/qtquick2applicationviewer.pri b/share/qtcreator/templates/qtquick2app/qtquick2applicationviewer/qtquick2applicationviewer.pri new file mode 100644 index 00000000000..5123a2567e2 --- /dev/null +++ b/share/qtcreator/templates/qtquick2app/qtquick2applicationviewer/qtquick2applicationviewer.pri @@ -0,0 +1,11 @@ +# This file was generated by the Qt Quick 2 Application wizard of Qt Creator. +# The code below adds the QtQuick2ApplicationViewer to the project and handles +# the activation of QML debugging. +# It is recommended not to modify this file, since newer versions of Qt Creator +# may offer an updated version of it. + +QT += qml quick + +SOURCES += $$PWD/qtquick2applicationviewer.cpp +HEADERS += $$PWD/qtquick2applicationviewer.h +INCLUDEPATH += $$PWD diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.cpp b/src/plugins/qt4projectmanager/qt4projectmanager.cpp index c428be4e497..6604ebe4b20 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager.cpp +++ b/src/plugins/qt4projectmanager/qt4projectmanager.cpp @@ -265,7 +265,9 @@ ProjectExplorer::Project *Qt4Manager::openProject(const QString &fileName, QStri } } - const QtQuickApp qtQuickApp; + QtQuickApp qtQuickApp; + updateBoilerPlateCodeFiles(&qtQuickApp, canonicalFilePath); + qtQuickApp.setComponentSet(QtQuickApp::QtQuick20Components); updateBoilerPlateCodeFiles(&qtQuickApp, canonicalFilePath); const Html5App html5App; updateBoilerPlateCodeFiles(&html5App, canonicalFilePath); diff --git a/src/plugins/qt4projectmanager/wizards/qtquickapp.cpp b/src/plugins/qt4projectmanager/wizards/qtquickapp.cpp index 91849d5ab37..eddb9bbd197 100644 --- a/src/plugins/qt4projectmanager/wizards/qtquickapp.cpp +++ b/src/plugins/qt4projectmanager/wizards/qtquickapp.cpp @@ -45,11 +45,6 @@ namespace Internal { const QString qmldir(QLatin1String("qmldir")); const QString qmldir_plugin(QLatin1String("plugin")); -const QString appViewerBaseName(QLatin1String("qmlapplicationviewer")); -const QString appViewerPriFileName(appViewerBaseName + QLatin1String(".pri")); -const QString appViewerCppFileName(appViewerBaseName + QLatin1String(".cpp")); -const QString appViewerHFileName(appViewerBaseName + QLatin1String(".h")); -const QString appViewerOriginsSubDir(appViewerBaseName + QLatin1Char('/')); QmlModule::QmlModule(const QString &uri, const QFileInfo &rootDir, const QFileInfo &qmldir, bool isExternal, QtQuickApp *qtQuickApp) @@ -177,7 +172,7 @@ QString QtQuickApp::pathExtended(int fileType) const const QString qmlSubDir = QLatin1String("qml/") + (importQmlFile ? m_mainQmlFile.dir().dirName() : projectName()) + QLatin1Char('/'); - const QString appViewerTargetSubDir = appViewerOriginsSubDir; + const QString appViewerTargetSubDir = appViewerOriginSubDir(); const QString mainQmlFile = QLatin1String("main.qml"); const QString mainPageQmlFile = QLatin1String("MainPage.qml"); @@ -196,12 +191,12 @@ QString QtQuickApp::pathExtended(int fileType) const 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; - case AppViewerCppOrigin: return originsRoot() + appViewerOriginsSubDir + appViewerCppFileName; - case AppViewerH: return pathBase + appViewerTargetSubDir + appViewerHFileName; - case AppViewerHOrigin: return originsRoot() + appViewerOriginsSubDir + appViewerHFileName; + case AppViewerPri: return pathBase + appViewerTargetSubDir + fileName(AppViewerPri); + case AppViewerPriOrigin: return originsRoot() + appViewerOriginSubDir() + fileName(AppViewerPri); + case AppViewerCpp: return pathBase + appViewerTargetSubDir + fileName(AppViewerCpp); + case AppViewerCppOrigin: return originsRoot() + appViewerOriginSubDir() + fileName(AppViewerCpp); + case AppViewerH: return pathBase + appViewerTargetSubDir + fileName(AppViewerH); + case AppViewerHOrigin: return originsRoot() + appViewerOriginSubDir() + fileName(AppViewerH); case QmlDir: return pathBase + qmlSubDir; case QmlDirProFileRelative: return importQmlFile ? appProFilePath.relativeFilePath(m_mainQmlFile.canonicalPath()) : QString(qmlSubDir).remove(qmlSubDir.length() - 1, 1); @@ -213,7 +208,8 @@ QString QtQuickApp::pathExtended(int fileType) const QString QtQuickApp::originsRoot() const { - return templatesRoot() + QLatin1String("qtquickapp/"); + const bool isQtQuick2 = m_componentSet == QtQuick20Components; + return templatesRoot() + QLatin1String(isQtQuick2 ? "qtquick2app/" : "qtquickapp/"); } QString QtQuickApp::mainWindowClassName() const @@ -370,6 +366,27 @@ const QList QtQuickApp::modules() const return m_modules; } +QString QtQuickApp::appViewerBaseName() const +{ + return QLatin1String(m_componentSet == QtQuick20Components ? + "qtquick2applicationviewer" : "qmlapplicationviewer"); +} + +QString QtQuickApp::fileName(QtQuickApp::ExtendedFileType type) const +{ + switch (type) { + case AppViewerPri: return appViewerBaseName() + QLatin1String(".pri"); + case AppViewerH: return appViewerBaseName() + QLatin1String(".h"); + case AppViewerCpp: return appViewerBaseName() + QLatin1String(".cpp"); + default: return QString(); + } +} + +QString QtQuickApp::appViewerOriginSubDir() const +{ + return appViewerBaseName() + QLatin1Char('/'); +} + QByteArray QtQuickApp::generateFileExtended(int fileType, bool *versionAndCheckSum, QString *comment, QString *errorMessage) const { @@ -402,7 +419,7 @@ QByteArray QtQuickApp::generateFileExtended(int fileType, int QtQuickApp::stubVersionMinor() const { - return StubVersion; + return m_componentSet == QtQuick20Components ? 1 : 22; } QList QtQuickApp::updateableFiles(const QString &mainProFile) const @@ -412,21 +429,21 @@ QList QtQuickApp::updateableFiles(const QString &main int fileType; QString fileName; } files[] = { - {QtQuickAppGeneratedFileInfo::AppViewerPriFile, appViewerPriFileName}, - {QtQuickAppGeneratedFileInfo::AppViewerHFile, appViewerHFileName}, - {QtQuickAppGeneratedFileInfo::AppViewerCppFile, appViewerCppFileName} + {QtQuickAppGeneratedFileInfo::AppViewerPriFile, fileName(AppViewerPri)}, + {QtQuickAppGeneratedFileInfo::AppViewerHFile, fileName(AppViewerH)}, + {QtQuickAppGeneratedFileInfo::AppViewerCppFile, fileName(AppViewerCpp)} }; const QFileInfo mainProFileInfo(mainProFile); const int size = sizeof(files) / sizeof(files[0]); for (int i = 0; i < size; ++i) { const QString fileName = mainProFileInfo.dir().absolutePath() - + QLatin1Char('/') + appViewerOriginsSubDir + files[i].fileName; + + QLatin1Char('/') + appViewerOriginSubDir() + files[i].fileName; if (!QFile::exists(fileName)) continue; QtQuickAppGeneratedFileInfo file; file.fileType = files[i].fileType; file.fileInfo = QFileInfo(fileName); - file.currentVersion = AbstractMobileApp::makeStubVersion(QtQuickApp::StubVersion); + file.currentVersion = AbstractMobileApp::makeStubVersion(stubVersionMinor()); result.append(file); } if (result.count() != size) @@ -449,13 +466,13 @@ QString QtQuickApp::componentSetDir(ComponentSet componentSet) const switch (componentSet) { case Meego10Components: return QLatin1String("meego10"); + case QtQuick20Components: + return QLatin1String("qtquick20"); case QtQuick10Components: default: return QLatin1String("qtquick10"); } } -const int QtQuickApp::StubVersion = 22; - } // namespace Internal } // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/wizards/qtquickapp.h b/src/plugins/qt4projectmanager/wizards/qtquickapp.h index 6696aafa492..22d60423e40 100644 --- a/src/plugins/qt4projectmanager/wizards/qtquickapp.h +++ b/src/plugins/qt4projectmanager/wizards/qtquickapp.h @@ -115,7 +115,8 @@ public: enum ComponentSet { QtQuick10Components, - Meego10Components + Meego10Components, + QtQuick20Components }; QtQuickApp(); @@ -138,6 +139,11 @@ public: static const int StubVersion; +protected: + virtual QString appViewerBaseName() const; + QString fileName(ExtendedFileType type) const; + QString appViewerOriginSubDir() const; + private: virtual QByteArray generateFileExtended(int fileType, bool *versionAndCheckSum, QString *comment, QString *errorMessage) const; diff --git a/src/plugins/qt4projectmanager/wizards/qtquickappwizard.cpp b/src/plugins/qt4projectmanager/wizards/qtquickappwizard.cpp index f599a17d064..0211a6ec628 100644 --- a/src/plugins/qt4projectmanager/wizards/qtquickappwizard.cpp +++ b/src/plugins/qt4projectmanager/wizards/qtquickappwizard.cpp @@ -72,7 +72,7 @@ QtQuickAppWizardDialog::QtQuickAppWizardDialog(QWidget *parent, QtQuickAppWizard::Kind kind) : AbstractMobileAppWizardDialog(parent, QtSupport::QtVersionNumber(4, 7, 0), - QtSupport::QtVersionNumber(4, INT_MAX, INT_MAX), parameters) + QtSupport::QtVersionNumber(5, INT_MAX, INT_MAX), parameters) { setWindowTitle(tr("New Qt Quick Application")); setIntroDescription(tr("This wizard generates a Qt Quick application project.")); @@ -143,13 +143,23 @@ void QtQuickAppWizard::createInstances(ExtensionSystem::IPlugin *plugin) basicFeatures = Core::Feature(QtSupport::Constants::FEATURE_QT_QUICK_1); parameter = base; - parameter.setDisplayName(tr("Qt Quick Application (Built-in Elements)")); - parameter.setDescription(basicDescription + tr("The built-in elements in the QtQuick namespace allow " + parameter.setDisplayName(tr("Qt Quick 1 Application (Built-in Elements)")); + parameter.setDescription(basicDescription + tr("The built-in elements in the QtQuick 1 namespace allow " "you to write cross-platform applications with " "a custom look and feel.\n\nRequires Qt 4.7.0 or newer.")); parameter.setRequiredFeatures(basicFeatures); list << parameter; + parameter = base; + parameter.setDisplayName(tr("Qt Quick 2 Application (Built-in Elements)")); + parameter.setDescription(tr("Creates a Qt Quick application project that can contain " + "both QML and C++ code and includes a QQuickView.\n\n" + "The built-in elements in the QtQuick 2 namespace allow " + "you to write cross-platform applications with " + "a custom look and feel.\n\nRequires Qt 5.0 or newer.")); + parameter.setRequiredFeatures(Core::Feature(QtSupport::Constants::FEATURE_QT_QUICK_2)); + list << parameter; + parameter = base; parameter.setDisplayName(tr("Qt Quick Application for MeeGo Harmattan")); parameter.setDescription(basicDescription + tr("The Qt Quick Components for MeeGo Harmattan are " @@ -173,7 +183,7 @@ void QtQuickAppWizard::createInstances(ExtensionSystem::IPlugin *plugin) QList wizardList = Core::createMultipleBaseFileWizardInstances(list, plugin); - Q_ASSERT(wizardList.count() == 3); + Q_ASSERT(wizardList.count() == 4); for (int i = 0; i < wizardList.count(); i++) { wizardList.at(i)->setQtQuickKind(Kind(i)); @@ -209,6 +219,10 @@ AbstractMobileAppWizardDialog *QtQuickAppWizard::createWizardDialogInternal(QWid d->app->setComponentSet(QtQuickApp::QtQuick10Components); d->app->setMainQml(QtQuickApp::ModeImport); break; + case QtQuick2_0: + d->app->setComponentSet(QtQuickApp::QtQuick20Components); + d->app->setMainQml(QtQuickApp::ModeGenerate); + break; default: qWarning() << "QtQuickAppWizard illegal subOption:" << qtQuickKind(); break; diff --git a/src/plugins/qt4projectmanager/wizards/qtquickappwizard.h b/src/plugins/qt4projectmanager/wizards/qtquickappwizard.h index ae337b6912e..b82917d45c1 100644 --- a/src/plugins/qt4projectmanager/wizards/qtquickappwizard.h +++ b/src/plugins/qt4projectmanager/wizards/qtquickappwizard.h @@ -43,8 +43,9 @@ public: enum Kind { QtQuick1_1 = 0, - MeegoComponents = 1, - ImportQml = 2 + QtQuick2_0 = 1, + MeegoComponents = 2, + ImportQml = 3 }; QtQuickAppWizard(); diff --git a/tests/manual/appwizards/main.cpp b/tests/manual/appwizards/main.cpp index 532aecdb829..c89d76582e3 100644 --- a/tests/manual/appwizards/main.cpp +++ b/tests/manual/appwizards/main.cpp @@ -50,6 +50,15 @@ int main(int argc, char *argv[]) return 1; } + { + QtQuickApp sAppNew; + sAppNew.setProjectPath(projectPath); + sAppNew.setComponentSet(QtQuickApp::ComponentSetQtQuick2_0); + sAppNew.setProjectName(QLatin1String("new_qtquick2_app")); + if (!sAppNew.generateFiles(&errorMessage)) + return 1; + } + { QtQuickApp sAppImport01; sAppImport01.setProjectPath(projectPath);