diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-11-09 00:21:06 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-11-09 00:21:06 (GMT) |
commit | 3d2504305fa39903ab680d7199cb4bb5427167e8 (patch) | |
tree | 71166564d72a9ccfbfcf6356a994f6e8061834f9 | |
parent | 198d903fa18d9f1d51615974d71de8236e97c2cd (diff) | |
parent | 1dab1be81c2f295736f196a9d56ce4facb59fe64 (diff) | |
download | Qt-3d2504305fa39903ab680d7199cb4bb5427167e8.zip Qt-3d2504305fa39903ab680d7199cb4bb5427167e8.tar.gz Qt-3d2504305fa39903ab680d7199cb4bb5427167e8.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-s60-public into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/qt-s60-public:
Fixed deployment for symbian/linux-armcc when using shadow builds.
Started using qtmain.lib for all Qt applications, also corelib ones.
Make qmake to pass all UTF-8 characters unchanged through parser.
Implement support for DEPLOYMENT.display_name in Symbian
Added .flags modifier support for DEPLOYMENT items in Symbian
Make default application deployment removable
Allow pkg_prerules and pkg_postrules to be targeted to separate files
Added missing def file symbol.
Revert "Use qtmain.lib to provide entry point for all Symbian applications"
Fixed test after the fix to QT-4077.
Fixed event starvation with pointer events on Symbian.
20 files changed, 497 insertions, 216 deletions
diff --git a/config.tests/symbian/audio/audio.pro b/config.tests/symbian/audio/audio.pro index b2a1986..b496341 100644 --- a/config.tests/symbian/audio/audio.pro +++ b/config.tests/symbian/audio/audio.pro @@ -6,4 +6,5 @@ INCLUDEPATH += $${EPOCROOT}epoc32/include/mmf/common INCLUDEPATH += $${EPOCROOT}epoc32/include/platform LIBS += -lmmfdevsound +CONFIG -= qt QT = diff --git a/config.tests/symbian/simple/simple.pro b/config.tests/symbian/simple/simple.pro index fa086c9..9c60d62 100644 --- a/config.tests/symbian/simple/simple.pro +++ b/config.tests/symbian/simple/simple.pro @@ -1,4 +1,5 @@ TEMPLATE = app +CONFIG -= qt QT = SOURCES += main.cpp diff --git a/doc/src/development/qmake-manual.qdoc b/doc/src/development/qmake-manual.qdoc index d65967d..6531d25 100644 --- a/doc/src/development/qmake-manual.qdoc +++ b/doc/src/development/qmake-manual.qdoc @@ -1394,12 +1394,16 @@ On the Symbian platform, generic PKG file content can also be specified with this variable. You can use either \c pkg_prerules or \c pkg_postrules to pass raw data to PKG file. The strings in \c pkg_prerules are added before - package-body and \c pkg_postrules after. The strings defined in - \c pkg_postrules or \c pkg_prerules are not parsed by qmake, so they - should be in a format understood by Symbian package generation tools. + package-body and \c pkg_postrules after. \c pkg_prerules is used for + defining vendor information, dependencies, custom package headers, and the + like, while \c pkg_postrules is used for custom file deployment and + embedded sis directives. + The strings defined in \c pkg_postrules or \c pkg_prerules are not parsed + by qmake, so they should be in a format understood by Symbian package + generation tools. Please consult the Symbian platform documentation for correct syntax. - For example, to deploy DLL and add a new dependency: + For example, to deploy DLL and add a new dependency: \snippet doc/src/snippets/code/doc_src_qmake-manual.qdoc 140 @@ -1415,13 +1419,28 @@ \o localized and unique vendor, for example \BR %{"Vendor-EN", ..., "Vendor-FR"} :"Unique vendor name" - \endlist + \endlist - If you decide to override any of these statements, you need to pay + If you decide to override any of these statements, you need to pay attention that also other statements stay valid. For example if you override languages statement, you must override also package-header statement and all other statements which are language specific. + On the Symbian platform, three separate PKG files are generated: + + \list + \o <app>_template.pkg - For application SIS file. Rules suffix: \c{.main} + \o <app>_installer.pkg - For smart installer SIS file. Rules suffix: \c{.installer} + \o <app>_stub.pkg - For ROM stubs. Rules suffix: \c{.stub} + \endlist + + \c pkg_prerules and \c pkg_postrules given without rules suffix will + intelligently apply to each of these files, but rules can also be + targeted to only one of above files by appending listed rules suffix + to the variable name: + + \snippet doc/src/snippets/code/doc_src_qmake-manual.qdoc 153 + On the Symbian platform, the \c default_deployment item specifies default platform and package dependencies. Those dependencies can be selectively disabled if alternative dependencies need to be defined @@ -1439,6 +1458,46 @@ \snippet doc/src/snippets/code/doc_src_qmake-manual.qdoc 141 + On the Symbian platform, a default deployment is generated for all + application projects. You can modify the autogenerated default + deployment via following \c DEPLOYMENT variable values: + + \list + \o default_bin_deployment - Application executable + \o default_resource_deployment - Application resources, including icon + \o default_reg_deployment - Application registration file + \endlist + + For example: + + \snippet doc/src/snippets/code/doc_src_qmake-manual.qdoc 154 + + This will entirely remove the default application deployment. + + On the Symbian platform, you can specify file specific install options + with \c{.flags} modifier. Please consult the Symbian platform documentation + for supported options. + + For example: + + \snippet doc/src/snippets/code/doc_src_qmake-manual.qdoc 155 + + This will show a message box that gives user an option to cancel the + installation and then automatically runs the application after + installation is complete. + + \note Automatically running the applications after install may require signing + the package with better than self-signed certificate, depending on the phone model. + Additionally, some tools such as Runonphone may not work properly with sis + packages that automatically run the application upon install. + + On the Symbian platform, the default package name and the default name that + appears in application menu is derived from the \c TARGET variable. + Often the default is not optimal for displaying to end user. To set a better + display name for these purposes, use \c{DEPLOYMENT.display_name} variable: + + \snippet doc/src/snippets/code/doc_src_qmake-manual.qdoc 156 + On the Symbian platform, you can use \c{DEPLOYMENT.installer_header} variable to generate smart installer wrapper for your application. If you specify just UID of the installer package as the value, then diff --git a/doc/src/snippets/code/doc_src_qmake-manual.qdoc b/doc/src/snippets/code/doc_src_qmake-manual.qdoc index 8c35c3f..4f74e9c 100644 --- a/doc/src/snippets/code/doc_src_qmake-manual.qdoc +++ b/doc/src/snippets/code/doc_src_qmake-manual.qdoc @@ -1009,3 +1009,23 @@ my_exports = \ "bar.h /epoc32/include/mylib/bar.h" BLD_INF_RULES.prj_exports += my_exports //! [152] + +//! [153] +my_note.pkg_postrules.installer = "\"myinstallnote.txt\" - \"\", FILETEXT, TEXTCONTINUE" +DEPLOYMENT += my_note +//! [153] + +//! [154] +DEPLOYMENT -= default_bin_deployment default_resource_deployment default_reg_deployment +//! [154] + +//! [155] +default_bin_deployment.flags += FILERUN RUNINSTALL +dep_note.sources = install_note.txt +dep_note.flags = FILETEXT TEXTEXIT +DEPLOYMENT += dep_note +//! [155] + +//! [156] +DEPLOYMENT.display_name = My Qt App +//! [156] diff --git a/mkspecs/common/symbian/symbian.conf b/mkspecs/common/symbian/symbian.conf index 6d1f708..69188a8 100644 --- a/mkspecs/common/symbian/symbian.conf +++ b/mkspecs/common/symbian/symbian.conf @@ -127,6 +127,8 @@ QT_ARCH = symbian load(qt_config) QMAKE_LIBS_QT_ENTRY = -lqtmain$${QT_LIBINFIX}.lib +QMAKE_LIBS_NO_QT_ENTRY = -llibcrt0.lib +QMAKE_LIBS_NO_QT_ENTRY_GCCE = -llibcrt0_gcce.lib # These directories must match what configure uses for QT_INSTALL_PLUGINS and QT_INSTALL_IMPORTS QT_PLUGINS_BASE_DIR = /resource/qt$${QT_LIBINFIX}/plugins @@ -203,7 +205,7 @@ pkg_platform_dependencies = \ "[0x20032DE7],0,0,0,{\"S60ProductID\"}" \ " " -DEPLOYMENT += default_deployment +DEPLOYMENT += default_deployment default_bin_deployment default_resource_deployment default_reg_deployment defineReplace(symbianRemoveSpecialCharacters) { # Produce identical string to what SymbianCommonGenerator::removeSpecialCharacters and diff --git a/mkspecs/features/symbian/application_icon.prf b/mkspecs/features/symbian/application_icon.prf index 9a9395a..6e1aa8e 100644 --- a/mkspecs/features/symbian/application_icon.prf +++ b/mkspecs/features/symbian/application_icon.prf @@ -1,21 +1,41 @@ load(data_caging_paths) -# If no_icon keyword exist, the S60 UI app is just made hidden. This because S60 app FW -# requires the registration resource file to exist always -contains( CONFIG, no_icon ) { - symbian:RSS_RULES += "hidden = KAppIsHidden;" - CONFIG -= no_icon -} else { -# There is no point in compiling the MIF icon if no_icon CONFIGS is set - !isEmpty(ICON) { +contains(CONFIG, no_icon) { + # If no_icon keyword exist, the S60 UI app is just made hidden. This because S60 app FW + # requires the registration resource file to exist always + contains(QT, gui):contains(CONFIG, qt) { + symbian:RSS_RULES += "hidden = KAppIsHidden;" + CONFIG -= no_icon + } +} + +!contains(CONFIG, no_icon) { + baseTarget = $$symbianRemoveSpecialCharacters($$basename(TARGET)) + symbian-abld|symbian-sbsv2 { + resourceZDir = $$EPOCROOT$$HW_ZDIR$$APP_RESOURCE_DIR + regZDir = $$EPOCROOT$$HW_ZDIR$$REG_RESOURCE_IMPORT_DIR + } else { + contains(DESTDIR, "/.*") { + resourceZDir = $$DESTDIR + } else:isEmpty(DESTDIR) { + resourceZDir = $$OUT_PWD + } else { + resourceZDir = $$OUT_PWD/$$DESTDIR + } + regZDir = $$resourceZDir + } + default_resource_deployment.sources += $$resourceZDir/$${baseTarget}.rsc + default_resource_deployment.path = $$APP_RESOURCE_DIR + default_reg_deployment.sources += $$regZDir/$${baseTarget}_reg.rsc + default_reg_deployment.path = $$REG_RESOURCE_IMPORT_DIR + + !isEmpty(ICON) { !count(ICON, 1) { ICON = $$first(ICON) warning("Only first icon specified in ICON variable is used: $$ICON") } - baseTarget = $$symbianRemoveSpecialCharacters($$basename(TARGET)) - # Note: symbian-sbsv2 builds can't utilize extra compiler for mifconv, so ICON handling is done in code !symbian-sbsv2 { # Absolute path required for shadow builds. @@ -27,13 +47,10 @@ contains( CONFIG, no_icon ) { ICON_backslashed = $$ICON symbian-abld { + # ${ZDIR} is defined in Makefile mifIconZDir = ${ZDIR}$$APP_RESOURCE_DIR } else { - isEmpty(DESTDIR) { - mifIconZDir = . - } else { - mifIconZDir = $$DESTDIR - } + mifIconZDir = $$resourceZDir } # Extra compiler rules for mifconv @@ -54,5 +71,9 @@ contains( CONFIG, no_icon ) { # Rules to use generated MIF file from symbian resources RSS_RULES.number_of_icons = $$size(ICON_backslashed) RSS_RULES.icon_file = $$APP_RESOURCE_DIR/$${baseTarget}.mif + + default_resource_deployment.sources += $$resourceZDir/$${baseTarget}.mif } } + + diff --git a/mkspecs/features/symbian/default_post.prf b/mkspecs/features/symbian/default_post.prf index 348c366..d9ff03d 100644 --- a/mkspecs/features/symbian/default_post.prf +++ b/mkspecs/features/symbian/default_post.prf @@ -3,9 +3,22 @@ load(default_post) contains(TEMPLATE, ".*app") { contains(CONFIG, stdbinary) { QMAKE_LIBS += - } else { + } else:contains(CONFIG,qt) { QMAKE_LIBS += $$QMAKE_LIBS_QT_ENTRY + } else { + QMAKE_LIBS += $$QMAKE_LIBS_NO_QT_ENTRY + } + + contains(DESTDIR, "/.*") { + default_bin_deployment.sources += $$DESTDIR/$$symbianRemoveSpecialCharacters($$basename(TARGET)).exe + } else:isEmpty(DESTDIR) { + default_bin_deployment.sources += $$OUT_PWD/$$symbianRemoveSpecialCharacters($$basename(TARGET)).exe + } else { + default_bin_deployment.sources += $$OUT_PWD/$$DESTDIR/$$symbianRemoveSpecialCharacters($$basename(TARGET)).exe } + default_bin_deployment.path += /sys/bin + + load(application_icon.prf) } contains(TEMPLATE, lib): { contains(CONFIG, staticlib)|contains(CONFIG, static): { @@ -23,10 +36,6 @@ contains(TEMPLATE, lib): { MMP_RULES -= EXPORTUNFROZEN } -contains(TEMPLATE, ".*app"):contains(QT, gui):contains(CONFIG,qt) { - load(application_icon.prf) -} - isEmpty(TARGET.UID3):TARGET.UID3 = $$generate_uid("$${OUT_PWD}/$${TARGET}") isEmpty(TARGET.UID2) { contains(CONFIG, stdbinary) { diff --git a/mkspecs/features/symbian/symbian_building.prf b/mkspecs/features/symbian/symbian_building.prf index 20bc3a3..0cedaa0 100644 --- a/mkspecs/features/symbian/symbian_building.prf +++ b/mkspecs/features/symbian/symbian_building.prf @@ -187,16 +187,29 @@ contains(TEMPLATE, app):!contains(QMAKE_LINK, "^@:.*") { linux-armcc: { QMAKE_LIBS += usrt2_2.lib dfpaeabi.dso dfprvct2_2.dso drtaeabi.dso scppnwdl.dso drtrvct2_2.dso h_t__uf.l\\(switch8.o\\) QMAKE_LIBS += -leexe.lib\\(uc_exe_.o\\) - QMAKE_LIBS -= $$QMAKE_LIBS_QT_ENTRY - QMAKE_LIBS += $$QMAKE_LIBS_QT_ENTRY + contains(CONFIG, "qt") { + QMAKE_LIBS -= $$QMAKE_LIBS_QT_ENTRY + QMAKE_LIBS += $$QMAKE_LIBS_QT_ENTRY + } else { + QMAKE_LIBS -= $$QMAKE_LIBS_NO_QT_ENTRY + QMAKE_LIBS += $$QMAKE_LIBS_NO_QT_ENTRY + } } else :linux-gcce { # notice that we can't merge these as ordering of arguments is important. QMAKE_LIBS += \ -l:eexe.lib \ -l:usrt2_2.lib - modified_entry = $$replace(QMAKE_LIBS_QT_ENTRY, "^-l", "-l:") - QMAKE_LIBS -= $$modified_entry - QMAKE_LIBS += $$modified_entry + contains(CONFIG, "qt") { + modified_entry = $$replace(QMAKE_LIBS_QT_ENTRY, "^-l", "-l:") + QMAKE_LIBS -= $$modified_entry + QMAKE_LIBS += $$modified_entry + } else { + modified_entry = $$replace(QMAKE_LIBS_NO_QT_ENTRY, "^-l", "-l:") + QMAKE_LIBS -= $$modified_entry + modified_entry = $$replace(QMAKE_LIBS_NO_QT_ENTRY_GCCE, "^-l", "-l:") + QMAKE_LIBS -= $$modified_entry + QMAKE_LIBS += $$modified_entry + } QMAKE_LIBS += \ -l:dfpaeabi.dso \ -l:drtaeabi.dso \ diff --git a/qmake/generators/symbian/initprojectdeploy_symbian.cpp b/qmake/generators/symbian/initprojectdeploy_symbian.cpp index 5963773..22a4a82 100644 --- a/qmake/generators/symbian/initprojectdeploy_symbian.cpp +++ b/qmake/generators/symbian/initprojectdeploy_symbian.cpp @@ -253,6 +253,8 @@ void initProjectDeploySymbian(QMakeProject* project, continue; } + QStringList flags = project->values(item + ".flags"); + foreach(QString source, project->values(item + ".sources")) { source = Option::fixPathToLocalOS(source); QString nameFilter; @@ -284,13 +286,15 @@ void initProjectDeploySymbian(QMakeProject* project, Option::fixPathToLocalOS(targetPath.absolutePath() + "/" + info.fileName(), false, true), fixPathToEpocOS(devicePath.left(2) + QLatin1String(SYSBIN_DIR "/") - + info.fileName()))); + + info.fileName()), + flags)); } else { deploymentList.append(CopyItem( Option::fixPathToLocalOS(targetPath.absolutePath() + "/" + info.fileName(), false, true), fixPathToEpocOS(deploymentDrive + QLatin1String("/" SYSBIN_DIR "/") - + info.fileName()))); + + info.fileName()), + flags)); } } if (isPlugin(info, devicePath)) { @@ -301,7 +305,8 @@ void initProjectDeploySymbian(QMakeProject* project, // Generate deployment even if file doesn't exist, as this may be the case // when generating .pkg files. deploymentList.append(CopyItem(Option::fixPathToLocalOS(info.absoluteFilePath()), - fixPathToEpocOS(devicePath + "/" + info.fileName()))); + fixPathToEpocOS(devicePath + "/" + info.fileName()), + flags)); continue; } } @@ -328,12 +333,14 @@ void initProjectDeploySymbian(QMakeProject* project, deploymentList.append(CopyItem( Option::fixPathToLocalOS(absoluteItemPath + "/" + iterator.fileName()), fixPathToEpocOS(devicePath.left(2) + QLatin1String(SYSBIN_DIR "/") - + iterator.fileName()))); + + iterator.fileName()), + flags)); } else { deploymentList.append(CopyItem( Option::fixPathToLocalOS(absoluteItemPath + "/" + iterator.fileName()), fixPathToEpocOS(deploymentDrive + QLatin1String("/" SYSBIN_DIR "/") - + iterator.fileName()))); + + iterator.fileName()), + flags)); } } createPluginStub(info, devicePath + "/" + absoluteItemPath.right(diffSize), @@ -343,7 +350,8 @@ void initProjectDeploySymbian(QMakeProject* project, deploymentList.append(CopyItem( Option::fixPathToLocalOS(absoluteItemPath + "/" + iterator.fileName()), fixPathToEpocOS(devicePath + "/" + absoluteItemPath.right(diffSize) - + "/" + iterator.fileName()))); + + "/" + iterator.fileName()), + flags)); } } } diff --git a/qmake/generators/symbian/initprojectdeploy_symbian.h b/qmake/generators/symbian/initprojectdeploy_symbian.h index 2653d2a..bc17b04 100644 --- a/qmake/generators/symbian/initprojectdeploy_symbian.h +++ b/qmake/generators/symbian/initprojectdeploy_symbian.h @@ -56,9 +56,13 @@ struct CopyItem { - CopyItem(const QString& f, const QString& t) : from(f) , to(t) { } + CopyItem(const QString& f, const QString& t) + : from(f) , to(t) { } + CopyItem(const QString& f, const QString& t, const QStringList& l) + : from(f) , to(t), flags(l) { } QString from; QString to; + QStringList flags; }; typedef QList<CopyItem> DeploymentList; diff --git a/qmake/generators/symbian/symbiancommon.cpp b/qmake/generators/symbian/symbiancommon.cpp index 6fea8fd..0938b58 100644 --- a/qmake/generators/symbian/symbiancommon.cpp +++ b/qmake/generators/symbian/symbiancommon.cpp @@ -204,44 +204,71 @@ void SymbianCommonGenerator::generatePkgFile(const QString &iconFile, bool epocB tw << headerComment.arg(wrapperPkgFilename).arg(dateStr); ts << headerComment.arg(stubPkgFileName).arg(dateStr); - // Construct QStringList from pkg_prerules since we need search it before printed to file - // Note: Though there can't be more than one language or header line, use stringlists + QStringList commonRawPreRules; + QStringList mainRawPreRules; + QStringList instRawPreRules; + QStringList stubRawPreRules; + + // Though there can't be more than one language or header line, use stringlists // in case user wants comments to go with the rules. - QStringList rawPkgPreRules; + // Note that it makes no sense to have file specific language or header rules, + // except what is provided for installer header via "DEPLOYMENT.installer_header" variable, + // because stub and main headers should always match. Vendor rules are similarly limited to + // make code cleaner as it is unlikely anyone will want different vendor in different files. QStringList languageRules; QStringList headerRules; - foreach(QString deploymentItem, project->values("DEPLOYMENT")) { - foreach(QString pkgrulesItem, project->values(deploymentItem + ".pkg_prerules")) { - QStringList pkgrulesValue = project->values(pkgrulesItem); - // If there is no stringlist defined for a rule, use rule name directly - // This is convenience for defining single line mmp statements - if (pkgrulesValue.isEmpty()) { - if (pkgrulesItem.startsWith("&")) - languageRules << pkgrulesItem; - else if (pkgrulesItem.startsWith("#")) - headerRules << pkgrulesItem; - else - rawPkgPreRules << pkgrulesItem; - } else { - if (containsStartWithItem('&', pkgrulesValue)) { - foreach(QString pkgrule, pkgrulesValue) { - languageRules << pkgrule; - } - } else if (containsStartWithItem('#', pkgrulesValue)) { - foreach(QString pkgrule, pkgrulesValue) { - headerRules << pkgrule; - } - } else { - foreach(QString pkgrule, pkgrulesValue) { - rawPkgPreRules << pkgrule; - } - } - } + QStringList vendorRules; + + QStringList commonRawPostRules; + QStringList mainRawPostRules; + QStringList instRawPostRules; + QStringList stubRawPostRules; + + QStringList failList; // Used for detecting incorrect usage + + QString emptySuffix; + QString mainSuffix(".main"); + QString instSuffix(".installer"); + QString stubSuffix(".stub"); + + foreach(QString item, project->values("DEPLOYMENT")) { + parsePreRules(item, emptySuffix, &commonRawPreRules, &languageRules, &headerRules, &vendorRules); + parsePreRules(item, mainSuffix, &mainRawPreRules, &failList, &failList, &failList); + parsePreRules(item, instSuffix, &instRawPreRules, &failList, &failList, &failList); + parsePreRules(item, stubSuffix, &stubRawPreRules, &failList, &failList, &failList); + + parsePostRules(item, emptySuffix, &commonRawPostRules); + parsePostRules(item, mainSuffix, &mainRawPostRules); + parsePostRules(item, instSuffix, &instRawPostRules); + parsePostRules(item, stubSuffix, &stubRawPostRules); + } + + if (!failList.isEmpty()) { + fprintf(stderr, "Warning: Custom language, header, or vendor definitions are not " + "supported by file specific pkg_prerules.* variables.\n" + "Use plain pkg_prerules and/or DEPLOYMENT.installer_header for customizing " + "these items.\n"); + } + + foreach(QString item, commonRawPreRules) { + if (item.startsWith("(")) { + // Only regular pkg file should have package dependencies + mainRawPreRules << item; + } else if (item.startsWith("[")) { + // stub pkg file should not have platform dependencies + mainRawPreRules << item; + instRawPreRules << item; + } else { + mainRawPreRules << item; + instRawPreRules << item; + stubRawPreRules << item; } } - // Apply some defaults if specific data does not exist in PKG pre-rules + // Currently common postrules only go to main + mainRawPostRules << commonRawPostRules; + // Apply some defaults if specific data does not exist in PKG pre-rules if (languageRules.isEmpty()) { // language, (*** hardcoded to english atm, should be parsed from TRANSLATIONS) languageRules << "; Language\n&EN\n\n"; @@ -293,7 +320,9 @@ void SymbianCommonGenerator::generatePkgFile(const QString &iconFile, bool epocB // Package header QString sisHeader = "; SIS header: name, uid, version\n#{\"%1\"},(%2),%3\n\n"; - QString visualTarget = generator->escapeFilePath(project->first("TARGET")); + QString visualTarget = project->values("DEPLOYMENT.display_name").join(" "); + if (visualTarget.isEmpty()) + visualTarget = generator->escapeFilePath(project->first("TARGET")); visualTarget = removePathSeparators(visualTarget); QString wrapperTarget = visualTarget + " installer"; @@ -313,49 +342,38 @@ void SymbianCommonGenerator::generatePkgFile(const QString &iconFile, bool epocB ts << headerRules.join("\n") << endl; } - // Localized vendor name - QString vendorName; - if (!containsStartWithItem('%', rawPkgPreRules)) { - vendorName += "; Localised Vendor name\n%{\"Vendor\"}\n\n"; + // Vendor name + if (!containsStartWithItem('%', vendorRules)) { + vendorRules << "; Default localized vendor name\n%{\"Vendor\"}\n\n"; } - - // Unique vendor name - if (!containsStartWithItem(':', rawPkgPreRules)) { - vendorName += "; Unique Vendor name\n:\"Vendor\"\n\n"; + if (!containsStartWithItem(':', vendorRules)) { + vendorRules << "; Default unique vendor name\n:\"Vendor\"\n\n"; } - t << vendorName; - tw << vendorName; - ts << vendorName; + t << vendorRules.join("\n") << endl; + tw << vendorRules.join("\n") << endl; + ts << vendorRules.join("\n") << endl; // PKG pre-rules - these are added before actual file installations i.e. SIS package body - if (rawPkgPreRules.size()) { - QString comment = "\n; Manual PKG pre-rules from PRO files\n"; + QString comment = "\n; Manual PKG pre-rules from PRO files\n"; + + if (mainRawPreRules.size()) { t << comment; + t << mainRawPreRules.join("\n") << endl; + } + if (instRawPreRules.size()) { tw << comment; + tw << instRawPreRules.join("\n") << endl; + } + if (stubRawPreRules.size()) { ts << comment; - - foreach(QString item, rawPkgPreRules) { - // Only regular pkg file should have package dependencies - if (item.startsWith("(")) { - t << item << endl; - } - // stub pkg file should not have platform dependencies - else if (item.startsWith("[")) { - t << item << endl; - tw << item << endl; - } - else { - t << item << endl; - ts << item << endl; - tw << item << endl; - } - } - t << endl; - ts << endl; - tw << endl; + ts << stubRawPreRules.join("\n") << endl; } + t << endl; + tw << endl; + ts << endl; + // Begin Manufacturer block if (!project->values("DEPLOYMENT.manufacturers").isEmpty()) { QString manufacturerStr("IF "); @@ -367,87 +385,7 @@ void SymbianCommonGenerator::generatePkgFile(const QString &iconFile, bool epocB t << manufacturerStr << endl; } - // Install paths on the phone *** should be dynamic at some point - QString installPathBin = "!:\\sys\\bin"; - QString installPathResource = "!:\\resource\\apps"; - QString installPathRegResource = "!:\\private\\10003a3f\\import\\apps"; - - // Find location of builds - QString destDirBin; - QString destDirResource; - QString destDirRegResource; - if (epocBuild) { - destDirBin = QString("%1epoc32/release/$(PLATFORM)/$(TARGET)").arg(epocRoot()); - destDirResource = QString("%1epoc32/data/z/resource/apps").arg(epocRoot()); - destDirRegResource = QString("%1epoc32/data/z/private/10003a3f/import/apps").arg(epocRoot()); - } else { - destDirBin = project->first("DESTDIR"); - if (destDirBin.isEmpty()) - destDirBin = "."; - else if (destDirBin.endsWith('/') || destDirBin.endsWith('\\')) - destDirBin.chop(1); - destDirResource = destDirBin; - destDirRegResource = destDirBin; - } - - if (targetType == TypeExe) { - // deploy .exe file - t << "; Executable and default resource files" << endl; - QString exeFile = fixedTarget + ".exe"; - t << QString("\"%1/%2\" - \"%3\\%4\"") - .arg(destDirBin) - .arg(exeFile) - .arg(installPathBin) - .arg(exeFile) << endl; - ts << QString("\"\" - \"%1\\%2\"") - .arg(romPath(installPathBin)) - .arg(exeFile) << endl; - - // deploy rsc & reg_rsc file - if (!project->isActiveConfig("no_icon")) { - t << QString("\"%1/%2\" - \"%3\\%4\"") - .arg(destDirResource) - .arg(fixedTarget + ".rsc") - .arg(installPathResource) - .arg(fixedTarget + ".rsc") << endl; - ts << QString("\"\" - \"%1\\%2\"") - .arg(romPath(installPathResource)) - .arg(fixedTarget + ".rsc") << endl; - - t << QString("\"%1/%2\" - \"%3\\%4\"") - .arg(destDirRegResource) - .arg(fixedTarget + "_reg.rsc") - .arg(installPathRegResource) - .arg(fixedTarget + "_reg.rsc") << endl; - ts << QString("\"\" - \"%1\\%2\"") - .arg(romPath(installPathRegResource)) - .arg(fixedTarget + "_reg.rsc") << endl; - - if (!iconFile.isEmpty()) { - if (epocBuild) { - t << QString("\"%1epoc32/data/z%2\" - \"!:%3\"") - .arg(epocRoot()) - .arg(iconFile) - .arg(QString(iconFile).replace('/', '\\')) << endl << endl; - ts << QString("\"\" - \"%1\"") - .arg(romPath(QString(iconFile).replace('/', '\\'))) << endl << endl; - } else { - QDir mifIconDir(project->first("DESTDIR")); - QFileInfo mifIcon(mifIconDir.relativeFilePath(project->first("TARGET"))); - QString mifIconFileName = mifIcon.fileName(); - mifIconFileName.append(".mif"); - t << QString("\"%1/%2\" - \"!:%3\"") - .arg(mifIcon.path()) - .arg(mifIconFileName) - .arg(QString(iconFile).replace('/', '\\')) << endl << endl; - ts << QString("\"\" - \"%1\"") - .arg(romPath(QString(iconFile).replace('/', '\\'))) << endl << endl; - } - } - } - } - - // deploy any additional DEPLOYMENT files + // deploy files specified by DEPLOYMENT variable QString remoteTestPath; QString zDir; remoteTestPath = QString("!:\\private\\%1").arg(privateDirUid); @@ -461,6 +399,15 @@ void SymbianCommonGenerator::generatePkgFile(const QString &iconFile, bool epocB for (int i = 0; i < depList.size(); ++i) { QString from = depList.at(i).from; QString to = depList.at(i).to; + QString flags; + bool showOnlyFile = false; + foreach(QString flag, depList.at(i).flags) { + if (flag == QLatin1String("FT") + || flag == QLatin1String("FILETEXT")) { + showOnlyFile = true; + } + flags.append(QLatin1Char(',')).append(flag); + } if (epocBuild) { // Deploy anything not already deployed from under epoc32 instead from under @@ -474,28 +421,33 @@ void SymbianCommonGenerator::generatePkgFile(const QString &iconFile, bool epocB } } - t << QString("\"%1\" - \"%2\"").arg(from.replace('\\','/')).arg(to) << endl; - ts << QString("\"\" - \"%1\"").arg(romPath(to)) << endl; + // Files with "FILETEXT"/"FT" flag are meant for showing only at installation time + // and therefore do not belong to the stub package and will not install the file into phone. + if (showOnlyFile) + to.clear(); + else + ts << QString("\"\" - \"%1\"").arg(romPath(to)) << endl; + + t << QString("\"%1\" - \"%2\"%3").arg(from.replace('\\','/')).arg(to).arg(flags) << endl; + } t << endl; ts << endl; // PKG post-rules - these are added after actual file installations i.e. SIS package body - t << "; Manual PKG post-rules from PRO files" << endl; - foreach(QString deploymentItem, project->values("DEPLOYMENT")) { - foreach(QString pkgrulesItem, project->values(deploymentItem + ".pkg_postrules")) { - QStringList pkgrulesValue = project->values(pkgrulesItem); - // If there is no stringlist defined for a rule, use rule name directly - // This is convenience for defining single line statements - if (pkgrulesValue.isEmpty()) { - t << pkgrulesItem << endl; - } else { - foreach(QString pkgrule, pkgrulesValue) { - t << pkgrule << endl; - } - } - t << endl; - } + comment = "; Manual PKG post-rules from PRO files\n"; + + if (mainRawPostRules.size()) { + t << comment; + t << mainRawPostRules.join("\n") << endl; + } + if (instRawPostRules.size()) { + tw << comment; + tw << instRawPostRules.join("\n") << endl; + } + if (stubRawPostRules.size()) { + ts << comment; + ts << stubRawPostRules.join("\n") << endl; } // Close Manufacturer block @@ -691,6 +643,11 @@ void SymbianCommonGenerator::writeLocFile(QStringList &symbianLangCodes) if (ft.open(QIODevice::WriteOnly)) { generatedFiles << ft.fileName(); QTextStream t(&ft); + + QString displayName = generator->project->values("DEPLOYMENT.display_name").join(" "); + if (displayName.isEmpty()) + displayName = generator->escapeFilePath(generator->project->first("TARGET")); + t << "// ============================================================================" << endl; t << "// * Generated by qmake (" << qmake_version() << ") (Qt " QT_VERSION_STR ") on: "; t << QDateTime::currentDateTime().toString(Qt::ISODate) << endl; @@ -699,16 +656,16 @@ void SymbianCommonGenerator::writeLocFile(QStringList &symbianLangCodes) t << "// ============================================================================" << endl; t << endl; t << "#ifdef LANGUAGE_SC" << endl; - t << "#define STRING_r_short_caption \"" << fixedTarget << "\"" << endl; - t << "#define STRING_r_caption \"" << fixedTarget << "\"" << endl; + t << "#define STRING_r_short_caption \"" << displayName << "\"" << endl; + t << "#define STRING_r_caption \"" << displayName << "\"" << endl; foreach(QString lang, symbianLangCodes) { t << "#elif defined LANGUAGE_" << lang << endl; - t << "#define STRING_r_short_caption \"" << fixedTarget << "\"" << endl; - t << "#define STRING_r_caption \"" << fixedTarget << "\"" << endl; + t << "#define STRING_r_short_caption \"" << displayName << "\"" << endl; + t << "#define STRING_r_caption \"" << displayName << "\"" << endl; } t << "#else" << endl; - t << "#define STRING_r_short_caption \"" << fixedTarget << "\"" << endl; - t << "#define STRING_r_caption \"" << fixedTarget << "\"" << endl; + t << "#define STRING_r_short_caption \"" << displayName << "\"" << endl; + t << "#define STRING_r_caption \"" << displayName << "\"" << endl; t << "#endif" << endl; } else { PRINT_FILE_CREATE_ERROR(filename); @@ -1037,3 +994,66 @@ void SymbianCommonGenerator::fillQt2S60LangMapTable() qt2S60LangMapTable.insert("ny", "SC"); //Chewa // } +void SymbianCommonGenerator::parsePreRules(const QString &deploymentVariable, + const QString &variableSuffix, + QStringList *rawRuleList, + QStringList *languageRuleList, + QStringList *headerRuleList, + QStringList *vendorRuleList) +{ + QMakeProject *project = generator->project; + foreach(QString pkgrulesItem, project->values(deploymentVariable + ".pkg_prerules" + variableSuffix)) { + QStringList pkgrulesValue = project->values(pkgrulesItem); + // If there is no stringlist defined for a rule, use rule name directly + // This is convenience for defining single line statements + if (pkgrulesValue.isEmpty()) { + if (pkgrulesItem.startsWith("&")) + *languageRuleList << pkgrulesItem; + else if (pkgrulesItem.startsWith("#")) + *headerRuleList << pkgrulesItem; + else if (pkgrulesItem.startsWith("%") || pkgrulesItem.startsWith(":")) + *vendorRuleList << pkgrulesItem; + else + *rawRuleList << pkgrulesItem; + } else { + if (containsStartWithItem('&', pkgrulesValue)) { + foreach(QString pkgrule, pkgrulesValue) { + *languageRuleList << pkgrule; + } + } else if (containsStartWithItem('#', pkgrulesValue)) { + foreach(QString pkgrule, pkgrulesValue) { + *headerRuleList << pkgrule; + } + } else if (containsStartWithItem('%', pkgrulesValue) + || containsStartWithItem(':', pkgrulesValue)) { + foreach(QString pkgrule, pkgrulesValue) { + *vendorRuleList << pkgrule; + } + } else { + foreach(QString pkgrule, pkgrulesValue) { + *rawRuleList << pkgrule; + } + } + } + } +} + +void SymbianCommonGenerator::parsePostRules(const QString &deploymentVariable, + const QString &variableSuffix, + QStringList *rawRuleList) +{ + QMakeProject *project = generator->project; + foreach(QString pkgrulesItem, project->values(deploymentVariable + ".pkg_postrules" + variableSuffix)) { + QStringList pkgrulesValue = project->values(pkgrulesItem); + // If there is no stringlist defined for a rule, use rule name directly + // This is convenience for defining single line statements + if (pkgrulesValue.isEmpty()) { + *rawRuleList << pkgrulesItem; + } else { + foreach(QString pkgrule, pkgrulesValue) { + *rawRuleList << pkgrule; + } + } + } +} + diff --git a/qmake/generators/symbian/symbiancommon.h b/qmake/generators/symbian/symbiancommon.h index dae1e4a..80f2079 100644 --- a/qmake/generators/symbian/symbiancommon.h +++ b/qmake/generators/symbian/symbiancommon.h @@ -86,6 +86,17 @@ protected: QStringList symbianLangCodesFromTsFiles(); void fillQt2S60LangMapTable(); + void parsePreRules(const QString &deploymentVariable, + const QString &variableSuffix, + QStringList *rawRuleList, + QStringList *languageRuleList, + QStringList *headerRuleList, + QStringList *vendorRuleList); + void parsePostRules(const QString &deploymentVariable, + const QString &variableSuffix, + QStringList *rawRuleList); + + protected: MakefileGenerator *generator; diff --git a/qmake/project.cpp b/qmake/project.cpp index 427bea3..fe08b7b 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -677,7 +677,23 @@ QMakeProject::reset() bool QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place, int numLines) { - QString s = t.simplified(); + // To preserve the integrity of any UTF-8 characters in .pro file, temporarily replace the + // non-breaking space (0xA0) characters with another non-space character, so that + // QString::simplified() call will not replace it with space. + // Note: There won't be any two byte characters in .pro files, so 0x10A0 should be a safe + // replacement character. + static QChar nbsp(0xA0); + static QChar nbspFix(0x01A0); + QString s; + if (t.indexOf(nbsp) != -1) { + s = t; + s.replace(nbsp, nbspFix); + s = s.simplified(); + s.replace(nbspFix, nbsp); + } else { + s = t.simplified(); + } + int hash_mark = s.indexOf("#"); if(hash_mark != -1) //good bye comments s = s.left(hash_mark); diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index d8cc344..bb9bd01 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -975,9 +975,7 @@ bool QEventDispatcherSymbian::sendPostedEvents() inline void QEventDispatcherSymbian::addDeferredActiveObject(QActiveObject *object) { - if (m_deferredActiveObjects.isEmpty()) { - m_completeDeferredAOs->complete(); - } + queueDeferredActiveObjectsCompletion(); m_deferredActiveObjects.append(object); } @@ -986,6 +984,11 @@ inline void QEventDispatcherSymbian::removeDeferredActiveObject(QActiveObject *o m_deferredActiveObjects.removeAll(object); } +void QEventDispatcherSymbian::queueDeferredActiveObjectsCompletion() +{ + m_completeDeferredAOs->complete(); +} + void QEventDispatcherSymbian::reactivateDeferredActiveObjects() { while (!m_deferredActiveObjects.isEmpty()) { diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h index 1486db5..3615996 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian_p.h +++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h @@ -247,7 +247,9 @@ public: void addDeferredActiveObject(QActiveObject *object); void removeDeferredActiveObject(QActiveObject *object); - void reactivateDeferredActiveObjects(); + void queueDeferredActiveObjectsCompletion(); + // Can be overridden to activate local active objects too, but do call baseclass! + virtual void reactivateDeferredActiveObjects(); inline int iterationCount() const { return m_iterationCount; } diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index ae7070e..8596563 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1425,7 +1425,7 @@ void qt_init(QApplicationPrivate * /* priv */, int) TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(commandLine); // After this construction, CEikonEnv will be available from CEikonEnv::Static(). // (much like our qApp). - CEikonEnv* coe = new CEikonEnv; + QtEikonEnv* coe = new QtEikonEnv; //not using QT_TRAP_THROWING, because coe owns the cleanupstack so it can't be pushed there. if(err == KErrNone) TRAP(err, coe->ConstructAppFromCommandLineL(factory,*commandLine)); diff --git a/src/gui/kernel/qeventdispatcher_s60.cpp b/src/gui/kernel/qeventdispatcher_s60.cpp index bc787b8..77ebd0d 100644 --- a/src/gui/kernel/qeventdispatcher_s60.cpp +++ b/src/gui/kernel/qeventdispatcher_s60.cpp @@ -45,6 +45,62 @@ QT_BEGIN_NAMESPACE +QtEikonEnv::QtEikonEnv() + : m_lastIterationCount(0) + , m_savedStatusCode(KRequestPending) + , m_hasAlreadyRun(false) +{ +} + +QtEikonEnv::~QtEikonEnv() +{ +} + +void QtEikonEnv::RunL() +{ + QEventDispatcherS60 *dispatcher = qobject_cast<QEventDispatcherS60 *>(QAbstractEventDispatcher::instance()); + if (!dispatcher) { + CEikonEnv::RunL(); + return; + } + + if (m_lastIterationCount != dispatcher->iterationCount()) { + m_hasAlreadyRun = false; + m_lastIterationCount = dispatcher->iterationCount(); + } + + if (m_hasAlreadyRun) { + // Fool the active scheduler into believing we are still waiting for events. + // The window server thinks we are not, however. + m_savedStatusCode = iStatus.Int(); + iStatus = KRequestPending; + SetActive(); + dispatcher->queueDeferredActiveObjectsCompletion(); + } else { + m_hasAlreadyRun = true; + CEikonEnv::RunL(); + } +} + +void QtEikonEnv::DoCancel() +{ + complete(); + + CEikonEnv::DoCancel(); +} + +void QtEikonEnv::complete() +{ + if (m_hasAlreadyRun) { + if (m_savedStatusCode != KRequestPending) { + TRequestStatus *status = &iStatus; + QEventDispatcherSymbian::RequestComplete(status, m_savedStatusCode); + m_savedStatusCode = KRequestPending; + } + m_hasAlreadyRun = false; + } +} + QEventDispatcherS60::QEventDispatcherS60(QObject *parent) : QEventDispatcherSymbian(parent), m_noInputEvents(false) @@ -127,4 +183,14 @@ void QEventDispatcherS60::removeInputEventsForWidget(QObject *object) } } +// reimpl +void QEventDispatcherS60::reactivateDeferredActiveObjects() +{ + if (S60->qtOwnsS60Environment) { + static_cast<QtEikonEnv *>(CCoeEnv::Static())->complete(); + } + + QEventDispatcherSymbian::reactivateDeferredActiveObjects(); +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qeventdispatcher_s60_p.h b/src/gui/kernel/qeventdispatcher_s60_p.h index d2f327c..c14fef0 100644 --- a/src/gui/kernel/qeventdispatcher_s60_p.h +++ b/src/gui/kernel/qeventdispatcher_s60_p.h @@ -56,8 +56,30 @@ #include <private/qeventdispatcher_symbian_p.h> #include "qt_s60_p.h" +#include <eikenv.h> + QT_BEGIN_NAMESPACE +class QEventDispatcherS60; + +class QtEikonEnv : public CEikonEnv +{ +public: + QtEikonEnv(); + ~QtEikonEnv(); + + // from CActive. + void RunL(); + void DoCancel(); + + void complete(); + +private: + int m_lastIterationCount; + TInt m_savedStatusCode; + bool m_hasAlreadyRun; +}; + class Q_GUI_EXPORT QEventDispatcherS60 : public QEventDispatcherSymbian { Q_OBJECT @@ -73,6 +95,8 @@ public: void saveInputEvent(QSymbianControl *control, QWidget *widget, QInputEvent *event); + void reactivateDeferredActiveObjects(); + private: bool sendDeferredInputEvents(); diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index eb53dca..aefbe1f 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -3713,4 +3713,5 @@ EXPORTS _ZrsR11QDataStreamR12QEasingCurve @ 3712 NONAME _Z26qt_symbian_SetupThreadHeapiR24SStdEpocThreadCreateInfo @ 3713 NONAME _ZN24QAbstractDeclarativeData17objectNameChangedE @ 3714 NONAME DATA 4 + _ZN23QEventDispatcherSymbian36queueDeferredActiveObjectsCompletionEv @ 3715 NONAME diff --git a/tests/auto/qinputcontext/tst_qinputcontext.cpp b/tests/auto/qinputcontext/tst_qinputcontext.cpp index 7811a53..5a258a9 100644 --- a/tests/auto/qinputcontext/tst_qinputcontext.cpp +++ b/tests/auto/qinputcontext/tst_qinputcontext.cpp @@ -158,8 +158,8 @@ public: } // For some reason, the test fails if using processEvents instead of an event loop - // with a zero timer to quit it, so use the timer. -#define KEY_WAIT 0 + // with a timer to quit it, so use the timer. +#define KEY_WAIT 10 void replay(QWidget *w) { |