2011-04-27 10:05:43 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
|
|
|
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
|
|
|
** All rights reserved.
|
|
|
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
|
|
**
|
|
|
|
** This file is part of the qmake application of the Qt Toolkit.
|
|
|
|
**
|
|
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
|
|
** GNU Lesser General Public License Usage
|
2011-05-24 09:34:08 +00:00
|
|
|
** 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.
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
|
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
2011-05-24 09:34:08 +00:00
|
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
2011-04-27 10:05:43 +00:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
2011-05-24 09:34:08 +00:00
|
|
|
** GNU General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU General
|
|
|
|
** Public License version 3.0 as published by the Free Software Foundation
|
|
|
|
** and appearing in the file LICENSE.GPL included in the packaging of this
|
|
|
|
** file. Please review the following information to ensure the GNU General
|
|
|
|
** Public License version 3.0 requirements will be met:
|
|
|
|
** http://www.gnu.org/copyleft/gpl.html.
|
|
|
|
**
|
|
|
|
** Other Usage
|
|
|
|
** Alternatively, this file may be used in accordance with the terms and
|
|
|
|
** conditions contained in a signed written agreement between you and Nokia.
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
|
|
|
**
|
|
|
|
**
|
|
|
|
**
|
|
|
|
**
|
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "symbiancommon.h"
|
|
|
|
#include <qdebug.h>
|
|
|
|
#include <qxmlstream.h>
|
|
|
|
|
|
|
|
// Included from tools/shared
|
|
|
|
#include <symbian/epocroot_p.h>
|
|
|
|
|
|
|
|
#define RESOURCE_DIRECTORY_RESOURCE "\\\\resource\\\\apps\\\\"
|
|
|
|
|
|
|
|
#define RSS_RULES "RSS_RULES"
|
|
|
|
#define RSS_RULES_BASE "RSS_RULES."
|
|
|
|
#define RSS_TAG_NBROFICONS "number_of_icons"
|
|
|
|
#define RSS_TAG_ICONFILE "icon_file"
|
|
|
|
#define RSS_TAG_HEADER "header"
|
|
|
|
#define RSS_TAG_SERVICE_LIST "service_list"
|
|
|
|
#define RSS_TAG_FILE_OWNERSHIP_LIST "file_ownership_list"
|
|
|
|
#define RSS_TAG_DATATYPE_LIST "datatype_list"
|
|
|
|
#define RSS_TAG_FOOTER "footer"
|
|
|
|
#define RSS_TAG_DEFAULT "default_rules" // Same as just giving rules without tag
|
|
|
|
|
|
|
|
#define PLUGIN_COMMON_DEF_FILE_ACTUAL "plugin_commonu.def"
|
|
|
|
|
|
|
|
#define MANUFACTURER_NOTE_FILE "manufacturer_note.txt"
|
|
|
|
#define DEFAULT_MANUFACTURER_NOTE \
|
|
|
|
"The package is not supported for devices from this manufacturer. Please try the selfsigned " \
|
|
|
|
"version of the package instead."
|
|
|
|
|
|
|
|
SymbianCommonGenerator::SymbianCommonGenerator(MakefileGenerator *generator)
|
|
|
|
: generator(generator)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void SymbianCommonGenerator::init()
|
|
|
|
{
|
|
|
|
QMakeProject *project = generator->project;
|
|
|
|
fixedTarget = project->first("QMAKE_ORIG_TARGET");
|
|
|
|
if (fixedTarget.isEmpty())
|
|
|
|
fixedTarget = project->first("TARGET");
|
|
|
|
fixedTarget = generator->unescapeFilePath(fixedTarget);
|
|
|
|
fixedTarget = removePathSeparators(fixedTarget);
|
|
|
|
removeSpecialCharacters(fixedTarget);
|
|
|
|
|
|
|
|
// This should not be empty since the mkspecs are supposed to set it if missing.
|
|
|
|
uid3 = project->first("TARGET.UID3").trimmed();
|
|
|
|
|
|
|
|
if ((project->values("TEMPLATE")).contains("app"))
|
|
|
|
targetType = TypeExe;
|
|
|
|
else if ((project->values("TEMPLATE")).contains("lib")) {
|
|
|
|
// Check CONFIG to see if we are to build staticlib or dll
|
|
|
|
if (project->isActiveConfig("staticlib") || project->isActiveConfig("static"))
|
|
|
|
targetType = TypeLib;
|
|
|
|
else if (project->isActiveConfig("plugin"))
|
|
|
|
targetType = TypePlugin;
|
|
|
|
else
|
|
|
|
targetType = TypeDll;
|
|
|
|
} else {
|
|
|
|
targetType = TypeSubdirs;
|
|
|
|
}
|
|
|
|
|
|
|
|
// UID is valid as either hex or decimal, so just convert it to number and back to hex
|
|
|
|
// to get proper string for private dir
|
|
|
|
bool conversionOk = false;
|
|
|
|
uint uidNum = uid3.toUInt(&conversionOk, 0);
|
|
|
|
|
|
|
|
if (!conversionOk) {
|
|
|
|
fprintf(stderr, "Error: Invalid UID \"%s\".\n", uid3.toUtf8().constData());
|
|
|
|
} else {
|
|
|
|
privateDirUid.setNum(uidNum, 16);
|
|
|
|
while (privateDirUid.length() < 8)
|
|
|
|
privateDirUid.insert(0, QLatin1Char('0'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SymbianCommonGenerator::containsStartWithItem(const QChar &c, const QStringList& src)
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
foreach(QString str, src) {
|
|
|
|
if (str.startsWith(c)) {
|
|
|
|
result = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SymbianCommonGenerator::removeSpecialCharacters(QString& str)
|
|
|
|
{
|
|
|
|
// When modifying this method check also symbianRemoveSpecialCharacters in symbian.conf
|
|
|
|
QString underscore = QLatin1String("_");
|
|
|
|
str.replace(QLatin1String("/"), underscore);
|
|
|
|
str.replace(QLatin1String("\\"), underscore);
|
|
|
|
str.replace(QLatin1String(" "), underscore);
|
|
|
|
str.replace(QLatin1String(":"), underscore);
|
|
|
|
}
|
|
|
|
|
|
|
|
QString romPath(const QString& path)
|
|
|
|
{
|
|
|
|
if(path.length() > 2 && path[1] == ':')
|
|
|
|
return QLatin1String("z:") + path.mid(2);
|
|
|
|
return QLatin1String("z:") + path;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SymbianCommonGenerator::generatePkgFile(const QString &iconFile,
|
|
|
|
bool epocBuild,
|
|
|
|
const SymbianLocalizationList &symbianLocalizationList)
|
|
|
|
{
|
|
|
|
QMakeProject *project = generator->project;
|
|
|
|
QString pkgFilename = Option::output_dir + QLatin1Char('/') +
|
|
|
|
QString("%1_template.pkg").arg(fixedTarget);
|
|
|
|
|
|
|
|
QFile pkgFile(pkgFilename);
|
|
|
|
if (!pkgFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
|
|
PRINT_FILE_CREATE_ERROR(pkgFilename);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString stubPkgFileName = Option::output_dir + QLatin1Char('/') +
|
|
|
|
QString("%1_stub.pkg").arg(fixedTarget);
|
|
|
|
|
|
|
|
QFile stubPkgFile(stubPkgFileName);
|
|
|
|
if (!stubPkgFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
|
|
PRINT_FILE_CREATE_ERROR(stubPkgFileName);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
generatedFiles << pkgFile.fileName();
|
|
|
|
QTextStream t(&pkgFile);
|
|
|
|
generatedFiles << stubPkgFile.fileName();
|
|
|
|
QTextStream ts(&stubPkgFile);
|
|
|
|
|
|
|
|
QString installerSisHeader = project->values("DEPLOYMENT.installer_header").join("\n");
|
|
|
|
if (installerSisHeader.isEmpty()) {
|
|
|
|
// Use correct protected UID for publishing if application UID is in protected range,
|
|
|
|
// otherwise use self-signable test UID.
|
|
|
|
QRegExp protUidMatcher("0[xX][0-7].*");
|
|
|
|
if (protUidMatcher.exactMatch(uid3))
|
|
|
|
installerSisHeader = QLatin1String("0x2002CCCF");
|
|
|
|
else
|
|
|
|
installerSisHeader = QLatin1String("0xA000D7CE"); // Use default self-signable UID
|
|
|
|
}
|
|
|
|
|
|
|
|
QString wrapperStreamBuffer;
|
|
|
|
QTextStream tw(&wrapperStreamBuffer);
|
|
|
|
|
|
|
|
QString dateStr = QDateTime::currentDateTime().toString(Qt::ISODate);
|
|
|
|
|
|
|
|
// Header info
|
|
|
|
QString wrapperPkgFilename = Option::output_dir + QLatin1Char('/') + QString("%1_installer.%2")
|
|
|
|
.arg(fixedTarget).arg("pkg");
|
|
|
|
|
|
|
|
QString headerComment = "; %1 generated by qmake at %2\n"
|
|
|
|
"; This file is generated by qmake and should not be modified by the user\n"
|
|
|
|
";\n\n";
|
|
|
|
t << headerComment.arg(pkgFilename).arg(dateStr);
|
|
|
|
tw << headerComment.arg(wrapperPkgFilename).arg(dateStr);
|
|
|
|
ts << headerComment.arg(stubPkgFileName).arg(dateStr);
|
|
|
|
|
|
|
|
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.
|
|
|
|
// 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;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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()) {
|
|
|
|
if (symbianLocalizationList.isEmpty()) {
|
|
|
|
languageRules << "; Language\n&EN\n\n";
|
|
|
|
} else {
|
|
|
|
QStringList langCodes;
|
|
|
|
SymbianLocalizationListIterator iter(symbianLocalizationList);
|
|
|
|
while (iter.hasNext()) {
|
|
|
|
const SymbianLocalization &loc = iter.next();
|
|
|
|
langCodes << loc.symbianLanguageCode;
|
|
|
|
}
|
|
|
|
languageRules << QString("; Languages\n&%1\n\n").arg(langCodes.join(","));
|
|
|
|
}
|
|
|
|
} else if (headerRules.isEmpty()) {
|
|
|
|
// In case user defines langs, he must take care also about SIS header
|
|
|
|
fprintf(stderr, "Warning: If language is defined with DEPLOYMENT pkg_prerules, also the SIS header must be defined\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
t << languageRules.join("\n") << endl;
|
|
|
|
tw << languageRules.join("\n") << endl;
|
|
|
|
ts << languageRules.join("\n") << endl;
|
|
|
|
|
|
|
|
// Determine application version. If version has missing component values,
|
|
|
|
// those will default to zero.
|
|
|
|
// If VERSION is missing altogether or is invalid, use "1,0,0"
|
|
|
|
QStringList verNumList = project->first("VERSION").split('.');
|
|
|
|
uint major = 0;
|
|
|
|
uint minor = 0;
|
|
|
|
uint patch = 0;
|
|
|
|
bool success = false;
|
|
|
|
|
|
|
|
if (verNumList.size() > 0) {
|
|
|
|
major = verNumList[0].toUInt(&success);
|
|
|
|
if (success && verNumList.size() > 1) {
|
|
|
|
minor = verNumList[1].toUInt(&success);
|
|
|
|
if (success && verNumList.size() > 2) {
|
|
|
|
patch = verNumList[2].toUInt(&success);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QString applicationVersion("1,0,0");
|
|
|
|
if (success)
|
|
|
|
applicationVersion = QString("%1,%2,%3").arg(major).arg(minor).arg(patch);
|
|
|
|
|
|
|
|
// Append package build version number if it is set
|
|
|
|
QString pkgBuildVersion = project->first("DEPLOYMENT.pkg_build_version");
|
|
|
|
if (!pkgBuildVersion.isEmpty()) {
|
|
|
|
success = false;
|
|
|
|
uint build = pkgBuildVersion.toUInt(&success);
|
|
|
|
if (success && build < 100) {
|
|
|
|
if (pkgBuildVersion.size() == 1)
|
|
|
|
pkgBuildVersion.prepend(QLatin1Char('0'));
|
|
|
|
applicationVersion.append(pkgBuildVersion);
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Warning: Invalid DEPLOYMENT.pkg_build_version (%s), must be a number between 0 - 99\n", qPrintable(pkgBuildVersion));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Package header
|
|
|
|
QString sisHeader = "; SIS header: name, uid, version\n#{\"%1\"},(%2),%3\n\n";
|
|
|
|
|
|
|
|
QString defaultVisualTarget = project->values("DEPLOYMENT.display_name").join(" ");
|
|
|
|
if (defaultVisualTarget.isEmpty())
|
|
|
|
defaultVisualTarget = generator->escapeFilePath(project->first("TARGET"));
|
|
|
|
defaultVisualTarget = removePathSeparators(defaultVisualTarget);
|
|
|
|
|
|
|
|
QString visualTarget = generatePkgNameForHeader(symbianLocalizationList, defaultVisualTarget, false);
|
|
|
|
QString wrapperTarget = generatePkgNameForHeader(symbianLocalizationList, defaultVisualTarget, true);
|
|
|
|
|
|
|
|
if (installerSisHeader.startsWith("0x", Qt::CaseInsensitive)) {
|
|
|
|
tw << sisHeader.arg(wrapperTarget).arg(installerSisHeader).arg(applicationVersion);
|
|
|
|
} else {
|
|
|
|
tw << installerSisHeader << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (headerRules.isEmpty()) {
|
|
|
|
t << sisHeader.arg(visualTarget).arg(uid3).arg(applicationVersion);
|
|
|
|
ts << sisHeader.arg(visualTarget).arg(uid3).arg(applicationVersion);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
t << headerRules.join("\n") << endl;
|
|
|
|
ts << headerRules.join("\n") << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Vendor name
|
|
|
|
if (!containsStartWithItem('%', vendorRules)) {
|
|
|
|
QString vendorStr = QLatin1String("\"Vendor\",");
|
|
|
|
QString locVendors = vendorStr;
|
|
|
|
for (int i = 1; i < symbianLocalizationList.size(); i++) {
|
|
|
|
locVendors.append(vendorStr);
|
|
|
|
}
|
|
|
|
locVendors.chop(1);
|
|
|
|
vendorRules << QString("; Default localized vendor name\n%{%1}\n\n").arg(locVendors);
|
|
|
|
}
|
|
|
|
if (!containsStartWithItem(':', vendorRules)) {
|
|
|
|
vendorRules << "; Default unique vendor name\n:\"Vendor\"\n\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
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;
|
|
|
|
ts << stubRawPreRules.join("\n") << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
t << endl;
|
|
|
|
tw << endl;
|
|
|
|
ts << endl;
|
|
|
|
|
|
|
|
// Begin Manufacturer block
|
|
|
|
if (!project->values("DEPLOYMENT.manufacturers").isEmpty()) {
|
|
|
|
QString manufacturerStr("IF ");
|
|
|
|
foreach(QString manufacturer, project->values("DEPLOYMENT.manufacturers")) {
|
|
|
|
manufacturerStr.append(QString("(MANUFACTURER)=(%1) OR \n ").arg(manufacturer));
|
|
|
|
}
|
|
|
|
// Remove the final OR
|
|
|
|
manufacturerStr.chop(8);
|
|
|
|
t << manufacturerStr << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (symbianLocalizationList.size()) {
|
|
|
|
// Add localized resources to DEPLOYMENT if default resource deployment is done
|
|
|
|
addLocalizedResourcesToDeployment("default_resource_deployment.files", symbianLocalizationList);
|
|
|
|
addLocalizedResourcesToDeployment("default_reg_deployment.files", symbianLocalizationList);
|
|
|
|
}
|
|
|
|
|
|
|
|
// deploy files specified by DEPLOYMENT variable
|
|
|
|
QString remoteTestPath;
|
|
|
|
QString zDir;
|
|
|
|
remoteTestPath = QString("!:\\private\\%1").arg(privateDirUid);
|
|
|
|
if (epocBuild)
|
|
|
|
zDir = qt_epocRoot() + QLatin1String("epoc32/data/z");
|
|
|
|
|
|
|
|
DeploymentList depList;
|
|
|
|
initProjectDeploySymbian(project, depList, remoteTestPath, true, epocBuild, "$(PLATFORM)", "$(TARGET)", generatedDirs, generatedFiles);
|
|
|
|
if (depList.size())
|
|
|
|
t << "; DEPLOYMENT" << endl;
|
|
|
|
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
|
|
|
|
// \epoc32\data\z\ to enable using pkg file without rebuilding
|
|
|
|
// the project, which can be useful for some binary only distributions.
|
|
|
|
if (!from.contains(QLatin1String("epoc32"), Qt::CaseInsensitive)) {
|
|
|
|
from = to;
|
|
|
|
if (from.size() > 1 && from.at(1) == QLatin1Char(':'))
|
|
|
|
from = from.mid(2);
|
|
|
|
from.prepend(zDir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
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
|
|
|
|
if (!project->values("DEPLOYMENT.manufacturers").isEmpty()) {
|
|
|
|
QString manufacturerFailNoteFile;
|
|
|
|
if (project->values("DEPLOYMENT.manufacturers.fail_note").isEmpty()) {
|
|
|
|
manufacturerFailNoteFile = QString("%1_" MANUFACTURER_NOTE_FILE).arg(uid3);
|
|
|
|
QFile ft(manufacturerFailNoteFile);
|
|
|
|
if (ft.open(QIODevice::WriteOnly)) {
|
|
|
|
generatedFiles << ft.fileName();
|
|
|
|
QTextStream t2(&ft);
|
|
|
|
|
|
|
|
t2 << QString(DEFAULT_MANUFACTURER_NOTE) << endl;
|
|
|
|
} else {
|
|
|
|
PRINT_FILE_CREATE_ERROR(manufacturerFailNoteFile)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
manufacturerFailNoteFile = project->values("DEPLOYMENT.manufacturers.fail_note").join("");
|
|
|
|
}
|
|
|
|
|
|
|
|
t << "ELSEIF NOT(0) ; MANUFACTURER" << endl
|
|
|
|
<< "\"" << generator->fileInfo(manufacturerFailNoteFile).absoluteFilePath() << "\""
|
|
|
|
<< " - \"\", FILETEXT, TEXTEXIT" << endl
|
|
|
|
<< "ENDIF ; MANUFACTURER" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write wrapper pkg
|
|
|
|
if (!installerSisHeader.isEmpty()) {
|
|
|
|
QFile wrapperPkgFile(wrapperPkgFilename);
|
|
|
|
if (!wrapperPkgFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
|
|
PRINT_FILE_CREATE_ERROR(wrapperPkgFilename);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
generatedFiles << wrapperPkgFile.fileName();
|
|
|
|
QTextStream twf(&wrapperPkgFile);
|
|
|
|
|
|
|
|
twf << wrapperStreamBuffer << endl;
|
|
|
|
|
|
|
|
// Wrapped files deployment
|
|
|
|
QString currentPath = qmake_getpwd();
|
|
|
|
QString sisName = QString("%1.sis").arg(fixedTarget);
|
|
|
|
twf << "\"" << currentPath << "/" << sisName << "\" - \"!:\\private\\2002CCCE\\import\\" << sisName << "\"" << endl;
|
|
|
|
|
|
|
|
QString bootStrapPath = QLibraryInfo::location(QLibraryInfo::PrefixPath);
|
|
|
|
bootStrapPath.append("/smartinstaller.sis");
|
|
|
|
QFileInfo fi(generator->fileInfo(bootStrapPath));
|
|
|
|
twf << "@\"" << fi.absoluteFilePath() << "\",(0x2002CCCD)" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QString SymbianCommonGenerator::removePathSeparators(QString &file)
|
|
|
|
{
|
|
|
|
QString ret = file;
|
|
|
|
|
|
|
|
if (QDir::separator().unicode() != '/')
|
|
|
|
ret.replace(QDir::separator(), QLatin1Char('/'));
|
|
|
|
|
|
|
|
if (ret.indexOf(QLatin1Char('/')) >= 0)
|
|
|
|
ret.remove(0, ret.lastIndexOf(QLatin1Char('/')) + 1);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SymbianCommonGenerator::writeRegRssFile(QMap<QString, QStringList> &userItems)
|
|
|
|
{
|
|
|
|
QString filename(fixedTarget);
|
|
|
|
filename.append("_reg.rss");
|
|
|
|
if (!Option::output_dir.isEmpty())
|
|
|
|
filename = Option::output_dir + '/' + filename;
|
|
|
|
QFile ft(filename);
|
|
|
|
if (ft.open(QIODevice::WriteOnly)) {
|
|
|
|
generatedFiles << ft.fileName();
|
|
|
|
QTextStream t(&ft);
|
|
|
|
t << "// ============================================================================" << endl;
|
|
|
|
t << "// * Generated by qmake (" << qmake_version() << ") (Qt " QT_VERSION_STR ") on: ";
|
|
|
|
t << QDateTime::currentDateTime().toString(Qt::ISODate) << endl;
|
|
|
|
t << "// * This file is generated by qmake and should not be modified by the" << endl;
|
|
|
|
t << "// * user." << endl;
|
|
|
|
t << "// ============================================================================" << endl;
|
|
|
|
t << endl;
|
|
|
|
t << "#include <" << fixedTarget << ".rsg>" << endl;
|
|
|
|
t << "#include <appinfo.rh>" << endl;
|
|
|
|
foreach(QString item, userItems[RSS_TAG_HEADER])
|
|
|
|
t << item << endl;
|
|
|
|
t << endl;
|
|
|
|
t << "UID2 KUidAppRegistrationResourceFile" << endl;
|
|
|
|
t << "UID3 " << uid3 << endl << endl;
|
|
|
|
t << "RESOURCE APP_REGISTRATION_INFO" << endl;
|
|
|
|
t << "\t{" << endl;
|
|
|
|
t << "\tapp_file=\"" << fixedTarget << "\";" << endl;
|
|
|
|
t << "\tlocalisable_resource_file=\"" RESOURCE_DIRECTORY_RESOURCE << fixedTarget << "\";" << endl;
|
|
|
|
|
|
|
|
writeRegRssList(t, userItems[RSS_TAG_SERVICE_LIST],
|
|
|
|
QLatin1String(RSS_TAG_SERVICE_LIST),
|
|
|
|
QLatin1String("SERVICE_INFO"));
|
|
|
|
writeRegRssList(t, userItems[RSS_TAG_FILE_OWNERSHIP_LIST],
|
|
|
|
QLatin1String(RSS_TAG_FILE_OWNERSHIP_LIST),
|
|
|
|
QLatin1String("FILE_OWNERSHIP_INFO"));
|
|
|
|
writeRegRssList(t, userItems[RSS_TAG_DATATYPE_LIST],
|
|
|
|
QLatin1String(RSS_TAG_DATATYPE_LIST),
|
|
|
|
QLatin1String("DATATYPE"));
|
|
|
|
t << endl;
|
|
|
|
|
|
|
|
foreach(QString item, userItems[RSS_TAG_DEFAULT])
|
|
|
|
t << "\t" << item.replace("\n","\n\t") << endl;
|
|
|
|
t << "\t}" << endl;
|
|
|
|
|
|
|
|
foreach(QString item, userItems[RSS_TAG_FOOTER])
|
|
|
|
t << item << endl;
|
|
|
|
} else {
|
|
|
|
PRINT_FILE_CREATE_ERROR(filename)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SymbianCommonGenerator::writeRegRssList(QTextStream &t,
|
|
|
|
QStringList &userList,
|
|
|
|
const QString &listTag,
|
|
|
|
const QString &listItem)
|
|
|
|
{
|
|
|
|
int itemCount = userList.count();
|
|
|
|
if (itemCount) {
|
|
|
|
t << "\t" << listTag << " ="<< endl;
|
|
|
|
t << "\t\t{" << endl;
|
|
|
|
foreach(QString item, userList) {
|
|
|
|
t << "\t\t" << listItem << endl;
|
|
|
|
t << "\t\t\t{" << endl;
|
|
|
|
t << "\t\t\t" << item.replace("\n","\n\t\t\t") << endl;
|
|
|
|
t << "\t\t\t}";
|
|
|
|
if (--itemCount)
|
|
|
|
t << ",";
|
|
|
|
t << endl;
|
|
|
|
}
|
|
|
|
t << "\t\t}; "<< endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SymbianCommonGenerator::writeRssFile(QString &numberOfIcons, QString &iconFile)
|
|
|
|
{
|
|
|
|
QString filename(fixedTarget);
|
|
|
|
if (!Option::output_dir.isEmpty())
|
|
|
|
filename = Option::output_dir + '/' + filename;
|
|
|
|
filename.append(".rss");
|
|
|
|
QFile ft(filename);
|
|
|
|
if (ft.open(QIODevice::WriteOnly)) {
|
|
|
|
generatedFiles << ft.fileName();
|
|
|
|
QTextStream t(&ft);
|
|
|
|
t << "// ============================================================================" << endl;
|
|
|
|
t << "// * Generated by qmake (" << qmake_version() << ") (Qt " QT_VERSION_STR ") on: ";
|
|
|
|
t << QDateTime::currentDateTime().toString(Qt::ISODate) << endl;
|
|
|
|
t << "// * This file is generated by qmake and should not be modified by the" << endl;
|
|
|
|
t << "// * user." << endl;
|
|
|
|
t << "// ============================================================================" << endl;
|
|
|
|
t << endl;
|
|
|
|
t << "CHARACTER_SET UTF8" << endl;
|
|
|
|
t << "#include <appinfo.rh>" << endl;
|
|
|
|
t << "#include \"" << fixedTarget << ".loc\"" << endl;
|
|
|
|
t << endl;
|
|
|
|
t << "RESOURCE LOCALISABLE_APP_INFO r_localisable_app_info" << endl;
|
|
|
|
t << "\t{" << endl;
|
|
|
|
t << "\tshort_caption = STRING_r_short_caption;" << endl;
|
|
|
|
t << "\tcaption_and_icon =" << endl;
|
|
|
|
t << "\tCAPTION_AND_ICON_INFO" << endl;
|
|
|
|
t << "\t\t{" << endl;
|
|
|
|
t << "\t\tcaption = STRING_r_caption;" << endl;
|
|
|
|
|
|
|
|
QString rssIconFile = iconFile;
|
|
|
|
rssIconFile = rssIconFile.replace("/", "\\\\");
|
|
|
|
|
|
|
|
if (numberOfIcons.isEmpty() || rssIconFile.isEmpty()) {
|
|
|
|
// There can be maximum one item in this tag, validated when parsed
|
|
|
|
t << "\t\tnumber_of_icons = 0;" << endl;
|
|
|
|
t << "\t\ticon_file = \"\";" << endl;
|
|
|
|
} else {
|
|
|
|
// There can be maximum one item in this tag, validated when parsed
|
|
|
|
t << "\t\tnumber_of_icons = " << numberOfIcons << ";" << endl;
|
|
|
|
t << "\t\ticon_file = \"" << rssIconFile << "\";" << endl;
|
|
|
|
}
|
|
|
|
t << "\t\t};" << endl;
|
|
|
|
t << "\t}" << endl;
|
|
|
|
t << endl;
|
|
|
|
} else {
|
|
|
|
PRINT_FILE_CREATE_ERROR(filename);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SymbianCommonGenerator::writeLocFile(const SymbianLocalizationList &symbianLocalizationList)
|
|
|
|
{
|
|
|
|
QString filename = generateLocFileName();
|
|
|
|
QFile ft(filename);
|
|
|
|
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;
|
|
|
|
t << "// * This file is generated by qmake and should not be modified by the" << endl;
|
|
|
|
t << "// * user." << endl;
|
|
|
|
t << "// ============================================================================" << endl;
|
|
|
|
t << endl;
|
|
|
|
t << "#ifdef LANGUAGE_SC" << endl;
|
|
|
|
t << "#define STRING_r_short_caption \"" << displayName << "\"" << endl;
|
|
|
|
t << "#define STRING_r_caption \"" << displayName << "\"" << endl;
|
|
|
|
|
|
|
|
SymbianLocalizationListIterator iter(symbianLocalizationList);
|
|
|
|
while (iter.hasNext()) {
|
|
|
|
const SymbianLocalization &loc = iter.next();
|
|
|
|
QString shortCaption = loc.shortCaption;
|
|
|
|
QString longCaption = loc.longCaption;
|
|
|
|
if (shortCaption.isEmpty())
|
|
|
|
shortCaption = displayName;
|
|
|
|
if (longCaption.isEmpty())
|
|
|
|
longCaption = displayName;
|
|
|
|
|
|
|
|
t << "#elif defined LANGUAGE_" << loc.symbianLanguageCode << endl;
|
|
|
|
t << "#define STRING_r_short_caption \"" << shortCaption << "\"" << endl;
|
|
|
|
t << "#define STRING_r_caption \"" << longCaption << "\"" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
t << "#else" << 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SymbianCommonGenerator::readRssRules(QString &numberOfIcons,
|
|
|
|
QString &iconFile, QMap<QString,
|
|
|
|
QStringList> &userRssRules)
|
|
|
|
{
|
|
|
|
QMakeProject *project = generator->project;
|
|
|
|
for (QMap<QString, QStringList>::iterator it = project->variables().begin(); it != project->variables().end(); ++it) {
|
|
|
|
if (it.key().startsWith(RSS_RULES_BASE)) {
|
|
|
|
QString newKey = it.key().mid(sizeof(RSS_RULES_BASE) - 1);
|
|
|
|
if (newKey.isEmpty()) {
|
|
|
|
fprintf(stderr, "Warning: Empty RSS_RULES_BASE key encountered\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
QStringList newValues;
|
|
|
|
QStringList values = it.value();
|
|
|
|
foreach(QString item, values) {
|
|
|
|
// If there is no stringlist defined for a rule, use rule value directly
|
|
|
|
// This is convenience for defining single line statements
|
|
|
|
if (project->values(item).isEmpty()) {
|
|
|
|
newValues << item;
|
|
|
|
} else {
|
|
|
|
QStringList itemList;
|
|
|
|
foreach(QString itemRow, project->values(item)) {
|
|
|
|
itemList << itemRow;
|
|
|
|
}
|
|
|
|
newValues << itemList.join("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Verify that there is exactly one value in RSS_TAG_NBROFICONS
|
|
|
|
if (newKey == RSS_TAG_NBROFICONS) {
|
|
|
|
if (newValues.count() == 1) {
|
|
|
|
numberOfIcons = newValues[0];
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Warning: There must be exactly one value in '%s%s'\n",
|
|
|
|
RSS_RULES_BASE, RSS_TAG_NBROFICONS);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// Verify that there is exactly one value in RSS_TAG_ICONFILE
|
|
|
|
} else if (newKey == RSS_TAG_ICONFILE) {
|
|
|
|
if (newValues.count() == 1) {
|
|
|
|
iconFile = newValues[0];
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Warning: There must be exactly one value in '%s%s'\n",
|
|
|
|
RSS_RULES_BASE, RSS_TAG_ICONFILE);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else if (newKey == RSS_TAG_HEADER
|
|
|
|
|| newKey == RSS_TAG_SERVICE_LIST
|
|
|
|
|| newKey == RSS_TAG_FILE_OWNERSHIP_LIST
|
|
|
|
|| newKey == RSS_TAG_DATATYPE_LIST
|
|
|
|
|| newKey == RSS_TAG_FOOTER
|
|
|
|
|| newKey == RSS_TAG_DEFAULT) {
|
|
|
|
userRssRules[newKey] = newValues;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Warning: Unsupported key:'%s%s'\n",
|
|
|
|
RSS_RULES_BASE, newKey.toLatin1().constData());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList newValues;
|
|
|
|
foreach(QString item, project->values(RSS_RULES)) {
|
|
|
|
// If there is no stringlist defined for a rule, use rule value directly
|
|
|
|
// This is convenience for defining single line statements
|
|
|
|
if (project->values(item).isEmpty()) {
|
|
|
|
newValues << item;
|
|
|
|
} else {
|
|
|
|
newValues << project->values(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
userRssRules[RSS_TAG_DEFAULT] << newValues;
|
|
|
|
|
|
|
|
// Validate that either both RSS_TAG_NBROFICONS and RSS_TAG_ICONFILE keys exist
|
|
|
|
// or neither of them exist
|
|
|
|
if (!((numberOfIcons.isEmpty() && iconFile.isEmpty()) ||
|
|
|
|
(!numberOfIcons.isEmpty() && !iconFile.isEmpty()))) {
|
|
|
|
numberOfIcons.clear();
|
|
|
|
iconFile.clear();
|
|
|
|
fprintf(stderr, "Warning: Both or neither of '%s%s' and '%s%s' keys must exist.\n",
|
|
|
|
RSS_RULES_BASE, RSS_TAG_NBROFICONS, RSS_RULES_BASE, RSS_TAG_ICONFILE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Validate that RSS_TAG_NBROFICONS contains only numbers
|
|
|
|
if (!numberOfIcons.isEmpty()) {
|
|
|
|
bool ok;
|
|
|
|
numberOfIcons = numberOfIcons.simplified();
|
|
|
|
numberOfIcons.toInt(&ok);
|
|
|
|
if (!ok) {
|
|
|
|
numberOfIcons.clear();
|
|
|
|
iconFile.clear();
|
|
|
|
fprintf(stderr, "Warning: '%s%s' must be integer in decimal format.\n",
|
|
|
|
RSS_RULES_BASE, RSS_TAG_NBROFICONS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SymbianCommonGenerator::writeCustomDefFile()
|
|
|
|
{
|
|
|
|
if (targetType == TypePlugin && !generator->project->isActiveConfig("stdbinary")) {
|
|
|
|
// Create custom def file for plugin
|
|
|
|
QFile ft(Option::output_dir + QLatin1Char('/') + QLatin1String(PLUGIN_COMMON_DEF_FILE_ACTUAL));
|
|
|
|
|
|
|
|
if (ft.open(QIODevice::WriteOnly)) {
|
|
|
|
generatedFiles << ft.fileName();
|
|
|
|
QTextStream t(&ft);
|
|
|
|
|
|
|
|
t << "; ==============================================================================" << endl;
|
|
|
|
t << "; Generated by qmake (" << qmake_version() << ") (Qt " QT_VERSION_STR ") on: ";
|
|
|
|
t << QDateTime::currentDateTime().toString(Qt::ISODate) << endl;
|
|
|
|
t << "; This file is generated by qmake and should not be modified by the" << endl;
|
|
|
|
t << "; user." << endl;
|
|
|
|
t << "; Name : " PLUGIN_COMMON_DEF_FILE_ACTUAL << endl;
|
|
|
|
t << "; Part of : " << generator->project->values("TARGET").join(" ") << endl;
|
|
|
|
t << "; Description : Fixes common plugin symbols to known ordinals" << endl;
|
|
|
|
t << "; Version : " << endl;
|
|
|
|
t << ";" << endl;
|
|
|
|
t << "; ==============================================================================" << "\n" << endl;
|
|
|
|
|
|
|
|
t << endl;
|
|
|
|
|
|
|
|
t << "EXPORTS" << endl;
|
|
|
|
t << "\tqt_plugin_query_verification_data @ 1 NONAME" << endl;
|
|
|
|
t << "\tqt_plugin_instance @ 2 NONAME" << endl;
|
|
|
|
t << endl;
|
|
|
|
} else {
|
|
|
|
PRINT_FILE_CREATE_ERROR(QString(PLUGIN_COMMON_DEF_FILE_ACTUAL))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SymbianCommonGenerator::parseTsFiles(SymbianLocalizationList *symbianLocalizationList)
|
|
|
|
{
|
|
|
|
if (!generator->project->isActiveConfig("localize_deployment")) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList symbianTsFiles;
|
|
|
|
|
|
|
|
symbianTsFiles << generator->project->values("SYMBIAN_MATCHED_TRANSLATIONS");
|
|
|
|
|
|
|
|
if (!symbianTsFiles.isEmpty()) {
|
|
|
|
fillQt2SymbianLocalizationList(symbianLocalizationList);
|
|
|
|
|
|
|
|
QMutableListIterator<SymbianLocalization> iter(*symbianLocalizationList);
|
|
|
|
while (iter.hasNext()) {
|
|
|
|
SymbianLocalization &loc = iter.next();
|
|
|
|
static QString matchStrTemplate = QLatin1String(".*_%1\\.ts");
|
|
|
|
QString matchStr = matchStrTemplate.arg(loc.qtLanguageCode);
|
|
|
|
|
|
|
|
foreach (QString file, symbianTsFiles) {
|
|
|
|
QRegExp matcher(matchStr);
|
|
|
|
if (matcher.exactMatch(file) && parseTsContent(file, &loc))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SymbianCommonGenerator::fillQt2SymbianLocalizationList(SymbianLocalizationList *symbianLocalizationList)
|
|
|
|
{
|
|
|
|
static QString symbianCodePrefix = QLatin1String("SYMBIAN_LANG.");
|
|
|
|
|
|
|
|
QStringList symbianLanguages = generator->project->values("SYMBIAN_MATCHED_LANGUAGES");
|
|
|
|
|
|
|
|
foreach (QString qtCode, symbianLanguages) {
|
|
|
|
SymbianLocalization newLoc;
|
|
|
|
QString symbianCodeVariable = symbianCodePrefix + qtCode;
|
|
|
|
newLoc.symbianLanguageCode = generator->project->first(symbianCodeVariable);
|
|
|
|
if (!newLoc.symbianLanguageCode.isEmpty()) {
|
|
|
|
newLoc.qtLanguageCode = qtCode;
|
|
|
|
symbianLocalizationList->append(newLoc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SymbianCommonGenerator::parseTsContent(const QString &tsFilename, SymbianLocalization *loc)
|
|
|
|
{
|
|
|
|
bool retval = true;
|
|
|
|
QMakeProject *project = generator->project;
|
|
|
|
QFile tsFile(tsFilename);
|
|
|
|
|
|
|
|
if (tsFile.exists()) {
|
|
|
|
if (tsFile.open(QIODevice::ReadOnly)) {
|
|
|
|
static QString applicationCaptionsContext = QLatin1String("QtApplicationCaptions");
|
|
|
|
static QString pkgNameContext = QLatin1String("QtPackageNames");
|
|
|
|
static QString tsElement = QLatin1String("TS");
|
|
|
|
static QString contextElement = QLatin1String("context");
|
|
|
|
static QString nameElement = QLatin1String("name");
|
|
|
|
static QString messageElement = QLatin1String("message");
|
|
|
|
static QString sourceElement = QLatin1String("source");
|
|
|
|
static QString translationElement = QLatin1String("translation");
|
|
|
|
static QString shortCaptionId = QLatin1String("Application short caption");
|
|
|
|
static QString longCaptionId = QLatin1String("Application long caption");
|
|
|
|
static QString pkgDisplayNameId = QLatin1String("Package name");
|
|
|
|
static QString installerPkgDisplayNameId = QLatin1String("Smart installer package name");
|
|
|
|
static QString languageAttribute = QLatin1String("language");
|
|
|
|
static QChar underscoreChar = QLatin1Char('_');
|
|
|
|
|
|
|
|
enum CurrentContext {
|
|
|
|
ContextUnknown,
|
|
|
|
ContextUninteresting,
|
|
|
|
ContextInteresting
|
|
|
|
};
|
|
|
|
|
|
|
|
QXmlStreamReader xml(&tsFile);
|
|
|
|
|
|
|
|
while (!xml.atEnd() && xml.name() != tsElement)
|
|
|
|
xml.readNextStartElement();
|
|
|
|
|
|
|
|
while (xml.readNextStartElement()) {
|
|
|
|
if (xml.name() == contextElement) {
|
|
|
|
CurrentContext currentContext = ContextUnknown;
|
|
|
|
while (xml.readNextStartElement()) {
|
|
|
|
if (currentContext == ContextUnknown) {
|
|
|
|
// Expect name element before message elements
|
|
|
|
if (xml.name() == nameElement) {
|
|
|
|
QString nameText = xml.readElementText();
|
|
|
|
if (nameText == applicationCaptionsContext || nameText == pkgNameContext) {
|
|
|
|
currentContext = ContextInteresting;
|
|
|
|
} else {
|
|
|
|
currentContext = ContextUninteresting;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
xml.skipCurrentElement();
|
|
|
|
}
|
|
|
|
} else if (currentContext == ContextInteresting) {
|
|
|
|
if (xml.name() == messageElement) {
|
|
|
|
QString source;
|
|
|
|
QString translation;
|
|
|
|
while (xml.readNextStartElement()) {
|
|
|
|
if (xml.name() == sourceElement) {
|
|
|
|
source = xml.readElementText();
|
|
|
|
} else if (xml.name() == translationElement) {
|
|
|
|
translation = xml.readElementText();
|
|
|
|
} else {
|
|
|
|
xml.skipCurrentElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source == shortCaptionId) {
|
|
|
|
if (loc->shortCaption.isEmpty()) {
|
|
|
|
loc->shortCaption = translation;
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Warning: Duplicate application short caption defined in (%s).\n",
|
|
|
|
qPrintable(tsFilename));
|
|
|
|
}
|
|
|
|
} else if (source == longCaptionId) {
|
|
|
|
if (loc->longCaption.isEmpty()) {
|
|
|
|
loc->longCaption = translation;
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Warning: Duplicate application long caption defined in (%s).\n",
|
|
|
|
qPrintable(tsFilename));
|
|
|
|
}
|
|
|
|
} else if (source == pkgDisplayNameId) {
|
|
|
|
if (loc->pkgDisplayName.isEmpty()) {
|
|
|
|
loc->pkgDisplayName = translation;
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Warning: Duplicate package display name defined in (%s).\n",
|
|
|
|
qPrintable(tsFilename));
|
|
|
|
}
|
|
|
|
} else if (source == installerPkgDisplayNameId) {
|
|
|
|
if (loc->installerPkgDisplayName.isEmpty()) {
|
|
|
|
loc->installerPkgDisplayName = translation;
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Warning: Duplicate smart installer package display name defined in (%s).\n",
|
|
|
|
qPrintable(tsFilename));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
xml.skipCurrentElement();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
xml.skipCurrentElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
xml.skipCurrentElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (xml.hasError()) {
|
|
|
|
retval = false;
|
|
|
|
fprintf(stderr, "ERROR: Encountered error \"%s\" when parsing ts file (%s).\n",
|
|
|
|
qPrintable(xml.errorString()), qPrintable(tsFilename));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
retval = false;
|
|
|
|
fprintf(stderr, "Warning: Could not open ts file (%s).\n", qPrintable(tsFilename));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
retval = false;
|
|
|
|
fprintf(stderr, "Warning: ts file does not exist: (%s), unable to parse it.\n",
|
|
|
|
qPrintable(tsFilename));
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString SymbianCommonGenerator::generatePkgNameForHeader(const SymbianLocalizationList &symbianLocalizationList,
|
|
|
|
const QString &defaultName,
|
|
|
|
bool isForSmartInstaller)
|
|
|
|
{
|
|
|
|
QStringList allNames;
|
|
|
|
QString noTranslation = defaultName;
|
|
|
|
|
|
|
|
if (isForSmartInstaller)
|
|
|
|
noTranslation += QLatin1String(" installer");
|
|
|
|
|
|
|
|
SymbianLocalizationListIterator iter(symbianLocalizationList);
|
|
|
|
while (iter.hasNext()) {
|
|
|
|
const SymbianLocalization &loc = iter.next();
|
|
|
|
QString currentName;
|
|
|
|
if (isForSmartInstaller) {
|
|
|
|
currentName = loc.installerPkgDisplayName;
|
|
|
|
} else {
|
|
|
|
currentName = loc.pkgDisplayName;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentName.isEmpty())
|
|
|
|
currentName = noTranslation;
|
|
|
|
|
|
|
|
allNames << currentName;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!allNames.size())
|
|
|
|
allNames << noTranslation;
|
|
|
|
|
|
|
|
return allNames.join("\",\"");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SymbianCommonGenerator::addLocalizedResourcesToDeployment(const QString &deploymentFilesVar,
|
|
|
|
const SymbianLocalizationList &symbianLocalizationList)
|
|
|
|
{
|
|
|
|
QStringList locResources;
|
|
|
|
foreach (QString defaultResource, generator->project->values(deploymentFilesVar)) {
|
|
|
|
if (defaultResource.endsWith(".rsc")) {
|
|
|
|
defaultResource.chop(2);
|
|
|
|
SymbianLocalizationListIterator iter(symbianLocalizationList);
|
|
|
|
while (iter.hasNext()) {
|
|
|
|
const SymbianLocalization &loc = iter.next();
|
|
|
|
locResources << QString(defaultResource + loc.symbianLanguageCode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
generator->project->values(deploymentFilesVar) << locResources;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString SymbianCommonGenerator::generateLocFileName()
|
|
|
|
{
|
|
|
|
QString fileName(fixedTarget);
|
|
|
|
if (!Option::output_dir.isEmpty())
|
|
|
|
fileName = Option::output_dir + QLatin1Char('/') + fileName;
|
|
|
|
fileName.append(".loc");
|
|
|
|
return fileName;
|
|
|
|
}
|