Source

Target

Commits (7)
Showing with 106 additions and 29 deletions
......@@ -1697,25 +1697,53 @@ bool copyQtFiles(Options *options)
return true;
}
QStringList getLibraryProjectsInOutputFolder(const Options &options)
{
QStringList ret;
QFile file(options.outputDirectory + QLatin1String("/project.properties"));
if (file.open(QIODevice::ReadOnly)) {
while (!file.atEnd()) {
QByteArray line = file.readLine().trimmed();
if (line.startsWith("android.library.reference")) {
int equalSignIndex = line.indexOf('=');
if (equalSignIndex >= 0) {
QString path = QString::fromLocal8Bit(line.mid(equalSignIndex + 1));
QFileInfo info(options.outputDirectory + QLatin1Char('/') + path);
if (QDir::isRelativePath(path)
&& info.exists()
&& info.isDir()
&& info.canonicalFilePath().startsWith(options.outputDirectory)) {
ret += info.canonicalFilePath();
}
}
}
}
}
return ret;
}
bool createAndroidProject(const Options &options)
{
if (options.verbose)
fprintf(stdout, "Running Android tool to create package definition.\n");
QString androidTool = options.sdkPath + QLatin1String("/tools/android");
QString androidToolExecutable = options.sdkPath + QLatin1String("/tools/android");
#if defined(Q_OS_WIN32)
androidTool += QLatin1String(".bat");
androidToolExecutable += QLatin1String(".bat");
#endif
if (!QFile::exists(androidTool)) {
fprintf(stderr, "Cannot find Android tool: %s\n", qPrintable(androidTool));
if (!QFile::exists(androidToolExecutable)) {
fprintf(stderr, "Cannot find Android tool: %s\n", qPrintable(androidToolExecutable));
return false;
}
androidTool = QString::fromLatin1("%1 update project --path %2 --target %3 --name QtApp")
.arg(shellQuote(androidTool))
.arg(shellQuote(options.outputDirectory))
.arg(shellQuote(options.androidPlatform));
QString androidTool = QString::fromLatin1("%1 update project --path %2 --target %3 --name QtApp")
.arg(shellQuote(androidToolExecutable))
.arg(shellQuote(options.outputDirectory))
.arg(shellQuote(options.androidPlatform));
if (options.verbose)
fprintf(stdout, " -- Command: %s\n", qPrintable(androidTool));
......@@ -1728,6 +1756,29 @@ bool createAndroidProject(const Options &options)
pclose(androidToolCommand);
// If the project has subprojects inside the current folder, we need to also run android update on these.
QStringList libraryProjects = getLibraryProjectsInOutputFolder(options);
foreach (QString libraryProject, libraryProjects) {
if (options.verbose)
fprintf(stdout, "Updating subproject %s\n", qPrintable(libraryProject));
androidTool = QString::fromLatin1("%1 update lib-project --path %2 --target %3")
.arg(shellQuote(androidToolExecutable))
.arg(shellQuote(libraryProject))
.arg(shellQuote(options.androidPlatform));
if (options.verbose)
fprintf(stdout, " -- Command: %s\n", qPrintable(androidTool));
FILE *androidToolCommand = popen(androidTool.toLocal8Bit().constData(), "r");
if (androidToolCommand == 0) {
fprintf(stderr, "Cannot run command '%s'\n", qPrintable(androidTool));
return false;
}
pclose(androidToolCommand);
}
return true;
}
......
......@@ -172,13 +172,6 @@ void dumpGlInfo(QTextStream &str, bool listExtensions)
#endif // !QT_NO_OPENGL
static QStringList toNativeSeparators(QStringList in)
{
for (int i = 0; i < in.size(); ++i)
in[i] = QDir::toNativeSeparators(in.at(i));
return in;
}
#define DUMP_CAPABILITY(str, integration, capability) \
if (platformIntegration->hasCapability(QPlatformIntegration::capability)) \
str << ' ' << #capability;
......@@ -243,7 +236,7 @@ QString qtDiag(unsigned flags)
DUMP_LIBRARYPATH(str, ExamplesPath)
DUMP_LIBRARYPATH(str, TestsPath)
str << "\nStandard paths:\n";
str << "\nStandard paths [*...* denote writable entry]:\n";
DUMP_STANDARDPATH(str, DesktopLocation)
DUMP_STANDARDPATH(str, DocumentsLocation)
DUMP_STANDARDPATH(str, FontsLocation)
......@@ -312,7 +305,7 @@ QString qtDiag(unsigned flags)
if (passwordMaskCharacter.unicode() >= 32 && passwordMaskCharacter.unicode() < 128)
str << '\'' << passwordMaskCharacter << '\'';
else
str << hex << showbase << passwordMaskCharacter.unicode() << noshowbase << dec;
str << "U+" << qSetFieldWidth(4) << qSetPadChar('0') << uppercasedigits << hex << passwordMaskCharacter.unicode() << dec << qSetFieldWidth(0);
str << '\n'
<< " fontSmoothingGamma: " << styleHints->fontSmoothingGamma() << '\n'
<< " useRtlExtensions: " << styleHints->useRtlExtensions() << '\n'
......@@ -331,7 +324,7 @@ QString qtDiag(unsigned flags)
str << " General font : " << QFontDatabase::systemFont(QFontDatabase::GeneralFont) << '\n'
<< " Fixed font : " << QFontDatabase::systemFont(QFontDatabase::FixedFont) << '\n'
<< " Title font : " << QFontDatabase::systemFont(QFontDatabase::TitleFont) << '\n'
<< " Smallest font: " << QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont) << "\n\n";
<< " Smallest font: " << QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont) << '\n';
if (platformTheme->usePlatformNativeDialog(QPlatformTheme::FileDialog))
str << " Native file dialog\n";
......@@ -345,9 +338,9 @@ QString qtDiag(unsigned flags)
str << "\nScreens: " << screenCount << '\n';
for (int s = 0; s < screenCount; ++s) {
const QScreen *screen = screens.at(s);
str << (screen == QGuiApplication::primaryScreen() ? '*' : ' ')
<< '#' << ' ' << s << " \"" << screen->name() << '"'
str << '#' << ' ' << s << " \"" << screen->name() << '"'
<< " Depth: " << screen->depth()
<< " Primary: " << (screen == QGuiApplication::primaryScreen() ? "yes" : "no")
<< "\n Geometry: " << screen->geometry() << " Available: " << screen->availableGeometry();
if (screen->geometry() != screen->virtualGeometry())
str << "\n Virtual geometry: " << screen->virtualGeometry() << " Available: " << screen->availableVirtualGeometry();
......
......@@ -571,14 +571,23 @@ private:
// QML import trees: DLLs (matching debgug) and .qml/,js, etc.
class QmlDirectoryFileEntryFunction {
public:
explicit QmlDirectoryFileEntryFunction(Platform platform, bool debug)
: m_qmlNameFilter(QStringList() << QStringLiteral("*.js") << QStringLiteral("qmldir") << QStringLiteral("*.qml") << QStringLiteral("*.qmltypes") << QStringLiteral("*.png"))
explicit QmlDirectoryFileEntryFunction(Platform platform, bool debug, bool skipQmlSources = false)
: m_qmlNameFilter(QmlDirectoryFileEntryFunction::qmlNameFilters(skipQmlSources))
, m_dllFilter(platform, debug)
{}
QStringList operator()(const QDir &dir) const { return m_dllFilter(dir) + m_qmlNameFilter(dir); }
private:
static inline QStringList qmlNameFilters(bool skipQmlSources)
{
QStringList result;
result << QStringLiteral("qmldir") << QStringLiteral("*.qmltypes");
if (!skipQmlSources)
result << QStringLiteral("*.js") << QStringLiteral("*.qml") << QStringLiteral("*.png");
return result;
}
NameFilterFileEntryFunction m_qmlNameFilter;
DllDirectoryFileEntryFunction m_dllFilter;
};
......@@ -1048,7 +1057,14 @@ static DeployResult deploy(const Options &options,
<< QDir::toNativeSeparators(installPath) << '\n';
if (installPath != options.directory && !createDirectory(installPath, errorMessage))
return result;
if (!updateFile(module.sourcePath, qmlFileEntryFunction, installPath, options.updateFileFlags, options.json, errorMessage))
const bool updateResult = module.sourcePath.contains(QLatin1String("QtQuick/Controls"))
|| module.sourcePath.contains(QLatin1String("QtQuick/Dialogs")) ?
updateFile(module.sourcePath, QmlDirectoryFileEntryFunction(options.platform, isDebug, true),
installPath, options.updateFileFlags | RemoveEmptyQmlDirectories,
options.json, errorMessage) :
updateFile(module.sourcePath, qmlFileEntryFunction, installPath, options.updateFileFlags,
options.json, errorMessage);
if (!updateResult)
return result;
}
} // Quick 2
......
......@@ -872,7 +872,7 @@ QString findD3dCompiler(Platform platform, const QString &qtBinDir, unsigned wor
#else // Q_OS_WIN
bool readPeExecutable(const QString &, QString *errorMessage,
QStringList *, unsigned *, bool *)
QStringList *, unsigned *, bool *, bool)
{
*errorMessage = QStringLiteral("Not implemented.");
return false;
......
......@@ -201,7 +201,8 @@ extern int optVerboseLevel;
// to obtain the files.
enum UpdateFileFlag {
ForceUpdateFile = 0x1,
SkipUpdateFile = 0x2
SkipUpdateFile = 0x2,
RemoveEmptyQmlDirectories = 0x4
};
template <class DirectoryFileEntryFunction>
......@@ -257,6 +258,7 @@ bool updateFile(const QString &sourceFileName,
} // Source is symbolic link
if (sourceFileInfo.isDir()) {
bool created = false;
if (targetFileInfo.exists()) {
if (!targetFileInfo.isDir()) {
*errorMessage = QString::fromLatin1("%1 already exists and is not a directory.")
......@@ -267,10 +269,13 @@ bool updateFile(const QString &sourceFileName,
QDir d(targetDirectory);
if (optVerboseLevel)
std::wcout << "Creating " << targetFileName << ".\n";
if (!(flags & SkipUpdateFile) && !d.mkdir(sourceFileInfo.fileName())) {
*errorMessage = QString::fromLatin1("Cannot create directory %1 under %2.")
.arg(sourceFileInfo.fileName(), QDir::toNativeSeparators(targetDirectory));
return false;
if (!(flags & SkipUpdateFile)) {
created = d.mkdir(sourceFileInfo.fileName());
if (!created) {
*errorMessage = QString::fromLatin1("Cannot create directory %1 under %2.")
.arg(sourceFileInfo.fileName(), QDir::toNativeSeparators(targetDirectory));
return false;
}
}
}
// Recurse into directory
......@@ -280,6 +285,18 @@ bool updateFile(const QString &sourceFileName,
foreach (const QString &entry, allEntries)
if (!updateFile(sourceFileName + QLatin1Char('/') + entry, directoryFileEntryFunction, targetFileName, flags, json, errorMessage))
return false;
// Remove empty directories, for example QML import folders for which the filter did not match.
if (created && (flags & RemoveEmptyQmlDirectories)) {
QDir d(targetFileName);
const QStringList entries = d.entryList(QStringList(), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
if (entries.isEmpty() || (entries.size() == 1 && entries.first() == QLatin1String("qmldir"))) {
if (!d.removeRecursively()) {
*errorMessage = QString::fromLatin1("Cannot remove empty directory %1.")
.arg(QDir::toNativeSeparators(targetFileName));
return false;
}
}
}
return true;
} // Source is directory.
......