diff options
Diffstat (limited to 'tools')
52 files changed, 5481 insertions, 1496 deletions
diff --git a/tools/assistant/tools/qcollectiongenerator/main.cpp b/tools/assistant/tools/qcollectiongenerator/main.cpp index 7fcb4e1..b3f6bd9 100644 --- a/tools/assistant/tools/qcollectiongenerator/main.cpp +++ b/tools/assistant/tools/qcollectiongenerator/main.cpp @@ -459,6 +459,8 @@ int main(int argc, char *argv[]) return -1; } } + if (!config.filesToRegister().isEmpty()) + CollectionConfiguration::updateLastRegisterTime(helpEngine); if (!config.title().isEmpty()) CollectionConfiguration::setWindowTitle(helpEngine, config.title()); diff --git a/tools/configure/configure.pro b/tools/configure/configure.pro index 64a6d9a..73f3317 100644 --- a/tools/configure/configure.pro +++ b/tools/configure/configure.pro @@ -23,7 +23,8 @@ win32-msvc* { PRECOMPILED_HEADER = configure_pch.h -INCPATH += $$QT_SOURCE_TREE/src/corelib/arch/generic \ +INCLUDEPATH += \ + $$QT_SOURCE_TREE/src/corelib/arch/generic \ $$QT_SOURCE_TREE/src/corelib/global \ $$QT_BUILD_TREE/include \ $$QT_BUILD_TREE/include/QtCore \ diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index c66eb53..952d4e0 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE -std::ostream &operator<<( std::ostream &s, const QString &val ) { +std::ostream &operator<<(std::ostream &s, const QString &val) { s << val.toLocal8Bit().data(); return s; } @@ -89,7 +89,7 @@ bool writeToFile(const char* text, const QString &filename) return true; } -Configure::Configure( int& argc, char** argv ) +Configure::Configure(int& argc, char** argv) { useUnixSeparators = false; // Default values for indentation @@ -111,7 +111,7 @@ Configure::Configure( int& argc, char** argv ) */ dictionary[ "CONFIGCMD" ] = argv[ 0 ]; - for ( i = 1; i < argc; i++ ) + for (i = 1; i < argc; i++) configCmdLine += argv[ i ]; @@ -127,7 +127,7 @@ Configure::Configure( int& argc, char** argv ) #else const QString installPath = buildPath; #endif - if(sourceDir != buildDir) { //shadow builds! + if (sourceDir != buildDir) { //shadow builds! if (!findFile("perl") && !findFile("perl.exe")) { cout << "Error: Creating a shadow build of Qt requires" << endl << "perl to be in the PATH environment"; @@ -140,37 +140,37 @@ Configure::Configure( int& argc, char** argv ) { //duplicate qmake QStack<QString> qmake_dirs; qmake_dirs.push("qmake"); - while(!qmake_dirs.isEmpty()) { + while (!qmake_dirs.isEmpty()) { QString dir = qmake_dirs.pop(); QString od(buildPath + "/" + dir); QString id(sourcePath + "/" + dir); QFileInfoList entries = QDir(id).entryInfoList(QDir::NoDotAndDotDot|QDir::AllEntries); - for(int i = 0; i < entries.size(); ++i) { + for (int i = 0; i < entries.size(); ++i) { QFileInfo fi(entries.at(i)); - if(fi.isDir()) { + if (fi.isDir()) { qmake_dirs.push(dir + "/" + fi.fileName()); QDir().mkpath(od + "/" + fi.fileName()); } else { - QDir().mkpath(od ); + QDir().mkpath(od); bool justCopy = true; const QString fname = fi.fileName(); const QString outFile(od + "/" + fname), inFile(id + "/" + fname); - if(fi.fileName() == "Makefile") { //ignore - } else if(fi.suffix() == "h" || fi.suffix() == "cpp") { + if (fi.fileName() == "Makefile") { //ignore + } else if (fi.suffix() == "h" || fi.suffix() == "cpp") { QTemporaryFile tmpFile; - if(tmpFile.open()) { + if (tmpFile.open()) { QTextStream stream(&tmpFile); stream << "#include \"" << inFile << "\"" << endl; justCopy = false; stream.flush(); tmpFile.flush(); - if(filesDiffer(tmpFile.fileName(), outFile)) { + if (filesDiffer(tmpFile.fileName(), outFile)) { QFile::remove(outFile); tmpFile.copy(outFile); } } } - if(justCopy && filesDiffer(inFile, outFile)) + if (justCopy && filesDiffer(inFile, outFile)) QFile::copy(inFile, outFile); } } @@ -179,13 +179,13 @@ Configure::Configure( int& argc, char** argv ) { //make a syncqt script(s) that can be used in the shadow QFile syncqt(buildPath + "/bin/syncqt"); - if(syncqt.open(QFile::WriteOnly)) { + if (syncqt.open(QFile::WriteOnly)) { QTextStream stream(&syncqt); stream << "#!/usr/bin/perl -w" << endl << "require \"" << sourcePath + "/bin/syncqt\";" << endl; } QFile syncqt_bat(buildPath + "/bin/syncqt.bat"); - if(syncqt_bat.open(QFile::WriteOnly)) { + if (syncqt_bat.open(QFile::WriteOnly)) { QTextStream stream(&syncqt_bat); stream << "@echo off" << endl << "set QTDIR=" << QDir::toNativeSeparators(sourcePath) << endl @@ -197,26 +197,26 @@ Configure::Configure( int& argc, char** argv ) // make patch_capabilities and createpackage scripts for Symbian that can be used from the shadow build QFile patch_capabilities(buildPath + "/bin/patch_capabilities"); - if(patch_capabilities.open(QFile::WriteOnly)) { + if (patch_capabilities.open(QFile::WriteOnly)) { QTextStream stream(&patch_capabilities); stream << "#!/usr/bin/perl -w" << endl << "require \"" << sourcePath + "/bin/patch_capabilities\";" << endl; } QFile patch_capabilities_bat(buildPath + "/bin/patch_capabilities.bat"); - if(patch_capabilities_bat.open(QFile::WriteOnly)) { + if (patch_capabilities_bat.open(QFile::WriteOnly)) { QTextStream stream(&patch_capabilities_bat); stream << "@echo off" << endl << "call " << fixSeparators(sourcePath) << fixSeparators("/bin/patch_capabilities.bat %*") << endl; patch_capabilities_bat.close(); } QFile createpackage(buildPath + "/bin/createpackage"); - if(createpackage.open(QFile::WriteOnly)) { + if (createpackage.open(QFile::WriteOnly)) { QTextStream stream(&createpackage); stream << "#!/usr/bin/perl -w" << endl << "require \"" << sourcePath + "/bin/createpackage\";" << endl; } QFile createpackage_bat(buildPath + "/bin/createpackage.bat"); - if(createpackage_bat.open(QFile::WriteOnly)) { + if (createpackage_bat.open(QFile::WriteOnly)) { QTextStream stream(&createpackage_bat); stream << "@echo off" << endl << "call " << fixSeparators(sourcePath) << fixSeparators("/bin/createpackage.bat %*") << endl; @@ -228,7 +228,7 @@ Configure::Configure( int& argc, char** argv ) QFile::copy(sourcePath + "/bin/setcepaths.bat" , buildPath + "/bin/setcepaths.bat"); //copy the mkspecs buildDir.mkpath("mkspecs"); - if(!Environment::cpdir(sourcePath + "/mkspecs", buildPath + "/mkspecs")){ + if (!Environment::cpdir(sourcePath + "/mkspecs", buildPath + "/mkspecs")){ cout << "Couldn't copy mkspecs!" << sourcePath << " " << buildPath << endl; dictionary["DONE"] = "error"; return; @@ -304,7 +304,7 @@ Configure::Configure( int& argc, char** argv ) dictionary[ "VERSION" ] = version; { QRegExp version_re("([0-9]*)\\.([0-9]*)\\.([0-9]*)(|-.*)"); - if(version_re.exactMatch(version)) { + if (version_re.exactMatch(version)) { dictionary[ "VERSION_MAJOR" ] = version_re.cap(1); dictionary[ "VERSION_MINOR" ] = version_re.cap(2); dictionary[ "VERSION_PATCH" ] = version_re.cap(3); @@ -372,9 +372,9 @@ Configure::Configure( int& argc, char** argv ) QString tmp = dictionary[ "QMAKESPEC" ]; if (tmp.contains("\\")) { - tmp = tmp.mid( tmp.lastIndexOf( "\\" ) + 1 ); + tmp = tmp.mid(tmp.lastIndexOf("\\") + 1); } else { - tmp = tmp.mid( tmp.lastIndexOf("/") + 1 ); + tmp = tmp.mid(tmp.lastIndexOf("/") + 1); } dictionary[ "QMAKESPEC" ] = tmp; @@ -439,12 +439,12 @@ void Configure::parseCmdLine() #if !defined(EVAL) if (argCount < 1) // skip rest if no arguments ; - else if( configCmdLine.at(i) == "-redo" ) { + else if (configCmdLine.at(i) == "-redo") { dictionary[ "REDO" ] = "yes"; configCmdLine.clear(); reloadCmdLine(); } - else if( configCmdLine.at(i) == "-loadconfig" ) { + else if (configCmdLine.at(i) == "-loadconfig") { ++i; if (i != argCount) { dictionary[ "REDO" ] = "yes"; @@ -460,9 +460,9 @@ void Configure::parseCmdLine() #endif // Look first for XQMAKESPEC - for(int j = 0 ; j < argCount; ++j) + for (int j = 0 ; j < argCount; ++j) { - if( configCmdLine.at(j) == "-xplatform") { + if (configCmdLine.at(j) == "-xplatform") { ++j; if (j == argCount) break; @@ -472,46 +472,46 @@ void Configure::parseCmdLine() } } - for( ; i<configCmdLine.size(); ++i ) { + for (; i<configCmdLine.size(); ++i) { bool continueElse[] = {false, false}; - if( configCmdLine.at(i) == "-help" + if (configCmdLine.at(i) == "-help" || configCmdLine.at(i) == "-h" - || configCmdLine.at(i) == "-?" ) + || configCmdLine.at(i) == "-?") dictionary[ "HELP" ] = "yes"; #if !defined(EVAL) - else if( configCmdLine.at(i) == "-qconfig" ) { + else if (configCmdLine.at(i) == "-qconfig") { ++i; - if (i==argCount) + if (i == argCount) break; dictionary[ "QCONFIG" ] = configCmdLine.at(i); } - else if ( configCmdLine.at(i) == "-buildkey" ) { + else if (configCmdLine.at(i) == "-buildkey") { ++i; - if (i==argCount) + if (i == argCount) break; dictionary[ "USER_BUILD_KEY" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-release" ) { + else if (configCmdLine.at(i) == "-release") { dictionary[ "BUILD" ] = "release"; if (dictionary[ "BUILDALL" ] == "auto") dictionary[ "BUILDALL" ] = "no"; - } else if( configCmdLine.at(i) == "-debug" ) { + } else if (configCmdLine.at(i) == "-debug") { dictionary[ "BUILD" ] = "debug"; if (dictionary[ "BUILDALL" ] == "auto") dictionary[ "BUILDALL" ] = "no"; - } else if( configCmdLine.at(i) == "-debug-and-release" ) + } else if (configCmdLine.at(i) == "-debug-and-release") dictionary[ "BUILDALL" ] = "yes"; - else if( configCmdLine.at(i) == "-shared" ) + else if (configCmdLine.at(i) == "-shared") dictionary[ "SHARED" ] = "yes"; - else if( configCmdLine.at(i) == "-static" ) + else if (configCmdLine.at(i) == "-static") dictionary[ "SHARED" ] = "no"; - else if( configCmdLine.at(i) == "-developer-build" ) + else if (configCmdLine.at(i) == "-developer-build") dictionary[ "BUILDDEV" ] = "yes"; - else if( configCmdLine.at(i) == "-nokia-developer" ) { + else if (configCmdLine.at(i) == "-nokia-developer") { cout << "Detected -nokia-developer option" << endl; cout << "Nokia employees and agents are allowed to use this software under" << endl; cout << "the authority of Nokia Corporation and/or its subsidiary(-ies)" << endl; @@ -522,45 +522,45 @@ void Configure::parseCmdLine() dictionary[ "SYMBIAN_DEFFILES" ] = "no"; } } - else if( configCmdLine.at(i) == "-opensource" ) { + else if (configCmdLine.at(i) == "-opensource") { dictionary[ "BUILDTYPE" ] = "opensource"; } - else if( configCmdLine.at(i) == "-commercial" ) { + else if (configCmdLine.at(i) == "-commercial") { dictionary[ "BUILDTYPE" ] = "commercial"; } - else if( configCmdLine.at(i) == "-ltcg" ) { + else if (configCmdLine.at(i) == "-ltcg") { dictionary[ "LTCG" ] = "yes"; } - else if( configCmdLine.at(i) == "-no-ltcg" ) { + else if (configCmdLine.at(i) == "-no-ltcg") { dictionary[ "LTCG" ] = "no"; } #endif - else if( configCmdLine.at(i) == "-platform" ) { + else if (configCmdLine.at(i) == "-platform") { ++i; - if (i==argCount) + if (i == argCount) break; dictionary[ "QMAKESPEC" ] = configCmdLine.at(i); dictionary[ "QMAKESPEC_FROM" ] = "commandline"; - } else if( configCmdLine.at(i) == "-arch" ) { + } else if (configCmdLine.at(i) == "-arch") { ++i; - if (i==argCount) + if (i == argCount) break; dictionary[ "ARCHITECTURE" ] = configCmdLine.at(i); if (configCmdLine.at(i) == "boundschecker") { dictionary[ "ARCHITECTURE" ] = "generic"; // Boundschecker uses the generic arch, qtConfig += "boundschecker"; // but also needs this CONFIG option } - } else if( configCmdLine.at(i) == "-embedded" ) { + } else if (configCmdLine.at(i) == "-embedded") { dictionary[ "EMBEDDED" ] = "yes"; - } else if( configCmdLine.at(i) == "-xplatform") { + } else if (configCmdLine.at(i) == "-xplatform") { ++i; // do nothing } #if !defined(EVAL) - else if( configCmdLine.at(i) == "-no-zlib" ) { + else if (configCmdLine.at(i) == "-no-zlib") { // No longer supported since Qt 4.4.0 // But save the information for later so that we can print a warning // @@ -572,72 +572,62 @@ void Configure::parseCmdLine() // There's no guarantee that Qt will build under those conditions dictionary[ "ZLIB_FORCED" ] = "yes"; - } else if( configCmdLine.at(i) == "-qt-zlib" ) { + } else if (configCmdLine.at(i) == "-qt-zlib") { dictionary[ "ZLIB" ] = "qt"; - } else if( configCmdLine.at(i) == "-system-zlib" ) { + } else if (configCmdLine.at(i) == "-system-zlib") { dictionary[ "ZLIB" ] = "system"; } // Image formats -------------------------------------------- - else if( configCmdLine.at(i) == "-no-gif" ) + else if (configCmdLine.at(i) == "-no-gif") dictionary[ "GIF" ] = "no"; - else if( configCmdLine.at(i) == "-qt-gif" ) - dictionary[ "GIF" ] = "auto"; - - else if( configCmdLine.at(i) == "-no-libtiff" ) { - dictionary[ "TIFF"] = "no"; - dictionary[ "LIBTIFF" ] = "no"; - } else if( configCmdLine.at(i) == "-qt-libtiff" ) { - dictionary[ "TIFF" ] = "plugin"; + + else if (configCmdLine.at(i) == "-no-libtiff") { + dictionary[ "TIFF"] = "no"; + dictionary[ "LIBTIFF" ] = "no"; + } else if (configCmdLine.at(i) == "-qt-libtiff") { dictionary[ "LIBTIFF" ] = "qt"; - } else if( configCmdLine.at(i) == "-system-libtiff" ) { - dictionary[ "TIFF" ] = "plugin"; - dictionary[ "LIBTIFF" ] = "system"; + } else if (configCmdLine.at(i) == "-system-libtiff") { + dictionary[ "LIBTIFF" ] = "system"; } - else if( configCmdLine.at(i) == "-no-libjpeg" ) { + else if (configCmdLine.at(i) == "-no-libjpeg") { dictionary[ "JPEG" ] = "no"; dictionary[ "LIBJPEG" ] = "no"; - } else if( configCmdLine.at(i) == "-qt-libjpeg" ) { - dictionary[ "JPEG" ] = "plugin"; + } else if (configCmdLine.at(i) == "-qt-libjpeg") { dictionary[ "LIBJPEG" ] = "qt"; - } else if( configCmdLine.at(i) == "-system-libjpeg" ) { - dictionary[ "JPEG" ] = "plugin"; + } else if (configCmdLine.at(i) == "-system-libjpeg") { dictionary[ "LIBJPEG" ] = "system"; } - else if( configCmdLine.at(i) == "-no-libpng" ) { + else if (configCmdLine.at(i) == "-no-libpng") { dictionary[ "PNG" ] = "no"; dictionary[ "LIBPNG" ] = "no"; - } else if( configCmdLine.at(i) == "-qt-libpng" ) { - dictionary[ "PNG" ] = "qt"; + } else if (configCmdLine.at(i) == "-qt-libpng") { dictionary[ "LIBPNG" ] = "qt"; - } else if( configCmdLine.at(i) == "-system-libpng" ) { - dictionary[ "PNG" ] = "qt"; + } else if (configCmdLine.at(i) == "-system-libpng") { dictionary[ "LIBPNG" ] = "system"; } - else if( configCmdLine.at(i) == "-no-libmng" ) { + else if (configCmdLine.at(i) == "-no-libmng") { dictionary[ "MNG" ] = "no"; dictionary[ "LIBMNG" ] = "no"; - } else if( configCmdLine.at(i) == "-qt-libmng" ) { - dictionary[ "MNG" ] = "qt"; + } else if (configCmdLine.at(i) == "-qt-libmng") { dictionary[ "LIBMNG" ] = "qt"; - } else if( configCmdLine.at(i) == "-system-libmng" ) { - dictionary[ "MNG" ] = "qt"; + } else if (configCmdLine.at(i) == "-system-libmng") { dictionary[ "LIBMNG" ] = "system"; } // Text Rendering -------------------------------------------- - else if( configCmdLine.at(i) == "-no-freetype" ) + else if (configCmdLine.at(i) == "-no-freetype") dictionary[ "FREETYPE" ] = "no"; - else if( configCmdLine.at(i) == "-qt-freetype" ) + else if (configCmdLine.at(i) == "-qt-freetype") dictionary[ "FREETYPE" ] = "yes"; // CE- C runtime -------------------------------------------- - else if( configCmdLine.at(i) == "-crt" ) { + else if (configCmdLine.at(i) == "-crt") { ++i; - if (i==argCount) + if (i == argCount) break; QDir cDir(configCmdLine.at(i)); if (!cDir.exists()) @@ -661,9 +651,9 @@ void Configure::parseCmdLine() dictionary[ "CETEST_REQUESTED" ] = "yes"; } // Qt/CE - signing tool ------------------------------------- - else if( configCmdLine.at(i) == "-signature") { + else if (configCmdLine.at(i) == "-signature") { ++i; - if (i==argCount) + if (i == argCount) break; QFileInfo info(configCmdLine.at(i)); if (!info.exists()) @@ -672,57 +662,57 @@ void Configure::parseCmdLine() dictionary[ "CE_SIGNATURE" ] = QDir::toNativeSeparators(info.absoluteFilePath()); } // Styles --------------------------------------------------- - else if( configCmdLine.at(i) == "-qt-style-windows" ) + else if (configCmdLine.at(i) == "-qt-style-windows") dictionary[ "STYLE_WINDOWS" ] = "yes"; - else if( configCmdLine.at(i) == "-no-style-windows" ) + else if (configCmdLine.at(i) == "-no-style-windows") dictionary[ "STYLE_WINDOWS" ] = "no"; - else if( configCmdLine.at(i) == "-qt-style-windowsce" ) + else if (configCmdLine.at(i) == "-qt-style-windowsce") dictionary[ "STYLE_WINDOWSCE" ] = "yes"; - else if( configCmdLine.at(i) == "-no-style-windowsce" ) + else if (configCmdLine.at(i) == "-no-style-windowsce") dictionary[ "STYLE_WINDOWSCE" ] = "no"; - else if( configCmdLine.at(i) == "-qt-style-windowsmobile" ) + else if (configCmdLine.at(i) == "-qt-style-windowsmobile") dictionary[ "STYLE_WINDOWSMOBILE" ] = "yes"; - else if( configCmdLine.at(i) == "-no-style-windowsmobile" ) + else if (configCmdLine.at(i) == "-no-style-windowsmobile") dictionary[ "STYLE_WINDOWSMOBILE" ] = "no"; - else if( configCmdLine.at(i) == "-qt-style-windowsxp" ) + else if (configCmdLine.at(i) == "-qt-style-windowsxp") dictionary[ "STYLE_WINDOWSXP" ] = "yes"; - else if( configCmdLine.at(i) == "-no-style-windowsxp" ) + else if (configCmdLine.at(i) == "-no-style-windowsxp") dictionary[ "STYLE_WINDOWSXP" ] = "no"; - else if( configCmdLine.at(i) == "-qt-style-windowsvista" ) + else if (configCmdLine.at(i) == "-qt-style-windowsvista") dictionary[ "STYLE_WINDOWSVISTA" ] = "yes"; - else if( configCmdLine.at(i) == "-no-style-windowsvista" ) + else if (configCmdLine.at(i) == "-no-style-windowsvista") dictionary[ "STYLE_WINDOWSVISTA" ] = "no"; - else if( configCmdLine.at(i) == "-qt-style-plastique" ) + else if (configCmdLine.at(i) == "-qt-style-plastique") dictionary[ "STYLE_PLASTIQUE" ] = "yes"; - else if( configCmdLine.at(i) == "-no-style-plastique" ) + else if (configCmdLine.at(i) == "-no-style-plastique") dictionary[ "STYLE_PLASTIQUE" ] = "no"; - else if( configCmdLine.at(i) == "-qt-style-cleanlooks" ) + else if (configCmdLine.at(i) == "-qt-style-cleanlooks") dictionary[ "STYLE_CLEANLOOKS" ] = "yes"; - else if( configCmdLine.at(i) == "-no-style-cleanlooks" ) + else if (configCmdLine.at(i) == "-no-style-cleanlooks") dictionary[ "STYLE_CLEANLOOKS" ] = "no"; - else if( configCmdLine.at(i) == "-qt-style-motif" ) + else if (configCmdLine.at(i) == "-qt-style-motif") dictionary[ "STYLE_MOTIF" ] = "yes"; - else if( configCmdLine.at(i) == "-no-style-motif" ) + else if (configCmdLine.at(i) == "-no-style-motif") dictionary[ "STYLE_MOTIF" ] = "no"; - else if( configCmdLine.at(i) == "-qt-style-cde" ) + else if (configCmdLine.at(i) == "-qt-style-cde") dictionary[ "STYLE_CDE" ] = "yes"; - else if( configCmdLine.at(i) == "-no-style-cde" ) + else if (configCmdLine.at(i) == "-no-style-cde") dictionary[ "STYLE_CDE" ] = "no"; - else if( configCmdLine.at(i) == "-qt-style-s60" ) + else if (configCmdLine.at(i) == "-qt-style-s60") dictionary[ "STYLE_S60" ] = "yes"; - else if( configCmdLine.at(i) == "-no-style-s60" ) + else if (configCmdLine.at(i) == "-no-style-s60") dictionary[ "STYLE_S60" ] = "no"; // Qt 3 Support --------------------------------------------- - else if( configCmdLine.at(i) == "-no-qt3support" ) + else if (configCmdLine.at(i) == "-no-qt3support") dictionary[ "QT3SUPPORT" ] = "no"; // Work around compiler nesting limitation @@ -732,156 +722,156 @@ void Configure::parseCmdLine() } // OpenGL Support ------------------------------------------- - else if( configCmdLine.at(i) == "-no-opengl" ) { + else if (configCmdLine.at(i) == "-no-opengl") { dictionary[ "OPENGL" ] = "no"; - } else if ( configCmdLine.at(i) == "-opengl-es-cm" ) { + } else if (configCmdLine.at(i) == "-opengl-es-cm") { dictionary[ "OPENGL" ] = "yes"; dictionary[ "OPENGL_ES_CM" ] = "yes"; - } else if ( configCmdLine.at(i) == "-opengl-es-2" ) { + } else if (configCmdLine.at(i) == "-opengl-es-2") { dictionary[ "OPENGL" ] = "yes"; dictionary[ "OPENGL_ES_2" ] = "yes"; } // OpenVG Support ------------------------------------------- - else if( configCmdLine.at(i) == "-openvg" ) { + else if (configCmdLine.at(i) == "-openvg") { dictionary[ "OPENVG" ] = "yes"; - } else if( configCmdLine.at(i) == "-no-openvg" ) { + } else if (configCmdLine.at(i) == "-no-openvg") { dictionary[ "OPENVG" ] = "no"; } // Databases ------------------------------------------------ - else if( configCmdLine.at(i) == "-qt-sql-mysql" ) + else if (configCmdLine.at(i) == "-qt-sql-mysql") dictionary[ "SQL_MYSQL" ] = "yes"; - else if( configCmdLine.at(i) == "-plugin-sql-mysql" ) + else if (configCmdLine.at(i) == "-plugin-sql-mysql") dictionary[ "SQL_MYSQL" ] = "plugin"; - else if( configCmdLine.at(i) == "-no-sql-mysql" ) + else if (configCmdLine.at(i) == "-no-sql-mysql") dictionary[ "SQL_MYSQL" ] = "no"; - else if( configCmdLine.at(i) == "-qt-sql-odbc" ) + else if (configCmdLine.at(i) == "-qt-sql-odbc") dictionary[ "SQL_ODBC" ] = "yes"; - else if( configCmdLine.at(i) == "-plugin-sql-odbc" ) + else if (configCmdLine.at(i) == "-plugin-sql-odbc") dictionary[ "SQL_ODBC" ] = "plugin"; - else if( configCmdLine.at(i) == "-no-sql-odbc" ) + else if (configCmdLine.at(i) == "-no-sql-odbc") dictionary[ "SQL_ODBC" ] = "no"; - else if( configCmdLine.at(i) == "-qt-sql-oci" ) + else if (configCmdLine.at(i) == "-qt-sql-oci") dictionary[ "SQL_OCI" ] = "yes"; - else if( configCmdLine.at(i) == "-plugin-sql-oci" ) + else if (configCmdLine.at(i) == "-plugin-sql-oci") dictionary[ "SQL_OCI" ] = "plugin"; - else if( configCmdLine.at(i) == "-no-sql-oci" ) + else if (configCmdLine.at(i) == "-no-sql-oci") dictionary[ "SQL_OCI" ] = "no"; - else if( configCmdLine.at(i) == "-qt-sql-psql" ) + else if (configCmdLine.at(i) == "-qt-sql-psql") dictionary[ "SQL_PSQL" ] = "yes"; - else if( configCmdLine.at(i) == "-plugin-sql-psql" ) + else if (configCmdLine.at(i) == "-plugin-sql-psql") dictionary[ "SQL_PSQL" ] = "plugin"; - else if( configCmdLine.at(i) == "-no-sql-psql" ) + else if (configCmdLine.at(i) == "-no-sql-psql") dictionary[ "SQL_PSQL" ] = "no"; - else if( configCmdLine.at(i) == "-qt-sql-tds" ) + else if (configCmdLine.at(i) == "-qt-sql-tds") dictionary[ "SQL_TDS" ] = "yes"; - else if( configCmdLine.at(i) == "-plugin-sql-tds" ) + else if (configCmdLine.at(i) == "-plugin-sql-tds") dictionary[ "SQL_TDS" ] = "plugin"; - else if( configCmdLine.at(i) == "-no-sql-tds" ) + else if (configCmdLine.at(i) == "-no-sql-tds") dictionary[ "SQL_TDS" ] = "no"; - else if( configCmdLine.at(i) == "-qt-sql-db2" ) + else if (configCmdLine.at(i) == "-qt-sql-db2") dictionary[ "SQL_DB2" ] = "yes"; - else if( configCmdLine.at(i) == "-plugin-sql-db2" ) + else if (configCmdLine.at(i) == "-plugin-sql-db2") dictionary[ "SQL_DB2" ] = "plugin"; - else if( configCmdLine.at(i) == "-no-sql-db2" ) + else if (configCmdLine.at(i) == "-no-sql-db2") dictionary[ "SQL_DB2" ] = "no"; - else if( configCmdLine.at(i) == "-qt-sql-sqlite" ) + else if (configCmdLine.at(i) == "-qt-sql-sqlite") dictionary[ "SQL_SQLITE" ] = "yes"; - else if( configCmdLine.at(i) == "-plugin-sql-sqlite" ) + else if (configCmdLine.at(i) == "-plugin-sql-sqlite") dictionary[ "SQL_SQLITE" ] = "plugin"; - else if( configCmdLine.at(i) == "-no-sql-sqlite" ) + else if (configCmdLine.at(i) == "-no-sql-sqlite") dictionary[ "SQL_SQLITE" ] = "no"; - else if( configCmdLine.at(i) == "-system-sqlite" ) + else if (configCmdLine.at(i) == "-system-sqlite") dictionary[ "SQL_SQLITE_LIB" ] = "system"; - else if( configCmdLine.at(i) == "-qt-sql-sqlite2" ) + else if (configCmdLine.at(i) == "-qt-sql-sqlite2") dictionary[ "SQL_SQLITE2" ] = "yes"; - else if( configCmdLine.at(i) == "-plugin-sql-sqlite2" ) + else if (configCmdLine.at(i) == "-plugin-sql-sqlite2") dictionary[ "SQL_SQLITE2" ] = "plugin"; - else if( configCmdLine.at(i) == "-no-sql-sqlite2" ) + else if (configCmdLine.at(i) == "-no-sql-sqlite2") dictionary[ "SQL_SQLITE2" ] = "no"; - else if( configCmdLine.at(i) == "-qt-sql-ibase" ) + else if (configCmdLine.at(i) == "-qt-sql-ibase") dictionary[ "SQL_IBASE" ] = "yes"; - else if( configCmdLine.at(i) == "-plugin-sql-ibase" ) + else if (configCmdLine.at(i) == "-plugin-sql-ibase") dictionary[ "SQL_IBASE" ] = "plugin"; - else if( configCmdLine.at(i) == "-no-sql-ibase" ) + else if (configCmdLine.at(i) == "-no-sql-ibase") dictionary[ "SQL_IBASE" ] = "no"; #endif // IDE project generation ----------------------------------- - else if( configCmdLine.at(i) == "-no-dsp" ) + else if (configCmdLine.at(i) == "-no-dsp") dictionary[ "DSPFILES" ] = "no"; - else if( configCmdLine.at(i) == "-dsp" ) + else if (configCmdLine.at(i) == "-dsp") dictionary[ "DSPFILES" ] = "yes"; - else if( configCmdLine.at(i) == "-no-vcp" ) + else if (configCmdLine.at(i) == "-no-vcp") dictionary[ "VCPFILES" ] = "no"; - else if( configCmdLine.at(i) == "-vcp" ) + else if (configCmdLine.at(i) == "-vcp") dictionary[ "VCPFILES" ] = "yes"; - else if( configCmdLine.at(i) == "-no-vcproj" ) + else if (configCmdLine.at(i) == "-no-vcproj") dictionary[ "VCPROJFILES" ] = "no"; - else if( configCmdLine.at(i) == "-vcproj" ) + else if (configCmdLine.at(i) == "-vcproj") dictionary[ "VCPROJFILES" ] = "yes"; - else if( configCmdLine.at(i) == "-no-incredibuild-xge" ) + else if (configCmdLine.at(i) == "-no-incredibuild-xge") dictionary[ "INCREDIBUILD_XGE" ] = "no"; - else if( configCmdLine.at(i) == "-incredibuild-xge" ) + else if (configCmdLine.at(i) == "-incredibuild-xge") dictionary[ "INCREDIBUILD_XGE" ] = "yes"; - else if( configCmdLine.at(i) == "-native-gestures" ) + else if (configCmdLine.at(i) == "-native-gestures") dictionary[ "NATIVE_GESTURES" ] = "yes"; - else if( configCmdLine.at(i) == "-no-native-gestures" ) + else if (configCmdLine.at(i) == "-no-native-gestures") dictionary[ "NATIVE_GESTURES" ] = "no"; #if !defined(EVAL) // Symbian Support ------------------------------------------- - else if (configCmdLine.at(i) == "-fpu" ) + else if (configCmdLine.at(i) == "-fpu") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "ARM_FPU_TYPE" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-s60" ) + else if (configCmdLine.at(i) == "-s60") dictionary[ "S60" ] = "yes"; - else if( configCmdLine.at(i) == "-no-s60" ) + else if (configCmdLine.at(i) == "-no-s60") dictionary[ "S60" ] = "no"; - else if( configCmdLine.at(i) == "-usedeffiles" ) + else if (configCmdLine.at(i) == "-usedeffiles") dictionary[ "SYMBIAN_DEFFILES" ] = "yes"; - else if( configCmdLine.at(i) == "-no-usedeffiles" ) + else if (configCmdLine.at(i) == "-no-usedeffiles") dictionary[ "SYMBIAN_DEFFILES" ] = "no"; // Others --------------------------------------------------- - else if (configCmdLine.at(i) == "-fast" ) + else if (configCmdLine.at(i) == "-fast") dictionary[ "FAST" ] = "yes"; - else if (configCmdLine.at(i) == "-no-fast" ) + else if (configCmdLine.at(i) == "-no-fast") dictionary[ "FAST" ] = "no"; - else if( configCmdLine.at(i) == "-stl" ) + else if (configCmdLine.at(i) == "-stl") dictionary[ "STL" ] = "yes"; - else if( configCmdLine.at(i) == "-no-stl" ) + else if (configCmdLine.at(i) == "-no-stl") dictionary[ "STL" ] = "no"; - else if ( configCmdLine.at(i) == "-exceptions" ) + else if (configCmdLine.at(i) == "-exceptions") dictionary[ "EXCEPTIONS" ] = "yes"; - else if ( configCmdLine.at(i) == "-no-exceptions" ) + else if (configCmdLine.at(i) == "-no-exceptions") dictionary[ "EXCEPTIONS" ] = "no"; - else if ( configCmdLine.at(i) == "-rtti" ) + else if (configCmdLine.at(i) == "-rtti") dictionary[ "RTTI" ] = "yes"; - else if ( configCmdLine.at(i) == "-no-rtti" ) + else if (configCmdLine.at(i) == "-no-rtti") dictionary[ "RTTI" ] = "no"; - else if( configCmdLine.at(i) == "-accessibility" ) + else if (configCmdLine.at(i) == "-accessibility") dictionary[ "ACCESSIBILITY" ] = "yes"; - else if( configCmdLine.at(i) == "-no-accessibility" ) { + else if (configCmdLine.at(i) == "-no-accessibility") { dictionary[ "ACCESSIBILITY" ] = "no"; cout << "Setting accessibility to NO" << endl; } @@ -907,63 +897,63 @@ void Configure::parseCmdLine() else if (configCmdLine.at(i) == "-iwmmxt") dictionary[ "IWMMXT" ] = "yes"; - else if( configCmdLine.at(i) == "-no-openssl" ) { + else if (configCmdLine.at(i) == "-no-openssl") { dictionary[ "OPENSSL"] = "no"; - } else if( configCmdLine.at(i) == "-openssl" ) { + } else if (configCmdLine.at(i) == "-openssl") { dictionary[ "OPENSSL" ] = "yes"; - } else if( configCmdLine.at(i) == "-openssl-linked" ) { + } else if (configCmdLine.at(i) == "-openssl-linked") { dictionary[ "OPENSSL" ] = "linked"; - } else if( configCmdLine.at(i) == "-no-qdbus" ) { + } else if (configCmdLine.at(i) == "-no-qdbus") { dictionary[ "DBUS" ] = "no"; - } else if( configCmdLine.at(i) == "-qdbus" ) { + } else if (configCmdLine.at(i) == "-qdbus") { dictionary[ "DBUS" ] = "yes"; - } else if( configCmdLine.at(i) == "-no-dbus" ) { + } else if (configCmdLine.at(i) == "-no-dbus") { dictionary[ "DBUS" ] = "no"; - } else if( configCmdLine.at(i) == "-dbus" ) { + } else if (configCmdLine.at(i) == "-dbus") { dictionary[ "DBUS" ] = "yes"; - } else if( configCmdLine.at(i) == "-dbus-linked" ) { + } else if (configCmdLine.at(i) == "-dbus-linked") { dictionary[ "DBUS" ] = "linked"; - } else if( configCmdLine.at(i) == "-no-script" ) { + } else if (configCmdLine.at(i) == "-no-script") { dictionary[ "SCRIPT" ] = "no"; - } else if( configCmdLine.at(i) == "-script" ) { + } else if (configCmdLine.at(i) == "-script") { dictionary[ "SCRIPT" ] = "yes"; - } else if( configCmdLine.at(i) == "-no-scripttools" ) { + } else if (configCmdLine.at(i) == "-no-scripttools") { dictionary[ "SCRIPTTOOLS" ] = "no"; - } else if( configCmdLine.at(i) == "-scripttools" ) { + } else if (configCmdLine.at(i) == "-scripttools") { dictionary[ "SCRIPTTOOLS" ] = "yes"; - } else if( configCmdLine.at(i) == "-no-xmlpatterns" ) { + } else if (configCmdLine.at(i) == "-no-xmlpatterns") { dictionary[ "XMLPATTERNS" ] = "no"; - } else if( configCmdLine.at(i) == "-xmlpatterns" ) { + } else if (configCmdLine.at(i) == "-xmlpatterns") { dictionary[ "XMLPATTERNS" ] = "yes"; - } else if( configCmdLine.at(i) == "-no-multimedia" ) { + } else if (configCmdLine.at(i) == "-no-multimedia") { dictionary[ "MULTIMEDIA" ] = "no"; - } else if( configCmdLine.at(i) == "-multimedia" ) { + } else if (configCmdLine.at(i) == "-multimedia") { dictionary[ "MULTIMEDIA" ] = "yes"; - } else if( configCmdLine.at(i) == "-audio-backend" ) { + } else if (configCmdLine.at(i) == "-audio-backend") { dictionary[ "AUDIO_BACKEND" ] = "yes"; - } else if( configCmdLine.at(i) == "-no-audio-backend" ) { + } else if (configCmdLine.at(i) == "-no-audio-backend") { dictionary[ "AUDIO_BACKEND" ] = "no"; - } else if( configCmdLine.at(i) == "-no-phonon" ) { + } else if (configCmdLine.at(i) == "-no-phonon") { dictionary[ "PHONON" ] = "no"; - } else if( configCmdLine.at(i) == "-phonon" ) { + } else if (configCmdLine.at(i) == "-phonon") { dictionary[ "PHONON" ] = "yes"; - } else if( configCmdLine.at(i) == "-no-phonon-backend" ) { + } else if (configCmdLine.at(i) == "-no-phonon-backend") { dictionary[ "PHONON_BACKEND" ] = "no"; - } else if( configCmdLine.at(i) == "-phonon-backend" ) { + } else if (configCmdLine.at(i) == "-phonon-backend") { dictionary[ "PHONON_BACKEND" ] = "yes"; - } else if( configCmdLine.at(i) == "-phonon-wince-ds9" ) { + } else if (configCmdLine.at(i) == "-phonon-wince-ds9") { dictionary[ "DIRECTSHOW" ] = "yes"; - } else if( configCmdLine.at(i) == "-no-webkit" ) { + } else if (configCmdLine.at(i) == "-no-webkit") { dictionary[ "WEBKIT" ] = "no"; - } else if( configCmdLine.at(i) == "-webkit" ) { + } else if (configCmdLine.at(i) == "-webkit") { dictionary[ "WEBKIT" ] = "yes"; - } else if( configCmdLine.at(i) == "-no-declarative" ) { + } else if (configCmdLine.at(i) == "-no-declarative") { dictionary[ "DECLARATIVE" ] = "no"; - } else if( configCmdLine.at(i) == "-declarative" ) { + } else if (configCmdLine.at(i) == "-declarative") { dictionary[ "DECLARATIVE" ] = "yes"; - } else if( configCmdLine.at(i) == "-no-plugin-manifests" ) { + } else if (configCmdLine.at(i) == "-no-plugin-manifests") { dictionary[ "PLUGIN_MANIFESTS" ] = "no"; - } else if( configCmdLine.at(i) == "-plugin-manifests" ) { + } else if (configCmdLine.at(i) == "-plugin-manifests") { dictionary[ "PLUGIN_MANIFESTS" ] = "yes"; } @@ -973,53 +963,53 @@ void Configure::parseCmdLine() if (!continueElse[0]) { } - else if( configCmdLine.at(i) == "-internal" ) + else if (configCmdLine.at(i) == "-internal") dictionary[ "QMAKE_INTERNAL" ] = "yes"; - else if( configCmdLine.at(i) == "-no-qmake" ) + else if (configCmdLine.at(i) == "-no-qmake") dictionary[ "BUILD_QMAKE" ] = "no"; - else if( configCmdLine.at(i) == "-qmake" ) + else if (configCmdLine.at(i) == "-qmake") dictionary[ "BUILD_QMAKE" ] = "yes"; - else if( configCmdLine.at(i) == "-dont-process" ) + else if (configCmdLine.at(i) == "-dont-process") dictionary[ "NOPROCESS" ] = "yes"; - else if( configCmdLine.at(i) == "-process" ) + else if (configCmdLine.at(i) == "-process") dictionary[ "NOPROCESS" ] = "no"; - else if( configCmdLine.at(i) == "-no-qmake-deps" ) + else if (configCmdLine.at(i) == "-no-qmake-deps") dictionary[ "DEPENDENCIES" ] = "no"; - else if( configCmdLine.at(i) == "-qmake-deps" ) + else if (configCmdLine.at(i) == "-qmake-deps") dictionary[ "DEPENDENCIES" ] = "yes"; - else if( configCmdLine.at(i) == "-qtnamespace" ) { + else if (configCmdLine.at(i) == "-qtnamespace") { ++i; - if(i==argCount) + if (i == argCount) break; qmakeDefines += "QT_NAMESPACE="+configCmdLine.at(i); dictionary[ "QT_NAMESPACE" ] = configCmdLine.at(i); - } else if( configCmdLine.at(i) == "-qtlibinfix" ) { + } else if (configCmdLine.at(i) == "-qtlibinfix") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "QT_LIBINFIX" ] = configCmdLine.at(i); if (dictionary.contains("XQMAKESPEC") && dictionary["XQMAKESPEC"].startsWith("symbian")) { dictionary[ "QT_INSTALL_PLUGINS" ] = QString("\\resource\\qt%1\\plugins").arg(dictionary[ "QT_LIBINFIX" ]); } - } else if( configCmdLine.at(i) == "-D" ) { + } else if (configCmdLine.at(i) == "-D") { ++i; - if (i==argCount) + if (i == argCount) break; qmakeDefines += configCmdLine.at(i); - } else if( configCmdLine.at(i) == "-I" ) { + } else if (configCmdLine.at(i) == "-I") { ++i; - if (i==argCount) + if (i == argCount) break; qmakeIncludes += configCmdLine.at(i); - } else if( configCmdLine.at(i) == "-L" ) { + } else if (configCmdLine.at(i) == "-L") { ++i; - if (i==argCount) + if (i == argCount) break; QFileInfo check(configCmdLine.at(i)); if (!check.isDir()) { @@ -1028,9 +1018,9 @@ void Configure::parseCmdLine() break; } qmakeLibs += QString("-L" + configCmdLine.at(i)); - } else if( configCmdLine.at(i) == "-l" ) { + } else if (configCmdLine.at(i) == "-l") { ++i; - if (i==argCount) + if (i == argCount) break; qmakeLibs += QString("-l" + configCmdLine.at(i)); } else if (configCmdLine.at(i).startsWith("OPENSSL_LIBS=")) { @@ -1039,16 +1029,16 @@ void Configure::parseCmdLine() psqlLibs = configCmdLine.at(i); } - else if( ( configCmdLine.at(i) == "-override-version" ) || ( configCmdLine.at(i) == "-version-override" ) ){ + else if ((configCmdLine.at(i) == "-override-version") || (configCmdLine.at(i) == "-version-override")){ ++i; - if (i==argCount) + if (i == argCount) break; dictionary[ "VERSION" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-saveconfig" ) { + else if (configCmdLine.at(i) == "-saveconfig") { ++i; - if (i==argCount) + if (i == argCount) break; dictionary[ "CUSTOMCONFIG" ] = "_" + configCmdLine.at(i); } @@ -1059,98 +1049,98 @@ void Configure::parseCmdLine() else if (configCmdLine.at(i) == "-nomake") { ++i; - if (i==argCount) + if (i == argCount) break; disabledBuildParts += configCmdLine.at(i); } // Directories ---------------------------------------------- - else if( configCmdLine.at(i) == "-prefix" ) { + else if (configCmdLine.at(i) == "-prefix") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "QT_INSTALL_PREFIX" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-bindir" ) { + else if (configCmdLine.at(i) == "-bindir") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "QT_INSTALL_BINS" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-libdir" ) { + else if (configCmdLine.at(i) == "-libdir") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "QT_INSTALL_LIBS" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-docdir" ) { + else if (configCmdLine.at(i) == "-docdir") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "QT_INSTALL_DOCS" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-headerdir" ) { + else if (configCmdLine.at(i) == "-headerdir") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "QT_INSTALL_HEADERS" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-plugindir" ) { + else if (configCmdLine.at(i) == "-plugindir") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "QT_INSTALL_PLUGINS" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-importdir" ) { + else if (configCmdLine.at(i) == "-importdir") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "QT_INSTALL_IMPORTS" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-datadir" ) { + else if (configCmdLine.at(i) == "-datadir") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "QT_INSTALL_DATA" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-translationdir" ) { + else if (configCmdLine.at(i) == "-translationdir") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "QT_INSTALL_TRANSLATIONS" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-examplesdir" ) { + else if (configCmdLine.at(i) == "-examplesdir") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "QT_INSTALL_EXAMPLES" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-demosdir" ) { + else if (configCmdLine.at(i) == "-demosdir") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "QT_INSTALL_DEMOS" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-hostprefix" ) { + else if (configCmdLine.at(i) == "-hostprefix") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "QT_HOST_PREFIX" ] = configCmdLine.at(i); } - else if( configCmdLine.at(i) == "-make" ) { + else if (configCmdLine.at(i) == "-make") { ++i; - if(i==argCount) + if (i == argCount) break; dictionary[ "MAKE" ] = configCmdLine.at(i); } @@ -1167,14 +1157,14 @@ void Configure::parseCmdLine() dictionary["GRAPHICS_SYSTEM"] = configCmdLine.at(i); } - else if( configCmdLine.at(i).indexOf( QRegExp( "^-(en|dis)able-" ) ) != -1 ) { + else if (configCmdLine.at(i).indexOf(QRegExp("^-(en|dis)able-")) != -1) { // Scan to see if any specific modules and drivers are enabled or disabled - for( QStringList::Iterator module = modules.begin(); module != modules.end(); ++module ) { - if( configCmdLine.at(i) == QString( "-enable-" ) + (*module) ) { + for (QStringList::Iterator module = modules.begin(); module != modules.end(); ++module) { + if (configCmdLine.at(i) == QString("-enable-") + (*module)) { enabledModules += (*module); break; } - else if( configCmdLine.at(i) == QString( "-disable-" ) + (*module) ) { + else if (configCmdLine.at(i) == QString("-disable-") + (*module)) { disabledModules += (*module); break; } @@ -1208,25 +1198,25 @@ void Configure::parseCmdLine() } cout << "See the README file for a list of supported operating systems and compilers." << endl; } else { - if( dictionary[ "QMAKESPEC" ].endsWith( "-icc" ) || - dictionary[ "QMAKESPEC" ].endsWith( "-msvc" ) || - dictionary[ "QMAKESPEC" ].endsWith( "-msvc.net" ) || - dictionary[ "QMAKESPEC" ].endsWith( "-msvc2002" ) || - dictionary[ "QMAKESPEC" ].endsWith( "-msvc2003" ) || - dictionary[ "QMAKESPEC" ].endsWith( "-msvc2005" ) || - dictionary[ "QMAKESPEC" ].endsWith( "-msvc2008" ) || - dictionary[ "QMAKESPEC" ].endsWith( "-msvc2010" )) { - if ( dictionary[ "MAKE" ].isEmpty() ) dictionary[ "MAKE" ] = "nmake"; + if (dictionary[ "QMAKESPEC" ].endsWith("-icc") || + dictionary[ "QMAKESPEC" ].endsWith("-msvc") || + dictionary[ "QMAKESPEC" ].endsWith("-msvc.net") || + dictionary[ "QMAKESPEC" ].endsWith("-msvc2002") || + dictionary[ "QMAKESPEC" ].endsWith("-msvc2003") || + dictionary[ "QMAKESPEC" ].endsWith("-msvc2005") || + dictionary[ "QMAKESPEC" ].endsWith("-msvc2008") || + dictionary[ "QMAKESPEC" ].endsWith("-msvc2010")) { + if (dictionary[ "MAKE" ].isEmpty()) dictionary[ "MAKE" ] = "nmake"; dictionary[ "QMAKEMAKEFILE" ] = "Makefile.win32"; - } else if ( dictionary[ "QMAKESPEC" ] == QString( "win32-g++" ) ) { - if ( dictionary[ "MAKE" ].isEmpty() ) dictionary[ "MAKE" ] = "mingw32-make"; + } else if (dictionary[ "QMAKESPEC" ] == QString("win32-g++")) { + if (dictionary[ "MAKE" ].isEmpty()) dictionary[ "MAKE" ] = "mingw32-make"; if (Environment::detectExecutable("sh.exe")) { dictionary[ "QMAKEMAKEFILE" ] = "Makefile.win32-g++-sh"; } else { dictionary[ "QMAKEMAKEFILE" ] = "Makefile.win32-g++"; } } else { - if ( dictionary[ "MAKE" ].isEmpty() ) dictionary[ "MAKE" ] = "make"; + if (dictionary[ "MAKE" ].isEmpty()) dictionary[ "MAKE" ] = "make"; dictionary[ "QMAKEMAKEFILE" ] = "Makefile.win32"; } } @@ -1282,19 +1272,19 @@ void Configure::parseCmdLine() #if !defined(EVAL) - for( QStringList::Iterator dis = disabledModules.begin(); dis != disabledModules.end(); ++dis ) { - modules.removeAll( (*dis) ); + for (QStringList::Iterator dis = disabledModules.begin(); dis != disabledModules.end(); ++dis) { + modules.removeAll((*dis)); } - for( QStringList::Iterator ena = enabledModules.begin(); ena != enabledModules.end(); ++ena ) { - if( modules.indexOf( (*ena) ) == -1 ) + for (QStringList::Iterator ena = enabledModules.begin(); ena != enabledModules.end(); ++ena) { + if (modules.indexOf((*ena)) == -1) modules += (*ena); } qtConfig += modules; - for( QStringList::Iterator it = disabledModules.begin(); it != disabledModules.end(); ++it ) + for (QStringList::Iterator it = disabledModules.begin(); it != disabledModules.end(); ++it) qtConfig.removeAll(*it); - if( ( dictionary[ "REDO" ] != "yes" ) && ( dictionary[ "HELP" ] != "yes" ) ) + if ((dictionary[ "REDO" ] != "yes") && (dictionary[ "HELP" ] != "yes")) saveCmdLine(); #endif } @@ -1314,7 +1304,7 @@ void Configure::validateArgs() QStringList stringList = dir.entryList(); QStringList::Iterator it; - for( it = stringList.begin(); it != stringList.end(); ++it ) + for (it = stringList.begin(); it != stringList.end(); ++it) allConfigs << it->remove("qconfig-").remove(".h"); allConfigs << "full"; @@ -1335,11 +1325,11 @@ void Configure::validateArgs() // If the internal configurations failed, try others. QStringList::Iterator config; - for( config = allConfigs.begin(); config != allConfigs.end(); ++config ) { - if( (*config) == dictionary[ "QCONFIG" ] ) + for (config = allConfigs.begin(); config != allConfigs.end(); ++config) { + if ((*config) == dictionary[ "QCONFIG" ]) break; } - if( config == allConfigs.end() ) { + if (config == allConfigs.end()) { dictionary[ "HELP" ] = "yes"; cout << "No such configuration \"" << qPrintable(dictionary[ "QCONFIG" ]) << "\"" << endl ; } @@ -1492,7 +1482,7 @@ void Configure::applySpecSpecifics() dictionary[ "QT_HOST_PREFIX" ] = dictionary[ "QT_INSTALL_PREFIX" ]; dictionary[ "QT_INSTALL_PREFIX" ] = ""; - } else if(dictionary[ "XQMAKESPEC" ].startsWith("symbian")) { + } else if (dictionary[ "XQMAKESPEC" ].startsWith("symbian")) { dictionary[ "ACCESSIBILITY" ] = "no"; dictionary[ "STYLE_WINDOWSXP" ] = "no"; dictionary[ "STYLE_WINDOWSVISTA" ] = "no"; @@ -1541,7 +1531,7 @@ void Configure::applySpecSpecifics() // Disable building docs and translations for now disabledBuildParts << "docs" << "translations"; - } else if(dictionary[ "XQMAKESPEC" ].startsWith("linux")) { //TODO actually wrong. + } else if (dictionary[ "XQMAKESPEC" ].startsWith("linux")) { //TODO actually wrong. //TODO dictionary[ "STYLE_WINDOWSXP" ] = "no"; dictionary[ "STYLE_WINDOWSVISTA" ] = "no"; @@ -1567,22 +1557,22 @@ void Configure::applySpecSpecifics() QString Configure::locateFileInPaths(const QString &fileName, const QStringList &paths) { QDir d; - for( QStringList::ConstIterator it = paths.begin(); it != paths.end(); ++it ) { + for (QStringList::ConstIterator it = paths.begin(); it != paths.end(); ++it) { // Remove any leading or trailing ", this is commonly used in the environment // variables QString path = (*it); - if ( path.startsWith( "\"" ) ) - path = path.right( path.length() - 1 ); - if ( path.endsWith( "\"" ) ) - path = path.left( path.length() - 1 ); - if( d.exists(path + QDir::separator() + fileName) ) { + if (path.startsWith("\"")) + path = path.right(path.length() - 1); + if (path.endsWith("\"")) + path = path.left(path.length() - 1); + if (d.exists(path + QDir::separator() + fileName)) { return (path); } } return QString(); } -QString Configure::locateFile( const QString &fileName ) +QString Configure::locateFile(const QString &fileName) { QString file = fileName.toLower(); QStringList paths; @@ -1593,7 +1583,7 @@ QString Configure::locateFile( const QString &fileName ) #endif if (file.endsWith(".h")) paths = QString::fromLocal8Bit(getenv("INCLUDE")).split(splitReg, QString::SkipEmptyParts); - else if ( file.endsWith( ".lib" ) ) + else if (file.endsWith(".lib")) paths = QString::fromLocal8Bit(getenv("LIB")).split(splitReg, QString::SkipEmptyParts); else paths = QString::fromLocal8Bit(getenv("PATH")).split(splitReg, QString::SkipEmptyParts); @@ -1605,7 +1595,7 @@ QString Configure::locateFile( const QString &fileName ) bool Configure::displayHelp() { - if( dictionary[ "HELP" ] == "yes" ) { + if (dictionary[ "HELP" ] == "yes") { desc("Usage: configure [-buildkey <key>]\n" // desc("Usage: configure [-prefix dir] [-bindir <dir>] [-libdir <dir>]\n" // "[-docdir <dir>] [-headerdir <dir>] [-plugindir <dir>]\n" @@ -1750,22 +1740,22 @@ bool Configure::displayHelp() desc("ZLIB", "qt", "-qt-zlib", "Use the zlib bundled with Qt."); desc("ZLIB", "system", "-system-zlib", "Use zlib from the operating system.\nSee http://www.gzip.org/zlib\n"); - desc("GIF", "no", "-no-gif", "Do not compile the plugin for GIF reading support."); - desc("GIF", "auto", "-qt-gif", "Compile the plugin for GIF reading support.\nSee also src/plugins/imageformats/gif/qgifhandler.h\n"); + desc("GIF", "no", "-no-gif", "Do not compile GIF reading support."); + desc("GIF", "auto", "-qt-gif", "Compile GIF reading support.\nSee also src/gui/image/qgifhandler.h\n"); - desc("LIBPNG", "no", "-no-libpng", "Do not compile in PNG support."); + desc("LIBPNG", "no", "-no-libpng", "Do not compile PNG support."); desc("LIBPNG", "qt", "-qt-libpng", "Use the libpng bundled with Qt."); desc("LIBPNG", "system","-system-libpng", "Use libpng from the operating system.\nSee http://www.libpng.org/pub/png\n"); - desc("LIBMNG", "no", "-no-libmng", "Do not compile in MNG support."); + desc("LIBMNG", "no", "-no-libmng", "Do not compile MNG support."); desc("LIBMNG", "qt", "-qt-libmng", "Use the libmng bundled with Qt."); desc("LIBMNG", "system","-system-libmng", "Use libmng from the operating system.\nSee See http://www.libmng.com\n"); - desc("LIBTIFF", "no", "-no-libtiff", "Do not compile the plugin for TIFF support."); + desc("LIBTIFF", "no", "-no-libtiff", "Do not compile TIFF support."); desc("LIBTIFF", "qt", "-qt-libtiff", "Use the libtiff bundled with Qt."); desc("LIBTIFF", "system","-system-libtiff", "Use libtiff from the operating system.\nSee http://www.libtiff.org\n"); - desc("LIBJPEG", "no", "-no-libjpeg", "Do not compile the plugin for JPEG support."); + desc("LIBJPEG", "no", "-no-libjpeg", "Do not compile JPEG support."); desc("LIBJPEG", "qt", "-qt-libjpeg", "Use the libjpeg bundled with Qt."); desc("LIBJPEG", "system","-system-libjpeg", "Use libjpeg from the operating system.\nSee http://www.ijg.org\n"); @@ -1898,21 +1888,21 @@ QString Configure::findFileInPaths(const QString &fileName, const QString &paths #endif QStringList pathList = paths.split(splitReg, QString::SkipEmptyParts); QDir d; - for( QStringList::ConstIterator it = pathList.begin(); it != pathList.end(); ++it ) { + for (QStringList::ConstIterator it = pathList.begin(); it != pathList.end(); ++it) { // Remove any leading or trailing ", this is commonly used in the environment // variables QString path = (*it); - if ( path.startsWith( '\"' ) ) - path = path.right( path.length() - 1 ); - if ( path.endsWith( '\"' ) ) - path = path.left( path.length() - 1 ); - if( d.exists( path + QDir::separator() + fileName ) ) + if (path.startsWith('\"')) + path = path.right(path.length() - 1); + if (path.endsWith('\"')) + path = path.left(path.length() - 1); + if (d.exists(path + QDir::separator() + fileName)) return path; } return QString(); } -bool Configure::findFile( const QString &fileName ) +bool Configure::findFile(const QString &fileName) { const QString file = fileName.toLower(); const QString pathEnvVar = QString::fromLocal8Bit(getenv("PATH")); @@ -1923,7 +1913,7 @@ bool Configure::findFile( const QString &fileName ) if (file.endsWith(".h")) { if (!mingwPath.isNull()) { if (!findFileInPaths(file, mingwPath + QLatin1String("/../include")).isNull()) - return true; + return true; //now let's try the additional compiler path QDir mingwLibDir = mingwPath + QLatin1String("/../lib/gcc/mingw32"); foreach(const QFileInfo &version, mingwLibDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) { @@ -1932,9 +1922,9 @@ bool Configure::findFile( const QString &fileName ) } } paths = QString::fromLocal8Bit(getenv("INCLUDE")); - } else if ( file.endsWith( ".lib" ) || file.endsWith( ".a" ) ) { + } else if (file.endsWith(".lib") || file.endsWith(".a")) { if (!mingwPath.isNull() && !findFileInPaths(file, mingwPath + QLatin1String("/../lib")).isNull()) - return true; + return true; paths = QString::fromLocal8Bit(getenv("LIB")); } else { paths = pathEnvVar; @@ -1957,21 +1947,28 @@ QString Configure::defaultTo(const QString &option) || option == "LIBTIFF") return "system"; - // We want PNG built-in + // PNG is always built-in, never a plugin if (option == "PNG") - return "qt"; - - // The JPEG image library can only be a plugin - if (option == "JPEG" - || option == "MNG" || option == "TIFF") - return "plugin"; - - // GIF off by default - if (option == "GIF") { - if (dictionary["SHARED"] == "yes") + return "yes"; + + // These database drivers and image formats can be built-in or plugins. + // Prefer plugins when Qt is shared. + if (dictionary[ "SHARED" ] == "yes") { + if (option == "SQL_MYSQL" + || option == "SQL_MYSQL" + || option == "SQL_ODBC" + || option == "SQL_OCI" + || option == "SQL_PSQL" + || option == "SQL_TDS" + || option == "SQL_DB2" + || option == "SQL_SQLITE" + || option == "SQL_SQLITE2" + || option == "SQL_IBASE" + || option == "JPEG" + || option == "MNG" + || option == "TIFF" + || option == "GIF") return "plugin"; - else - return "yes"; } // By default we do not want to compile OCI driver when compiling with @@ -1981,18 +1978,6 @@ QString Configure::defaultTo(const QString &option) && option == "SQL_OCI") return "no"; - if (option == "SQL_MYSQL" - || option == "SQL_MYSQL" - || option == "SQL_ODBC" - || option == "SQL_OCI" - || option == "SQL_PSQL" - || option == "SQL_TDS" - || option == "SQL_DB2" - || option == "SQL_SQLITE" - || option == "SQL_SQLITE2" - || option == "SQL_IBASE") - return "plugin"; - if (option == "SYNCQT" && (!QFile::exists(sourcePath + "/bin/syncqt") || !QFile::exists(sourcePath + "/bin/syncqt.bat"))) @@ -2041,15 +2026,15 @@ bool Configure::checkAvailability(const QString &part) available = true; // Built in, we have a fork else if (part == "SQL_SQLITE_LIB") { if (dictionary[ "SQL_SQLITE_LIB" ] == "system") { - // Symbian has multiple .lib/.dll files we need to find + // Symbian has multiple .lib/.dll files we need to find if (dictionary.contains("XQMAKESPEC") && dictionary["XQMAKESPEC"].startsWith("symbian")) { - available = true; // There is sqlite_symbian plugin which exports the necessary stuff - dictionary[ "QT_LFLAGS_SQLITE" ] += "-lsqlite3"; - } else { - available = findFile("sqlite3.h") && findFile("sqlite3.lib"); - if (available) - dictionary[ "QT_LFLAGS_SQLITE" ] += "sqlite3.lib"; - } + available = true; // There is sqlite_symbian plugin which exports the necessary stuff + dictionary[ "QT_LFLAGS_SQLITE" ] += "-lsqlite3"; + } else { + available = findFile("sqlite3.h") && findFile("sqlite3.lib"); + if (available) + dictionary[ "QT_LFLAGS_SQLITE" ] += "sqlite3.lib"; + } } else available = true; } else if (part == "SQL_SQLITE2") @@ -2066,7 +2051,7 @@ bool Configure::checkAvailability(const QString &part) available = (dictionary[ "ARCHITECTURE" ] == "windowsce"); else if (part == "SSE2") available = (dictionary.value("QMAKESPEC") != "win32-msvc"); - else if (part == "3DNOW" ) + else if (part == "3DNOW") available = (dictionary.value("QMAKESPEC") != "win32-msvc") && (dictionary.value("QMAKESPEC") != "win32-icc") && findFile("mm3dnow.h"); else if (part == "MMX" || part == "SSE") available = (dictionary.value("QMAKESPEC") != "win32-msvc"); @@ -2125,7 +2110,7 @@ bool Configure::checkAvailability(const QString &part) available = true; } else if (part == "WEBKIT") { available = (dictionary.value("QMAKESPEC") == "win32-msvc2005") || (dictionary.value("QMAKESPEC") == "win32-msvc2008") || (dictionary.value("QMAKESPEC") == "win32-msvc2010") || (dictionary.value("QMAKESPEC") == "win32-g++"); - if( dictionary[ "SHARED" ] == "no" ) { + if (dictionary[ "SHARED" ] == "no") { cout << endl << "WARNING: Using static linking will disable the WebKit module." << endl << endl; available = false; @@ -2290,7 +2275,7 @@ bool Configure::verifyConfiguration() cout << "WARNING: Configure could not detect the presence of a system SQLite3 lib." << endl << "Configure will therefore continue with the SQLite3 lib bundled with Qt." << endl << "(Press any key to continue..)"; - if(_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout) + if (_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout) exit(0); // Exit cleanly for Ctrl+C dictionary["SQL_SQLITE_LIB"] = "qt"; // Set to Qt's bundled lib an continue @@ -2301,14 +2286,14 @@ bool Configure::verifyConfiguration() << "MinGW, due to lack of such support from Oracle. Consider disabling the" << endl << "Oracle driver, as the current build will most likely fail." << endl; cout << "(Press any key to continue..)"; - if(_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout) + if (_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout) exit(0); // Exit cleanly for Ctrl+C } if (dictionary["QMAKESPEC"].endsWith("win32-msvc.net")) { cout << "WARNING: The makespec win32-msvc.net is deprecated. Consider using" << endl << "win32-msvc2002 or win32-msvc2003 instead." << endl; cout << "(Press any key to continue..)"; - if(_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout) + if (_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout) exit(0); // Exit cleanly for Ctrl+C } if (0 != dictionary["ARM_FPU_TYPE"].size()) { @@ -2323,7 +2308,7 @@ bool Configure::verifyConfiguration() cout << "WARNING: To be able to compile QtDeclarative we need to also compile the" << endl << "QtScript module. If you continue, we will turn on the QtScript module." << endl << "(Press any key to continue..)"; - if(_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout) + if (_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout) exit(0); // Exit cleanly for Ctrl+C dictionary["SCRIPT"] = "yes"; @@ -2423,13 +2408,13 @@ void Configure::generateOutputVars() { // Generate variables for output // Build key ---------------------------------------------------- - if ( dictionary.contains("BUILD_KEY") ) { + if (dictionary.contains("BUILD_KEY")) { qmakeVars += dictionary.value("BUILD_KEY"); } QString build = dictionary[ "BUILD" ]; bool buildAll = (dictionary[ "BUILDALL" ] == "yes"); - if ( build == "debug") { + if (build == "debug") { if (buildAll) qtConfig += "release"; qtConfig += "debug"; @@ -2440,142 +2425,142 @@ void Configure::generateOutputVars() } // Compression -------------------------------------------------- - if( dictionary[ "ZLIB" ] == "qt" ) + if (dictionary[ "ZLIB" ] == "qt") qtConfig += "zlib"; - else if( dictionary[ "ZLIB" ] == "system" ) + else if (dictionary[ "ZLIB" ] == "system") qtConfig += "system-zlib"; // Image formates ----------------------------------------------- - if( dictionary[ "GIF" ] == "no" ) + if (dictionary[ "GIF" ] == "no") qtConfig += "no-gif"; - else if( dictionary[ "GIF" ] == "yes" ) + else if (dictionary[ "GIF" ] == "yes") qtConfig += "gif"; - else if( dictionary[ "GIF" ] == "plugin" ) + else if (dictionary[ "GIF" ] == "plugin") qmakeFormatPlugins += "gif"; - if( dictionary[ "TIFF" ] == "no" ) + if (dictionary[ "TIFF" ] == "no") qtConfig += "no-tiff"; - else if( dictionary[ "TIFF" ] == "plugin" ) + else if (dictionary[ "TIFF" ] == "plugin") qmakeFormatPlugins += "tiff"; - if( dictionary[ "LIBTIFF" ] == "system" ) + if (dictionary[ "LIBTIFF" ] == "system") qtConfig += "system-tiff"; - if( dictionary[ "JPEG" ] == "no" ) + if (dictionary[ "JPEG" ] == "no") qtConfig += "no-jpeg"; - else if( dictionary[ "JPEG" ] == "plugin" ) + else if (dictionary[ "JPEG" ] == "plugin") qmakeFormatPlugins += "jpeg"; - if( dictionary[ "LIBJPEG" ] == "system" ) + if (dictionary[ "LIBJPEG" ] == "system") qtConfig += "system-jpeg"; - if( dictionary[ "PNG" ] == "no" ) + if (dictionary[ "PNG" ] == "no") qtConfig += "no-png"; - else if( dictionary[ "PNG" ] == "qt" ) + else if (dictionary[ "PNG" ] == "yes") qtConfig += "png"; - if( dictionary[ "LIBPNG" ] == "system" ) + if (dictionary[ "LIBPNG" ] == "system") qtConfig += "system-png"; - if( dictionary[ "MNG" ] == "no" ) + if (dictionary[ "MNG" ] == "no") qtConfig += "no-mng"; - else if( dictionary[ "MNG" ] == "qt" ) + else if (dictionary[ "MNG" ] == "yes") qtConfig += "mng"; - if( dictionary[ "LIBMNG" ] == "system" ) + if (dictionary[ "LIBMNG" ] == "system") qtConfig += "system-mng"; // Text rendering -------------------------------------------------- - if( dictionary[ "FREETYPE" ] == "yes" ) + if (dictionary[ "FREETYPE" ] == "yes") qtConfig += "freetype"; // Styles ------------------------------------------------------- - if ( dictionary[ "STYLE_WINDOWS" ] == "yes" ) + if (dictionary[ "STYLE_WINDOWS" ] == "yes") qmakeStyles += "windows"; - if ( dictionary[ "STYLE_PLASTIQUE" ] == "yes" ) + if (dictionary[ "STYLE_PLASTIQUE" ] == "yes") qmakeStyles += "plastique"; - if ( dictionary[ "STYLE_CLEANLOOKS" ] == "yes" ) + if (dictionary[ "STYLE_CLEANLOOKS" ] == "yes") qmakeStyles += "cleanlooks"; - if ( dictionary[ "STYLE_WINDOWSXP" ] == "yes" ) + if (dictionary[ "STYLE_WINDOWSXP" ] == "yes") qmakeStyles += "windowsxp"; - if ( dictionary[ "STYLE_WINDOWSVISTA" ] == "yes" ) + if (dictionary[ "STYLE_WINDOWSVISTA" ] == "yes") qmakeStyles += "windowsvista"; - if ( dictionary[ "STYLE_MOTIF" ] == "yes" ) + if (dictionary[ "STYLE_MOTIF" ] == "yes") qmakeStyles += "motif"; - if ( dictionary[ "STYLE_SGI" ] == "yes" ) + if (dictionary[ "STYLE_SGI" ] == "yes") qmakeStyles += "sgi"; - if ( dictionary[ "STYLE_WINDOWSCE" ] == "yes" ) + if (dictionary[ "STYLE_WINDOWSCE" ] == "yes") qmakeStyles += "windowsce"; - if ( dictionary[ "STYLE_WINDOWSMOBILE" ] == "yes" ) + if (dictionary[ "STYLE_WINDOWSMOBILE" ] == "yes") qmakeStyles += "windowsmobile"; - if ( dictionary[ "STYLE_CDE" ] == "yes" ) + if (dictionary[ "STYLE_CDE" ] == "yes") qmakeStyles += "cde"; - if ( dictionary[ "STYLE_S60" ] == "yes" ) + if (dictionary[ "STYLE_S60" ] == "yes") qmakeStyles += "s60"; // Databases ---------------------------------------------------- - if ( dictionary[ "SQL_MYSQL" ] == "yes" ) + if (dictionary[ "SQL_MYSQL" ] == "yes") qmakeSql += "mysql"; - else if ( dictionary[ "SQL_MYSQL" ] == "plugin" ) + else if (dictionary[ "SQL_MYSQL" ] == "plugin") qmakeSqlPlugins += "mysql"; - if ( dictionary[ "SQL_ODBC" ] == "yes" ) + if (dictionary[ "SQL_ODBC" ] == "yes") qmakeSql += "odbc"; - else if ( dictionary[ "SQL_ODBC" ] == "plugin" ) + else if (dictionary[ "SQL_ODBC" ] == "plugin") qmakeSqlPlugins += "odbc"; - if ( dictionary[ "SQL_OCI" ] == "yes" ) + if (dictionary[ "SQL_OCI" ] == "yes") qmakeSql += "oci"; - else if ( dictionary[ "SQL_OCI" ] == "plugin" ) + else if (dictionary[ "SQL_OCI" ] == "plugin") qmakeSqlPlugins += "oci"; - if ( dictionary[ "SQL_PSQL" ] == "yes" ) + if (dictionary[ "SQL_PSQL" ] == "yes") qmakeSql += "psql"; - else if ( dictionary[ "SQL_PSQL" ] == "plugin" ) + else if (dictionary[ "SQL_PSQL" ] == "plugin") qmakeSqlPlugins += "psql"; - if ( dictionary[ "SQL_TDS" ] == "yes" ) + if (dictionary[ "SQL_TDS" ] == "yes") qmakeSql += "tds"; - else if ( dictionary[ "SQL_TDS" ] == "plugin" ) + else if (dictionary[ "SQL_TDS" ] == "plugin") qmakeSqlPlugins += "tds"; - if ( dictionary[ "SQL_DB2" ] == "yes" ) + if (dictionary[ "SQL_DB2" ] == "yes") qmakeSql += "db2"; - else if ( dictionary[ "SQL_DB2" ] == "plugin" ) + else if (dictionary[ "SQL_DB2" ] == "plugin") qmakeSqlPlugins += "db2"; - if ( dictionary[ "SQL_SQLITE" ] == "yes" ) + if (dictionary[ "SQL_SQLITE" ] == "yes") qmakeSql += "sqlite"; - else if ( dictionary[ "SQL_SQLITE" ] == "plugin" ) + else if (dictionary[ "SQL_SQLITE" ] == "plugin") qmakeSqlPlugins += "sqlite"; - if ( dictionary[ "SQL_SQLITE_LIB" ] == "system" ) + if (dictionary[ "SQL_SQLITE_LIB" ] == "system") qmakeConfig += "system-sqlite"; - if ( dictionary[ "SQL_SQLITE2" ] == "yes" ) + if (dictionary[ "SQL_SQLITE2" ] == "yes") qmakeSql += "sqlite2"; - else if ( dictionary[ "SQL_SQLITE2" ] == "plugin" ) + else if (dictionary[ "SQL_SQLITE2" ] == "plugin") qmakeSqlPlugins += "sqlite2"; - if ( dictionary[ "SQL_IBASE" ] == "yes" ) + if (dictionary[ "SQL_IBASE" ] == "yes") qmakeSql += "ibase"; - else if ( dictionary[ "SQL_IBASE" ] == "plugin" ) + else if (dictionary[ "SQL_IBASE" ] == "plugin") qmakeSqlPlugins += "ibase"; // Other options ------------------------------------------------ - if( dictionary[ "BUILDALL" ] == "yes" ) { + if (dictionary[ "BUILDALL" ] == "yes") { qmakeConfig += "build_all"; } qmakeConfig += dictionary[ "BUILD" ]; dictionary[ "QMAKE_OUTDIR" ] = dictionary[ "BUILD" ]; - if ( dictionary[ "SHARED" ] == "yes" ) { + if (dictionary[ "SHARED" ] == "yes") { QString version = dictionary[ "VERSION" ]; if (!version.isEmpty()) { qmakeVars += "QMAKE_QT_VERSION_OVERRIDE = " + version.left(version.indexOf(".")); @@ -2586,13 +2571,13 @@ void Configure::generateOutputVars() dictionary[ "QMAKE_OUTDIR" ] += "_static"; } - if( dictionary[ "ACCESSIBILITY" ] == "yes" ) + if (dictionary[ "ACCESSIBILITY" ] == "yes") qtConfig += "accessibility"; - if( !qmakeLibs.isEmpty() ) - qmakeVars += "LIBS += " + escapeSeparators(qmakeLibs.join( " " )); + if (!qmakeLibs.isEmpty()) + qmakeVars += "LIBS += " + escapeSeparators(qmakeLibs.join(" ")); - if( !dictionary["QT_LFLAGS_SQLITE"].isEmpty() ) + if (!dictionary["QT_LFLAGS_SQLITE"].isEmpty()) qmakeVars += "QT_LFLAGS_SQLITE += " + escapeSeparators(dictionary["QT_LFLAGS_SQLITE"]); if (dictionary[ "QT3SUPPORT" ] == "yes") @@ -2601,26 +2586,26 @@ void Configure::generateOutputVars() if (dictionary[ "OPENGL" ] == "yes") qtConfig += "opengl"; - if ( dictionary["OPENGL_ES_CM"] == "yes" ) { + if (dictionary["OPENGL_ES_CM"] == "yes") { qtConfig += "opengles1"; qtConfig += "egl"; } - if ( dictionary["OPENGL_ES_2"] == "yes" ) { + if (dictionary["OPENGL_ES_2"] == "yes") { qtConfig += "opengles2"; qtConfig += "egl"; } - if ( dictionary["OPENVG"] == "yes" ) { + if (dictionary["OPENVG"] == "yes") { qtConfig += "openvg"; qtConfig += "egl"; } - if ( dictionary["S60"] == "yes" ) { + if (dictionary["S60"] == "yes") { qtConfig += "s60"; } - if ( dictionary["DIRECTSHOW"] == "yes" ) + if (dictionary["DIRECTSHOW"] == "yes") qtConfig += "directshow"; if (dictionary[ "OPENSSL" ] == "yes") @@ -2680,7 +2665,7 @@ void Configure::generateOutputVars() qtConfig += "declarative"; } - if( dictionary[ "NATIVE_GESTURES" ] == "yes" ) + if (dictionary[ "NATIVE_GESTURES" ] == "yes") qtConfig += "native-gestures"; // We currently have no switch for QtSvg, so add it unconditionally. @@ -2703,7 +2688,7 @@ void Configure::generateOutputVars() } } - if (dictionary.contains("XQMAKESPEC") && ( dictionary["QMAKESPEC"] != dictionary["XQMAKESPEC"] ) ) + if (dictionary.contains("XQMAKESPEC") && (dictionary["QMAKESPEC"] != dictionary["XQMAKESPEC"])) qmakeConfig += "cross_compile"; // Directories and settings for .qmake.cache -------------------- @@ -2711,31 +2696,31 @@ void Configure::generateOutputVars() // if QT_INSTALL_* have not been specified on commandline, define them now from QT_INSTALL_PREFIX // if prefix is empty (WINCE), make all of them empty, if they aren't set bool qipempty = false; - if(dictionary[ "QT_INSTALL_PREFIX" ].isEmpty()) + if (dictionary[ "QT_INSTALL_PREFIX" ].isEmpty()) qipempty = true; - if( !dictionary[ "QT_INSTALL_DOCS" ].size() ) - dictionary[ "QT_INSTALL_DOCS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/doc" ); - if( !dictionary[ "QT_INSTALL_HEADERS" ].size() ) - dictionary[ "QT_INSTALL_HEADERS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/include" ); - if( !dictionary[ "QT_INSTALL_LIBS" ].size() ) - dictionary[ "QT_INSTALL_LIBS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/lib" ); - if( !dictionary[ "QT_INSTALL_BINS" ].size() ) - dictionary[ "QT_INSTALL_BINS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/bin" ); - if( !dictionary[ "QT_INSTALL_PLUGINS" ].size() ) - dictionary[ "QT_INSTALL_PLUGINS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/plugins" ); - if( !dictionary[ "QT_INSTALL_IMPORTS" ].size() ) - dictionary[ "QT_INSTALL_IMPORTS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/imports" ); - if( !dictionary[ "QT_INSTALL_DATA" ].size() ) - dictionary[ "QT_INSTALL_DATA" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] ); - if( !dictionary[ "QT_INSTALL_TRANSLATIONS" ].size() ) - dictionary[ "QT_INSTALL_TRANSLATIONS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/translations" ); - if( !dictionary[ "QT_INSTALL_EXAMPLES" ].size() ) - dictionary[ "QT_INSTALL_EXAMPLES" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/examples"); - if( !dictionary[ "QT_INSTALL_DEMOS" ].size() ) - dictionary[ "QT_INSTALL_DEMOS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/demos" ); - - if(dictionary.contains("XQMAKESPEC") && dictionary[ "XQMAKESPEC" ].startsWith("linux")) + if (!dictionary[ "QT_INSTALL_DOCS" ].size()) + dictionary[ "QT_INSTALL_DOCS" ] = qipempty ? "" : fixSeparators(dictionary[ "QT_INSTALL_PREFIX" ] + "/doc"); + if (!dictionary[ "QT_INSTALL_HEADERS" ].size()) + dictionary[ "QT_INSTALL_HEADERS" ] = qipempty ? "" : fixSeparators(dictionary[ "QT_INSTALL_PREFIX" ] + "/include"); + if (!dictionary[ "QT_INSTALL_LIBS" ].size()) + dictionary[ "QT_INSTALL_LIBS" ] = qipempty ? "" : fixSeparators(dictionary[ "QT_INSTALL_PREFIX" ] + "/lib"); + if (!dictionary[ "QT_INSTALL_BINS" ].size()) + dictionary[ "QT_INSTALL_BINS" ] = qipempty ? "" : fixSeparators(dictionary[ "QT_INSTALL_PREFIX" ] + "/bin"); + if (!dictionary[ "QT_INSTALL_PLUGINS" ].size()) + dictionary[ "QT_INSTALL_PLUGINS" ] = qipempty ? "" : fixSeparators(dictionary[ "QT_INSTALL_PREFIX" ] + "/plugins"); + if (!dictionary[ "QT_INSTALL_IMPORTS" ].size()) + dictionary[ "QT_INSTALL_IMPORTS" ] = qipempty ? "" : fixSeparators(dictionary[ "QT_INSTALL_PREFIX" ] + "/imports"); + if (!dictionary[ "QT_INSTALL_DATA" ].size()) + dictionary[ "QT_INSTALL_DATA" ] = qipempty ? "" : fixSeparators(dictionary[ "QT_INSTALL_PREFIX" ]); + if (!dictionary[ "QT_INSTALL_TRANSLATIONS" ].size()) + dictionary[ "QT_INSTALL_TRANSLATIONS" ] = qipempty ? "" : fixSeparators(dictionary[ "QT_INSTALL_PREFIX" ] + "/translations"); + if (!dictionary[ "QT_INSTALL_EXAMPLES" ].size()) + dictionary[ "QT_INSTALL_EXAMPLES" ] = qipempty ? "" : fixSeparators(dictionary[ "QT_INSTALL_PREFIX" ] + "/examples"); + if (!dictionary[ "QT_INSTALL_DEMOS" ].size()) + dictionary[ "QT_INSTALL_DEMOS" ] = qipempty ? "" : fixSeparators(dictionary[ "QT_INSTALL_PREFIX" ] + "/demos"); + + if (dictionary.contains("XQMAKESPEC") && dictionary[ "XQMAKESPEC" ].startsWith("linux")) dictionary[ "QMAKE_RPATHDIR" ] = dictionary[ "QT_INSTALL_LIBS" ]; qmakeVars += QString("OBJECTS_DIR = ") + fixSeparators("tmp/obj/" + dictionary[ "QMAKE_OUTDIR" ], true); @@ -2743,13 +2728,13 @@ void Configure::generateOutputVars() qmakeVars += QString("RCC_DIR = ") + fixSeparators("tmp/rcc/" + dictionary["QMAKE_OUTDIR"], true); if (!qmakeDefines.isEmpty()) - qmakeVars += QString("DEFINES += ") + qmakeDefines.join( " " ); + qmakeVars += QString("DEFINES += ") + qmakeDefines.join(" "); if (!qmakeIncludes.isEmpty()) - qmakeVars += QString("INCLUDEPATH += ") + escapeSeparators(qmakeIncludes.join( " " )); + qmakeVars += QString("INCLUDEPATH += ") + escapeSeparators(qmakeIncludes.join(" ")); if (!opensslLibs.isEmpty()) qmakeVars += opensslLibs; else if (dictionary[ "OPENSSL" ] == "linked") { - if(dictionary.contains("XQMAKESPEC") && dictionary[ "XQMAKESPEC" ].startsWith("symbian") ) + if (dictionary.contains("XQMAKESPEC") && dictionary[ "XQMAKESPEC" ].startsWith("symbian")) qmakeVars += QString("OPENSSL_LIBS = -llibssl -llibcrypto"); else qmakeVars += QString("OPENSSL_LIBS = -lssleay32 -llibeay32"); @@ -2757,15 +2742,15 @@ void Configure::generateOutputVars() if (!psqlLibs.isEmpty()) qmakeVars += QString("QT_LFLAGS_PSQL=") + psqlLibs.section("=", 1); if (!qmakeSql.isEmpty()) - qmakeVars += QString("sql-drivers += ") + qmakeSql.join( " " ); + qmakeVars += QString("sql-drivers += ") + qmakeSql.join(" "); if (!qmakeSqlPlugins.isEmpty()) - qmakeVars += QString("sql-plugins += ") + qmakeSqlPlugins.join( " " ); + qmakeVars += QString("sql-plugins += ") + qmakeSqlPlugins.join(" "); if (!qmakeStyles.isEmpty()) - qmakeVars += QString("styles += ") + qmakeStyles.join( " " ); + qmakeVars += QString("styles += ") + qmakeStyles.join(" "); if (!qmakeStylePlugins.isEmpty()) - qmakeVars += QString("style-plugins += ") + qmakeStylePlugins.join( " " ); + qmakeVars += QString("style-plugins += ") + qmakeStylePlugins.join(" "); if (!qmakeFormatPlugins.isEmpty()) - qmakeVars += QString("imageformat-plugins += ") + qmakeFormatPlugins.join( " " ); + qmakeVars += QString("imageformat-plugins += ") + qmakeFormatPlugins.join(" "); if (dictionary["QMAKESPEC"].endsWith("-g++")) { QString includepath = qgetenv("INCLUDE"); @@ -2777,22 +2762,22 @@ void Configure::generateOutputVars() qmakeVars += QString("QMAKE_LIBDIR_POST += $$split(TMPPATH,\"%1\")").arg(separator); } - if( !dictionary[ "QMAKESPEC" ].length() ) { + if (!dictionary[ "QMAKESPEC" ].length()) { cout << "Configure could not detect your compiler. QMAKESPEC must either" << endl << "be defined as an environment variable, or specified as an" << endl << "argument with -platform" << endl; dictionary[ "HELP" ] = "yes"; QStringList winPlatforms; - QDir mkspecsDir( sourcePath + "/mkspecs" ); + QDir mkspecsDir(sourcePath + "/mkspecs"); const QFileInfoList &specsList = mkspecsDir.entryInfoList(); - for(int i = 0; i < specsList.size(); ++i) { + for (int i = 0; i < specsList.size(); ++i) { const QFileInfo &fi = specsList.at(i); - if( fi.fileName().left( 5 ) == "win32" ) { + if (fi.fileName().left(5) == "win32") { winPlatforms += fi.fileName(); } } - cout << "Available platforms are: " << qPrintable(winPlatforms.join( ", " )) << endl; + cout << "Available platforms are: " << qPrintable(winPlatforms.join(", ")) << endl; dictionary[ "DONE" ] = "error"; } } @@ -2801,24 +2786,24 @@ void Configure::generateOutputVars() void Configure::generateCachefile() { // Generate .qmake.cache - QFile cacheFile( buildPath + "/.qmake.cache" ); - if( cacheFile.open( QFile::WriteOnly | QFile::Text ) ) { // Truncates any existing file. - QTextStream cacheStream( &cacheFile ); - for( QStringList::Iterator var = qmakeVars.begin(); var != qmakeVars.end(); ++var ) { + QFile cacheFile(buildPath + "/.qmake.cache"); + if (cacheFile.open(QFile::WriteOnly | QFile::Text)) { // Truncates any existing file. + QTextStream cacheStream(&cacheFile); + for (QStringList::Iterator var = qmakeVars.begin(); var != qmakeVars.end(); ++var) { cacheStream << (*var) << endl; } - cacheStream << "CONFIG += " << qmakeConfig.join( " " ) << " incremental create_prl link_prl depend_includepath QTDIR_build" << endl; + cacheStream << "CONFIG += " << qmakeConfig.join(" ") << " incremental create_prl link_prl depend_includepath QTDIR_build" << endl; QStringList buildParts; buildParts << "libs" << "tools" << "examples" << "demos" << "docs" << "translations"; foreach(QString item, disabledBuildParts) { buildParts.removeAll(item); } - cacheStream << "QT_BUILD_PARTS = " << buildParts.join( " " ) << endl; + cacheStream << "QT_BUILD_PARTS = " << buildParts.join(" ") << endl; QString targetSpec = dictionary.contains("XQMAKESPEC") ? dictionary[ "XQMAKESPEC" ] : dictionary[ "QMAKESPEC" ]; QString mkspec_path = fixSeparators(sourcePath + "/mkspecs/" + targetSpec); - if(QFile::exists(mkspec_path)) + if (QFile::exists(mkspec_path)) cacheStream << "QMAKESPEC = " << escapeSeparators(mkspec_path) << endl; else cacheStream << "QMAKESPEC = " << fixSeparators(targetSpec, true) << endl; @@ -2843,60 +2828,60 @@ void Configure::generateCachefile() } // embedded - if( !dictionary["KBD_DRIVERS"].isEmpty()) + if (!dictionary["KBD_DRIVERS"].isEmpty()) cacheStream << "kbd-drivers += "<< dictionary["KBD_DRIVERS"]<<endl; - if( !dictionary["GFX_DRIVERS"].isEmpty()) + if (!dictionary["GFX_DRIVERS"].isEmpty()) cacheStream << "gfx-drivers += "<< dictionary["GFX_DRIVERS"]<<endl; - if( !dictionary["MOUSE_DRIVERS"].isEmpty()) + if (!dictionary["MOUSE_DRIVERS"].isEmpty()) cacheStream << "mouse-drivers += "<< dictionary["MOUSE_DRIVERS"]<<endl; - if( !dictionary["DECORATIONS"].isEmpty()) + if (!dictionary["DECORATIONS"].isEmpty()) cacheStream << "decorations += "<<dictionary["DECORATIONS"]<<endl; - if( !dictionary["QMAKE_RPATHDIR"].isEmpty() ) + if (!dictionary["QMAKE_RPATHDIR"].isEmpty()) cacheStream << "QMAKE_RPATHDIR += "<<dictionary["QMAKE_RPATHDIR"]; cacheStream.flush(); cacheFile.close(); } - QFile configFile( dictionary[ "QT_BUILD_TREE" ] + "/mkspecs/qconfig.pri" ); - if( configFile.open( QFile::WriteOnly | QFile::Text ) ) { // Truncates any existing file. - QTextStream configStream( &configFile ); + QFile configFile(dictionary[ "QT_BUILD_TREE" ] + "/mkspecs/qconfig.pri"); + if (configFile.open(QFile::WriteOnly | QFile::Text)) { // Truncates any existing file. + QTextStream configStream(&configFile); configStream << "CONFIG+= "; configStream << dictionary[ "BUILD" ]; - if( dictionary[ "SHARED" ] == "yes" ) + if (dictionary[ "SHARED" ] == "yes") configStream << " shared"; else configStream << " static"; - if( dictionary[ "LTCG" ] == "yes" ) + if (dictionary[ "LTCG" ] == "yes") configStream << " ltcg"; - if( dictionary[ "STL" ] == "yes" ) + if (dictionary[ "STL" ] == "yes") configStream << " stl"; - if ( dictionary[ "EXCEPTIONS" ] == "yes" ) + if (dictionary[ "EXCEPTIONS" ] == "yes") configStream << " exceptions"; - if ( dictionary[ "EXCEPTIONS" ] == "no" ) + if (dictionary[ "EXCEPTIONS" ] == "no") configStream << " exceptions_off"; - if ( dictionary[ "RTTI" ] == "yes" ) + if (dictionary[ "RTTI" ] == "yes") configStream << " rtti"; - if ( dictionary[ "MMX" ] == "yes" ) + if (dictionary[ "MMX" ] == "yes") configStream << " mmx"; - if ( dictionary[ "3DNOW" ] == "yes" ) + if (dictionary[ "3DNOW" ] == "yes") configStream << " 3dnow"; - if ( dictionary[ "SSE" ] == "yes" ) + if (dictionary[ "SSE" ] == "yes") configStream << " sse"; - if ( dictionary[ "SSE2" ] == "yes" ) + if (dictionary[ "SSE2" ] == "yes") configStream << " sse2"; - if ( dictionary[ "IWMMXT" ] == "yes" ) + if (dictionary[ "IWMMXT" ] == "yes") configStream << " iwmmxt"; - if ( dictionary["INCREDIBUILD_XGE"] == "yes" ) + if (dictionary["INCREDIBUILD_XGE"] == "yes") configStream << " incredibuild_xge"; - if ( dictionary["PLUGIN_MANIFESTS"] == "no" ) + if (dictionary["PLUGIN_MANIFESTS"] == "no") configStream << " no_plugin_manifest"; - if ( dictionary.contains("SYMBIAN_DEFFILES") ) { - if(dictionary["SYMBIAN_DEFFILES"] == "yes" ) { + if (dictionary.contains("SYMBIAN_DEFFILES")) { + if (dictionary["SYMBIAN_DEFFILES"] == "yes") { configStream << " def_files"; - } else if ( dictionary["SYMBIAN_DEFFILES"] == "no" ) { + } else if (dictionary["SYMBIAN_DEFFILES"] == "no") { configStream << " def_files_disabled"; } } @@ -2917,17 +2902,17 @@ void Configure::generateCachefile() configStream << "#Qt for Windows CE c-runtime deployment" << endl << "QT_CE_C_RUNTIME = " << fixSeparators(dictionary[ "CE_CRT" ], true) << endl; - if(dictionary["CE_SIGNATURE"] != QLatin1String("no")) + if (dictionary["CE_SIGNATURE"] != QLatin1String("no")) configStream << "DEFAULT_SIGNATURE=" << dictionary["CE_SIGNATURE"] << endl; - if(!dictionary["QMAKE_RPATHDIR"].isEmpty()) + if (!dictionary["QMAKE_RPATHDIR"].isEmpty()) configStream << "QMAKE_RPATHDIR += " << dictionary["QMAKE_RPATHDIR"] << endl; if (!dictionary["QT_LIBINFIX"].isEmpty()) configStream << "QT_LIBINFIX = " << dictionary["QT_LIBINFIX"] << endl; configStream << "#Qt for Symbian FPU settings" << endl; - if(!dictionary["ARM_FPU_TYPE"].isEmpty()) { + if (!dictionary["ARM_FPU_TYPE"].isEmpty()) { configStream<<"MMP_RULES += \"ARMFPU "<< dictionary["ARM_FPU_TYPE"]<< "\""; } if (!dictionary["QT_NAMESPACE"].isEmpty()) { @@ -2947,10 +2932,10 @@ QString Configure::addDefine(QString def) defD.replace(QRegExp("=.*"), ""); def.replace(QRegExp("="), " "); - if(def.startsWith("QT_NO_")) { + if (def.startsWith("QT_NO_")) { defNeg = defD; defNeg.replace("QT_NO_", "QT_"); - } else if(def.startsWith("QT_")) { + } else if (def.startsWith("QT_")) { defNeg = defD; defNeg.replace("QT_", "QT_NO_"); } @@ -2976,30 +2961,30 @@ QString Configure::addDefine(QString def) void Configure::generateConfigfiles() { QDir(buildPath).mkpath("src/corelib/global"); - QString outName( buildPath + "/src/corelib/global/qconfig.h" ); + QString outName(buildPath + "/src/corelib/global/qconfig.h"); QTemporaryFile tmpFile; QTextStream tmpStream; - if(tmpFile.open()) { + if (tmpFile.open()) { tmpStream.setDevice(&tmpFile); - if( dictionary[ "QCONFIG" ] == "full" ) { + if (dictionary[ "QCONFIG" ] == "full") { tmpStream << "/* Everything */" << endl; } else { - QString configName( "qconfig-" + dictionary[ "QCONFIG" ] + ".h" ); + QString configName("qconfig-" + dictionary[ "QCONFIG" ] + ".h"); tmpStream << "/* Copied from " << configName << "*/" << endl; tmpStream << "#ifndef QT_BOOTSTRAPPED" << endl; - QFile inFile( sourcePath + "/src/corelib/global/" + configName ); - if( inFile.open( QFile::ReadOnly ) ) { + QFile inFile(sourcePath + "/src/corelib/global/" + configName); + if (inFile.open(QFile::ReadOnly)) { QByteArray buffer = inFile.readAll(); - tmpFile.write( buffer.constData(), buffer.size() ); + tmpFile.write(buffer.constData(), buffer.size()); inFile.close(); } tmpStream << "#endif // QT_BOOTSTRAPPED" << endl; } tmpStream << endl; - if( dictionary[ "SHARED" ] == "yes" ) { + if (dictionary[ "SHARED" ] == "yes") { tmpStream << "#ifndef QT_DLL" << endl; tmpStream << "#define QT_DLL" << endl; tmpStream << "#endif" << endl; @@ -3025,7 +3010,7 @@ void Configure::generateConfigfiles() tmpStream << "/* Machine byte-order */" << endl; tmpStream << "#define Q_BIG_ENDIAN 4321" << endl; tmpStream << "#define Q_LITTLE_ENDIAN 1234" << endl; - if ( QSysInfo::ByteOrder == QSysInfo::BigEndian ) + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) tmpStream << "#define Q_BYTE_ORDER Q_BIG_ENDIAN" << endl; else tmpStream << "#define Q_BYTE_ORDER Q_LITTLE_ENDIAN" << endl; @@ -3033,67 +3018,67 @@ void Configure::generateConfigfiles() tmpStream << endl << "// Compile time features" << endl; tmpStream << "#define QT_ARCH_" << dictionary["ARCHITECTURE"].toUpper() << endl; QStringList qconfigList; - if(dictionary["STL"] == "no") qconfigList += "QT_NO_STL"; - if(dictionary["STYLE_WINDOWS"] != "yes") qconfigList += "QT_NO_STYLE_WINDOWS"; - if(dictionary["STYLE_PLASTIQUE"] != "yes") qconfigList += "QT_NO_STYLE_PLASTIQUE"; - if(dictionary["STYLE_CLEANLOOKS"] != "yes") qconfigList += "QT_NO_STYLE_CLEANLOOKS"; - if(dictionary["STYLE_WINDOWSXP"] != "yes" && dictionary["STYLE_WINDOWSVISTA"] != "yes") + if (dictionary["STL"] == "no") qconfigList += "QT_NO_STL"; + if (dictionary["STYLE_WINDOWS"] != "yes") qconfigList += "QT_NO_STYLE_WINDOWS"; + if (dictionary["STYLE_PLASTIQUE"] != "yes") qconfigList += "QT_NO_STYLE_PLASTIQUE"; + if (dictionary["STYLE_CLEANLOOKS"] != "yes") qconfigList += "QT_NO_STYLE_CLEANLOOKS"; + if (dictionary["STYLE_WINDOWSXP"] != "yes" && dictionary["STYLE_WINDOWSVISTA"] != "yes") qconfigList += "QT_NO_STYLE_WINDOWSXP"; - if(dictionary["STYLE_WINDOWSVISTA"] != "yes") qconfigList += "QT_NO_STYLE_WINDOWSVISTA"; - if(dictionary["STYLE_MOTIF"] != "yes") qconfigList += "QT_NO_STYLE_MOTIF"; - if(dictionary["STYLE_CDE"] != "yes") qconfigList += "QT_NO_STYLE_CDE"; - if(dictionary["STYLE_S60"] != "yes") qconfigList += "QT_NO_STYLE_S60"; - if(dictionary["STYLE_WINDOWSCE"] != "yes") qconfigList += "QT_NO_STYLE_WINDOWSCE"; - if(dictionary["STYLE_WINDOWSMOBILE"] != "yes") qconfigList += "QT_NO_STYLE_WINDOWSMOBILE"; - if(dictionary["STYLE_GTK"] != "yes") qconfigList += "QT_NO_STYLE_GTK"; - - if(dictionary["GIF"] == "yes") qconfigList += "QT_BUILTIN_GIF_READER=1"; - if(dictionary["PNG"] == "no") qconfigList += "QT_NO_IMAGEFORMAT_PNG"; - if(dictionary["MNG"] == "no") qconfigList += "QT_NO_IMAGEFORMAT_MNG"; - if(dictionary["JPEG"] == "no") qconfigList += "QT_NO_IMAGEFORMAT_JPEG"; - if(dictionary["TIFF"] == "no") qconfigList += "QT_NO_IMAGEFORMAT_TIFF"; - if(dictionary["ZLIB"] == "no") { + if (dictionary["STYLE_WINDOWSVISTA"] != "yes") qconfigList += "QT_NO_STYLE_WINDOWSVISTA"; + if (dictionary["STYLE_MOTIF"] != "yes") qconfigList += "QT_NO_STYLE_MOTIF"; + if (dictionary["STYLE_CDE"] != "yes") qconfigList += "QT_NO_STYLE_CDE"; + if (dictionary["STYLE_S60"] != "yes") qconfigList += "QT_NO_STYLE_S60"; + if (dictionary["STYLE_WINDOWSCE"] != "yes") qconfigList += "QT_NO_STYLE_WINDOWSCE"; + if (dictionary["STYLE_WINDOWSMOBILE"] != "yes") qconfigList += "QT_NO_STYLE_WINDOWSMOBILE"; + if (dictionary["STYLE_GTK"] != "yes") qconfigList += "QT_NO_STYLE_GTK"; + + if (dictionary["GIF"] == "yes") qconfigList += "QT_BUILTIN_GIF_READER=1"; + if (dictionary["PNG"] != "yes") qconfigList += "QT_NO_IMAGEFORMAT_PNG"; + if (dictionary["MNG"] != "yes") qconfigList += "QT_NO_IMAGEFORMAT_MNG"; + if (dictionary["JPEG"] != "yes") qconfigList += "QT_NO_IMAGEFORMAT_JPEG"; + if (dictionary["TIFF"] != "yes") qconfigList += "QT_NO_IMAGEFORMAT_TIFF"; + if (dictionary["ZLIB"] == "no") { qconfigList += "QT_NO_ZLIB"; qconfigList += "QT_NO_COMPRESS"; } - if(dictionary["ACCESSIBILITY"] == "no") qconfigList += "QT_NO_ACCESSIBILITY"; - if(dictionary["EXCEPTIONS"] == "no") qconfigList += "QT_NO_EXCEPTIONS"; - if(dictionary["OPENGL"] == "no") qconfigList += "QT_NO_OPENGL"; - if(dictionary["OPENVG"] == "no") qconfigList += "QT_NO_OPENVG"; - if(dictionary["OPENSSL"] == "no") qconfigList += "QT_NO_OPENSSL"; - if(dictionary["OPENSSL"] == "linked") qconfigList += "QT_LINKED_OPENSSL"; - if(dictionary["DBUS"] == "no") qconfigList += "QT_NO_DBUS"; - if(dictionary["IPV6"] == "no") qconfigList += "QT_NO_IPV6"; - if(dictionary["WEBKIT"] == "no") qconfigList += "QT_NO_WEBKIT"; - if(dictionary["DECLARATIVE"] == "no") qconfigList += "QT_NO_DECLARATIVE"; - if(dictionary["PHONON"] == "no") qconfigList += "QT_NO_PHONON"; - if(dictionary["MULTIMEDIA"] == "no") qconfigList += "QT_NO_MULTIMEDIA"; - if(dictionary["XMLPATTERNS"] == "no") qconfigList += "QT_NO_XMLPATTERNS"; - if(dictionary["SCRIPT"] == "no") qconfigList += "QT_NO_SCRIPT"; - if(dictionary["SCRIPTTOOLS"] == "no") qconfigList += "QT_NO_SCRIPTTOOLS"; - if(dictionary["FREETYPE"] == "no") qconfigList += "QT_NO_FREETYPE"; - if(dictionary["S60"] == "no") qconfigList += "QT_NO_S60"; - if(dictionary["NATIVE_GESTURES"] == "no") qconfigList += "QT_NO_NATIVE_GESTURES"; - - if(dictionary["OPENGL_ES_CM"] == "no" && + if (dictionary["ACCESSIBILITY"] == "no") qconfigList += "QT_NO_ACCESSIBILITY"; + if (dictionary["EXCEPTIONS"] == "no") qconfigList += "QT_NO_EXCEPTIONS"; + if (dictionary["OPENGL"] == "no") qconfigList += "QT_NO_OPENGL"; + if (dictionary["OPENVG"] == "no") qconfigList += "QT_NO_OPENVG"; + if (dictionary["OPENSSL"] == "no") qconfigList += "QT_NO_OPENSSL"; + if (dictionary["OPENSSL"] == "linked") qconfigList += "QT_LINKED_OPENSSL"; + if (dictionary["DBUS"] == "no") qconfigList += "QT_NO_DBUS"; + if (dictionary["IPV6"] == "no") qconfigList += "QT_NO_IPV6"; + if (dictionary["WEBKIT"] == "no") qconfigList += "QT_NO_WEBKIT"; + if (dictionary["DECLARATIVE"] == "no") qconfigList += "QT_NO_DECLARATIVE"; + if (dictionary["PHONON"] == "no") qconfigList += "QT_NO_PHONON"; + if (dictionary["MULTIMEDIA"] == "no") qconfigList += "QT_NO_MULTIMEDIA"; + if (dictionary["XMLPATTERNS"] == "no") qconfigList += "QT_NO_XMLPATTERNS"; + if (dictionary["SCRIPT"] == "no") qconfigList += "QT_NO_SCRIPT"; + if (dictionary["SCRIPTTOOLS"] == "no") qconfigList += "QT_NO_SCRIPTTOOLS"; + if (dictionary["FREETYPE"] == "no") qconfigList += "QT_NO_FREETYPE"; + if (dictionary["S60"] == "no") qconfigList += "QT_NO_S60"; + if (dictionary["NATIVE_GESTURES"] == "no") qconfigList += "QT_NO_NATIVE_GESTURES"; + + if (dictionary["OPENGL_ES_CM"] == "no" && dictionary["OPENGL_ES_2"] == "no" && dictionary["OPENVG"] == "no") qconfigList += "QT_NO_EGL"; - if(dictionary["OPENGL_ES_CM"] == "yes" || + if (dictionary["OPENGL_ES_CM"] == "yes" || dictionary["OPENGL_ES_2"] == "yes") qconfigList += "QT_OPENGL_ES"; - if(dictionary["OPENGL_ES_CM"] == "yes") qconfigList += "QT_OPENGL_ES_1"; - if(dictionary["OPENGL_ES_2"] == "yes") qconfigList += "QT_OPENGL_ES_2"; - if(dictionary["SQL_MYSQL"] == "yes") qconfigList += "QT_SQL_MYSQL"; - if(dictionary["SQL_ODBC"] == "yes") qconfigList += "QT_SQL_ODBC"; - if(dictionary["SQL_OCI"] == "yes") qconfigList += "QT_SQL_OCI"; - if(dictionary["SQL_PSQL"] == "yes") qconfigList += "QT_SQL_PSQL"; - if(dictionary["SQL_TDS"] == "yes") qconfigList += "QT_SQL_TDS"; - if(dictionary["SQL_DB2"] == "yes") qconfigList += "QT_SQL_DB2"; - if(dictionary["SQL_SQLITE"] == "yes") qconfigList += "QT_SQL_SQLITE"; - if(dictionary["SQL_SQLITE2"] == "yes") qconfigList += "QT_SQL_SQLITE2"; - if(dictionary["SQL_IBASE"] == "yes") qconfigList += "QT_SQL_IBASE"; + if (dictionary["OPENGL_ES_CM"] == "yes") qconfigList += "QT_OPENGL_ES_1"; + if (dictionary["OPENGL_ES_2"] == "yes") qconfigList += "QT_OPENGL_ES_2"; + if (dictionary["SQL_MYSQL"] == "yes") qconfigList += "QT_SQL_MYSQL"; + if (dictionary["SQL_ODBC"] == "yes") qconfigList += "QT_SQL_ODBC"; + if (dictionary["SQL_OCI"] == "yes") qconfigList += "QT_SQL_OCI"; + if (dictionary["SQL_PSQL"] == "yes") qconfigList += "QT_SQL_PSQL"; + if (dictionary["SQL_TDS"] == "yes") qconfigList += "QT_SQL_TDS"; + if (dictionary["SQL_DB2"] == "yes") qconfigList += "QT_SQL_DB2"; + if (dictionary["SQL_SQLITE"] == "yes") qconfigList += "QT_SQL_SQLITE"; + if (dictionary["SQL_SQLITE2"] == "yes") qconfigList += "QT_SQL_SQLITE2"; + if (dictionary["SQL_IBASE"] == "yes") qconfigList += "QT_SQL_IBASE"; if (dictionary["GRAPHICS_SYSTEM"] == "openvg") qconfigList += "QT_GRAPHICSSYSTEM_OPENVG"; if (dictionary["GRAPHICS_SYSTEM"] == "opengl") qconfigList += "QT_GRAPHICSSYSTEM_OPENGL"; @@ -3115,14 +3100,14 @@ void Configure::generateConfigfiles() for (int i = 0; i < qconfigList.count(); ++i) tmpStream << addDefine(qconfigList.at(i)); - if(dictionary["EMBEDDED"] == "yes") + if (dictionary["EMBEDDED"] == "yes") { // Check for keyboard, mouse, gfx. QStringList kbdDrivers = dictionary["KBD_DRIVERS"].split(" ");; QStringList allKbdDrivers; allKbdDrivers<<"tty"<<"usb"<<"sl5000"<<"yopy"<<"vr41xx"<<"qvfb"<<"um"; foreach(QString kbd, allKbdDrivers) { - if( !kbdDrivers.contains(kbd)) + if (!kbdDrivers.contains(kbd)) tmpStream<<"#define QT_NO_QWS_KBD_"<<kbd.toUpper()<<endl; } @@ -3130,7 +3115,7 @@ void Configure::generateConfigfiles() QStringList allMouseDrivers; allMouseDrivers << "pc"<<"bus"<<"linuxtp"<<"yopy"<<"vr41xx"<<"tslib"<<"qvfb"; foreach(QString mouse, allMouseDrivers) { - if( !mouseDrivers.contains(mouse) ) + if (!mouseDrivers.contains(mouse)) tmpStream<<"#define QT_NO_QWS_MOUSE_"<<mouse.toUpper()<<endl; } @@ -3138,7 +3123,7 @@ void Configure::generateConfigfiles() QStringList allGfxDrivers; allGfxDrivers<<"linuxfb"<<"transformed"<<"qvfb"<<"vnc"<<"multiscreen"<<"ahi"; foreach(QString gfx, allGfxDrivers) { - if( !gfxDrivers.contains(gfx)) + if (!gfxDrivers.contains(gfx)) tmpStream<<"#define QT_NO_QWS_"<<gfx.toUpper()<<endl; } @@ -3149,22 +3134,22 @@ void Configure::generateConfigfiles() tmpStream<<"#define QT_QWS_DEPTH_"+depth<<endl; } - if( dictionary[ "QT_CUPS" ] == "no") + if (dictionary[ "QT_CUPS" ] == "no") tmpStream<<"#define QT_NO_CUPS"<<endl; - if( dictionary[ "QT_ICONV" ] == "no") + if (dictionary[ "QT_ICONV" ] == "no") tmpStream<<"#define QT_NO_ICONV"<<endl; - if(dictionary[ "QT_GLIB" ] == "no") + if (dictionary[ "QT_GLIB" ] == "no") tmpStream<<"#define QT_NO_GLIB"<<endl; - if(dictionary[ "QT_LPR" ] == "no") + if (dictionary[ "QT_LPR" ] == "no") tmpStream<<"#define QT_NO_LPR"<<endl; - if(dictionary[ "QT_INOTIFY" ] == "no" ) + if (dictionary[ "QT_INOTIFY" ] == "no") tmpStream<<"#define QT_NO_INOTIFY"<<endl; - if(dictionary[ "QT_SXE" ] == "no") + if (dictionary[ "QT_SXE" ] == "no") tmpStream<<"#define QT_NO_SXE"<<endl; tmpStream.flush(); @@ -3176,7 +3161,7 @@ void Configure::generateConfigfiles() tmpFile.copy(outName); tmpFile.close(); - if(!QFile::exists(buildPath + "/include/QtCore/qconfig.h")) { + if (!QFile::exists(buildPath + "/include/QtCore/qconfig.h")) { if (!writeToFile("#include \"../../src/corelib/global/qconfig.h\"\n", buildPath + "/include/QtCore/qconfig.h") || !writeToFile("#include \"../../src/corelib/global/qconfig.h\"\n", @@ -3207,7 +3192,7 @@ void Configure::generateConfigfiles() } outName = defSpec + "/qmake.conf"; - ::SetFileAttributes((wchar_t*)outName.utf16(), FILE_ATTRIBUTE_NORMAL ); + ::SetFileAttributes((wchar_t*)outName.utf16(), FILE_ATTRIBUTE_NORMAL); QFile qmakeConfFile(outName); if (qmakeConfFile.open(QFile::Append | QFile::WriteOnly | QFile::Text)) { QTextStream qmakeConfStream; @@ -3231,7 +3216,7 @@ void Configure::generateConfigfiles() << "/* Build date */" << endl << "static const char qt_configure_installation [11 + 12] = \"qt_instdate=" << QDate::currentDate().toString(Qt::ISODate) << "\";" << endl << endl; - if(!dictionary[ "QT_HOST_PREFIX" ].isNull()) + if (!dictionary[ "QT_HOST_PREFIX" ].isNull()) tmpStream << "#if !defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE)" << endl; tmpStream << "static const char qt_configure_prefix_path_str [512 + 12] = \"qt_prfxpath=" << escapeSeparators(dictionary["QT_INSTALL_PREFIX"]) << "\";" << endl << "static const char qt_configure_documentation_path_str[512 + 12] = \"qt_docspath=" << escapeSeparators(dictionary["QT_INSTALL_DOCS"]) << "\";" << endl @@ -3246,7 +3231,7 @@ void Configure::generateConfigfiles() << "static const char qt_configure_demos_path_str [512 + 12] = \"qt_demopath=" << escapeSeparators(dictionary["QT_INSTALL_DEMOS"]) << "\";" << endl //<< "static const char qt_configure_settings_path_str [256] = \"qt_stngpath=" << escapeSeparators(dictionary["QT_INSTALL_SETTINGS"]) << "\";" << endl ; - if(!dictionary[ "QT_HOST_PREFIX" ].isNull()) { + if (!dictionary[ "QT_HOST_PREFIX" ].isNull()) { tmpStream << "#else" << endl << "static const char qt_configure_prefix_path_str [512 + 12] = \"qt_prfxpath=" << escapeSeparators(dictionary[ "QT_HOST_PREFIX" ]) << "\";" << endl << "static const char qt_configure_documentation_path_str[512 + 12] = \"qt_docspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/doc", true) <<"\";" << endl @@ -3261,7 +3246,7 @@ void Configure::generateConfigfiles() << "static const char qt_configure_demos_path_str [512 + 12] = \"qt_demopath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/demos", true) <<"\";" << endl << "#endif //QT_BOOTSTRAPPED" << endl; } - tmpStream << "/* strlen( \"qt_lcnsxxxx\" ) == 12 */" << endl + tmpStream << "/* strlen( \"qt_lcnsxxxx\") == 12 */" << endl << "#define QT_CONFIGURE_LICENSEE qt_configure_licensee_str + 12;" << endl << "#define QT_CONFIGURE_LICENSED_PRODUCTS qt_configure_licensed_products_str + 12;" << endl << "#define QT_CONFIGURE_PREFIX_PATH qt_configure_prefix_path_str + 12;" << endl @@ -3282,8 +3267,8 @@ void Configure::generateConfigfiles() tmpFile2.flush(); // Replace old qconfig.cpp with new one - ::SetFileAttributes((wchar_t*)outName.utf16(), FILE_ATTRIBUTE_NORMAL ); - QFile::remove( outName ); + ::SetFileAttributes((wchar_t*)outName.utf16(), FILE_ATTRIBUTE_NORMAL); + QFile::remove(outName); tmpFile2.copy(outName); tmpFile2.close(); } @@ -3298,8 +3283,8 @@ void Configure::generateConfigfiles() tmpFile3.flush(); outName = buildPath + "/src/corelib/global/qconfig_eval.cpp"; - ::SetFileAttributes((wchar_t*)outName.utf16(), FILE_ATTRIBUTE_NORMAL ); - QFile::remove( outName ); + ::SetFileAttributes((wchar_t*)outName.utf16(), FILE_ATTRIBUTE_NORMAL); + QFile::remove(outName); if (dictionary["EDITION"] == "Evaluation" || qmakeDefines.contains("QT_EVAL")) tmpFile3.copy(outName); @@ -3343,9 +3328,9 @@ void Configure::displayConfig() } cout << "Configuration:" << endl; - cout << " " << qmakeConfig.join( "\r\n " ) << endl; + cout << " " << qmakeConfig.join("\r\n ") << endl; cout << "Qt Configuration:" << endl; - cout << " " << qtConfig.join( "\r\n " ) << endl; + cout << " " << qtConfig.join("\r\n ") << endl; cout << endl; if (dictionary.contains("XQMAKESPEC")) @@ -3437,51 +3422,51 @@ void Configure::displayConfig() if (dictionary.contains("SYMBIAN_DEFFILES")) { cout << "Symbian DEF files enabled..." << dictionary[ "SYMBIAN_DEFFILES" ] << endl; - if(dictionary["SYMBIAN_DEFFILES"] == "no") { + if (dictionary["SYMBIAN_DEFFILES"] == "no") { cout << "WARNING: Disabling DEF files will mean that Qt is NOT binary compatible with previous versions." << endl; cout << " This feature is only intended for use during development, NEVER for release builds." << endl; } } - if(dictionary["ASSISTANT_WEBKIT"] == "yes") + if (dictionary["ASSISTANT_WEBKIT"] == "yes") cout << "Using WebKit as html rendering engine in Qt Assistant." << endl; - if(checkAvailability("INCREDIBUILD_XGE")) + if (checkAvailability("INCREDIBUILD_XGE")) cout << "Using IncrediBuild XGE......" << dictionary["INCREDIBUILD_XGE"] << endl; - if( !qmakeDefines.isEmpty() ) { + if (!qmakeDefines.isEmpty()) { cout << "Defines....................."; - for( QStringList::Iterator defs = qmakeDefines.begin(); defs != qmakeDefines.end(); ++defs ) + for (QStringList::Iterator defs = qmakeDefines.begin(); defs != qmakeDefines.end(); ++defs) cout << (*defs) << " "; cout << endl; } - if( !qmakeIncludes.isEmpty() ) { + if (!qmakeIncludes.isEmpty()) { cout << "Include paths..............."; - for( QStringList::Iterator incs = qmakeIncludes.begin(); incs != qmakeIncludes.end(); ++incs ) + for (QStringList::Iterator incs = qmakeIncludes.begin(); incs != qmakeIncludes.end(); ++incs) cout << (*incs) << " "; cout << endl; } - if( !qmakeLibs.isEmpty() ) { + if (!qmakeLibs.isEmpty()) { cout << "Additional libraries........"; - for( QStringList::Iterator libs = qmakeLibs.begin(); libs != qmakeLibs.end(); ++libs ) + for (QStringList::Iterator libs = qmakeLibs.begin(); libs != qmakeLibs.end(); ++libs) cout << (*libs) << " "; cout << endl; } - if( dictionary[ "QMAKE_INTERNAL" ] == "yes" ) { + if (dictionary[ "QMAKE_INTERNAL" ] == "yes") { cout << "Using internal configuration." << endl; } - if( dictionary[ "SHARED" ] == "no" ) { + if (dictionary[ "SHARED" ] == "no") { cout << "WARNING: Using static linking will disable the use of plugins." << endl; cout << " Make sure you compile ALL needed modules into the library." << endl; } - if( dictionary[ "OPENSSL" ] == "linked" && opensslLibs.isEmpty() ) { + if (dictionary[ "OPENSSL" ] == "linked" && opensslLibs.isEmpty()) { cout << "NOTE: When linking against OpenSSL, you can override the default" << endl; cout << "library names through OPENSSL_LIBS." << endl; cout << "For example:" << endl; cout << " configure -openssl-linked OPENSSL_LIBS=\"-lssleay32 -llibeay32\"" << endl; } - if( dictionary[ "ZLIB_FORCED" ] == "yes" ) { + if (dictionary[ "ZLIB_FORCED" ] == "yes") { QString which_zlib = "supplied"; - if( dictionary[ "ZLIB" ] == "system") + if (dictionary[ "ZLIB" ] == "system") which_zlib = "system"; cout << "NOTE: The -no-zlib option was supplied but is no longer supported." << endl @@ -3510,17 +3495,17 @@ void Configure::generateHeaders() void Configure::buildQmake() { - if( dictionary[ "BUILD_QMAKE" ] == "yes" ) { + if (dictionary[ "BUILD_QMAKE" ] == "yes") { QStringList args; // Build qmake QString pwd = QDir::currentPath(); - QDir::setCurrent(buildPath + "/qmake" ); + QDir::setCurrent(buildPath + "/qmake"); QString makefile = "Makefile"; { QFile out(makefile); - if(out.open(QFile::WriteOnly | QFile::Text)) { + if (out.open(QFile::WriteOnly | QFile::Text)) { QTextStream stream(&out); stream << "#AutoGenerated by configure.exe" << endl << "BUILD_PATH = " << QDir::convertSeparators(buildPath) << endl @@ -3533,7 +3518,7 @@ void Configure::buildQmake() stream << "\n\n"; QFile in(sourcePath + "/qmake/" + dictionary["QMAKEMAKEFILE"]); - if(in.open(QFile::ReadOnly | QFile::Text)) { + if (in.open(QFile::ReadOnly | QFile::Text)) { QString d = in.readAll(); //### need replaces (like configure.sh)? --Sam stream << d << endl; @@ -3549,14 +3534,14 @@ void Configure::buildQmake() cout << "Creating qmake..." << endl; int exitCode = Environment::execute(args, QStringList(), QStringList()); - if( exitCode ) { + if (exitCode) { args.clear(); args += dictionary[ "MAKE" ]; args += "-f"; args += makefile; args += "clean"; exitCode = Environment::execute(args, QStringList(), QStringList()); - if(exitCode) { + if (exitCode) { cout << "Cleaning qmake failed, return code " << exitCode << endl << endl; dictionary[ "DONE" ] = "error"; } else { @@ -3571,7 +3556,7 @@ void Configure::buildQmake() } } } - QDir::setCurrent( pwd ); + QDir::setCurrent(pwd); } } #endif @@ -3590,7 +3575,7 @@ void Configure::buildHostTools() << "src/tools" << "tools/linguist/lrelease"; - if(dictionary["XQMAKESPEC"].startsWith("wince")) + if (dictionary["XQMAKESPEC"].startsWith("wince")) hostToolsDirs << "tools/checksdk"; if (dictionary[ "CETEST" ] == "yes") @@ -3626,7 +3611,7 @@ void Configure::buildHostTools() args += dictionary["MAKE"]; args += "clean"; exitCode = Environment::execute(args, QStringList(), QStringList()); - if(exitCode) { + if (exitCode) { cout << "Cleaning " << hostToolsDirs.at(i) << " failed, return code " << exitCode << endl << endl; dictionary["DONE"] = "error"; break; @@ -3645,24 +3630,24 @@ void Configure::buildHostTools() QDir::setCurrent(pwd); } -void Configure::findProjects( const QString& dirName ) +void Configure::findProjects(const QString& dirName) { - if( dictionary[ "NOPROCESS" ] == "no" ) { - QDir dir( dirName ); + if (dictionary[ "NOPROCESS" ] == "no") { + QDir dir(dirName); QString entryName; int makeListNumber; ProjectType qmakeTemplate; const QFileInfoList &list = dir.entryInfoList(QStringList(QLatin1String("*.pro")), QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot); - for(int i = 0; i < list.size(); ++i) { + for (int i = 0; i < list.size(); ++i) { const QFileInfo &fi = list.at(i); - if(fi.fileName() != "qmake.pro") { + if (fi.fileName() != "qmake.pro") { entryName = dirName + "/" + fi.fileName(); - if(fi.isDir()) { - findProjects( entryName ); + if (fi.isDir()) { + findProjects(entryName); } else { - qmakeTemplate = projectType( fi.absoluteFilePath() ); - switch ( qmakeTemplate ) { + qmakeTemplate = projectType(fi.absoluteFilePath()); + switch (qmakeTemplate) { case Lib: case Subdirs: makeListNumber = 1; @@ -3689,33 +3674,33 @@ void Configure::appendMakeItem(int inList, const QString &item) dir = "/" + item; dir.prepend("/src"); makeList[inList].append(new MakeItem(sourcePath + dir, - item + ".pro", buildPath + dir + "/Makefile", Lib ) ); - if( dictionary[ "DSPFILES" ] == "yes" ) { - makeList[inList].append( new MakeItem(sourcePath + dir, - item + ".pro", buildPath + dir + "/" + item + ".dsp", Lib ) ); + item + ".pro", buildPath + dir + "/Makefile", Lib)); + if (dictionary[ "DSPFILES" ] == "yes") { + makeList[inList].append(new MakeItem(sourcePath + dir, + item + ".pro", buildPath + dir + "/" + item + ".dsp", Lib)); } - if( dictionary[ "VCPFILES" ] == "yes" ) { - makeList[inList].append( new MakeItem(sourcePath + dir, - item + ".pro", buildPath + dir + "/" + item + ".vcp", Lib ) ); + if (dictionary[ "VCPFILES" ] == "yes") { + makeList[inList].append(new MakeItem(sourcePath + dir, + item + ".pro", buildPath + dir + "/" + item + ".vcp", Lib)); } - if( dictionary[ "VCPROJFILES" ] == "yes" ) { - makeList[inList].append( new MakeItem(sourcePath + dir, - item + ".pro", buildPath + dir + "/" + item + ".vcproj", Lib ) ); + if (dictionary[ "VCPROJFILES" ] == "yes") { + makeList[inList].append(new MakeItem(sourcePath + dir, + item + ".pro", buildPath + dir + "/" + item + ".vcproj", Lib)); } } void Configure::generateMakefiles() { - if( dictionary[ "NOPROCESS" ] == "no" ) { + if (dictionary[ "NOPROCESS" ] == "no") { #if !defined(EVAL) cout << "Creating makefiles in src..." << endl; #endif QString spec = dictionary.contains("XQMAKESPEC") ? dictionary[ "XQMAKESPEC" ] : dictionary[ "QMAKESPEC" ]; - if( spec != "win32-msvc" ) + if (spec != "win32-msvc") dictionary[ "DSPFILES" ] = "no"; - if( spec != "win32-msvc.net" && !spec.startsWith("win32-msvc2") && !spec.startsWith(QLatin1String("wince"))) + if (spec != "win32-msvc.net" && !spec.startsWith("win32-msvc2") && !spec.startsWith(QLatin1String("wince"))) dictionary[ "VCPROJFILES" ] = "no"; int i = 0; @@ -3730,10 +3715,10 @@ void Configure::generateMakefiles() QString dirPath = fixSeparators(buildPath + dirName); QStringList args; - args << fixSeparators( buildPath + "/bin/qmake" ); + args << fixSeparators(buildPath + "/bin/qmake"); if (doDsp) { - if( dictionary[ "DEPENDENCIES" ] == "no" ) + if (dictionary[ "DEPENDENCIES" ] == "no") args << "-nodepend"; args << "-tp" << "vc"; doDsp = false; // DSP files will be done @@ -3748,21 +3733,21 @@ void Configure::generateMakefiles() args << (sourcePath + "/projects.pro"); args << "-o"; args << buildPath; - if(!dictionary[ "QMAKEADDITIONALARGS" ].isEmpty()) + if (!dictionary[ "QMAKEADDITIONALARGS" ].isEmpty()) args << dictionary[ "QMAKEADDITIONALARGS" ]; - QDir::setCurrent( fixSeparators( dirPath ) ); - if( int exitCode = Environment::execute(args, QStringList(), QStringList()) ) { + QDir::setCurrent(fixSeparators(dirPath)); + if (int exitCode = Environment::execute(args, QStringList(), QStringList())) { cout << "Qmake failed, return code " << exitCode << endl << endl; dictionary[ "DONE" ] = "error"; } } } else { findProjects(sourcePath); - for ( i=0; i<3; i++ ) { - for ( int j=0; j<makeList[i].size(); ++j) { + for (i=0; i<3; i++) { + for (int j=0; j<makeList[i].size(); ++j) { MakeItem *it=makeList[i][j]; - QString dirPath = fixSeparators( it->directory + "/" ); + QString dirPath = fixSeparators(it->directory + "/"); QString projectName = it->proFile; QString makefileName = buildPath + "/" + dirPath + it->target; @@ -3773,7 +3758,7 @@ void Configure::generateMakefiles() QStringList args; - args << fixSeparators( buildPath + "/bin/qmake" ); + args << fixSeparators(buildPath + "/bin/qmake"); args << sourcePath + "/" + dirPath + projectName; args << dictionary[ "QMAKE_ALL_ARGS" ]; @@ -3782,10 +3767,10 @@ void Configure::generateMakefiles() args << it->target; args << "-spec"; args << spec; - if(!dictionary[ "QMAKEADDITIONALARGS" ].isEmpty()) + if (!dictionary[ "QMAKEADDITIONALARGS" ].isEmpty()) args << dictionary[ "QMAKEADDITIONALARGS" ]; - QDir::setCurrent( fixSeparators( dirPath ) ); + QDir::setCurrent(fixSeparators(dirPath)); QFile file(makefileName); if (!file.open(QFile::WriteOnly)) { @@ -3803,7 +3788,7 @@ void Configure::generateMakefiles() } } } - QDir::setCurrent( pwd ); + QDir::setCurrent(pwd); } else { cout << "Processing of project files have been disabled." << endl; cout << "Only use this option if you really know what you're doing." << endl << endl; @@ -3817,7 +3802,7 @@ void Configure::showSummary() if (!dictionary.contains("XQMAKESPEC")) { cout << endl << endl << "Qt is now configured for building. Just run " << qPrintable(make) << "." << endl; cout << "To reconfigure, run " << qPrintable(make) << " confclean and configure." << endl << endl; - } else if(dictionary.value("QMAKESPEC").startsWith("wince")) { + } else if (dictionary.value("QMAKESPEC").startsWith("wince")) { // we are cross compiling for Windows CE cout << endl << endl << "Qt is now configured for building. To start the build run:" << endl << "\tsetcepaths " << dictionary.value("XQMAKESPEC") << endl @@ -3829,24 +3814,24 @@ void Configure::showSummary() } } -Configure::ProjectType Configure::projectType( const QString& proFileName ) +Configure::ProjectType Configure::projectType(const QString& proFileName) { - QFile proFile( proFileName ); - if( proFile.open( QFile::ReadOnly ) ) { + QFile proFile(proFileName); + if (proFile.open(QFile::ReadOnly)) { QString buffer = proFile.readLine(1024); while (!buffer.isEmpty()) { - QStringList segments = buffer.split(QRegExp( "\\s" )); + QStringList segments = buffer.split(QRegExp("\\s")); QStringList::Iterator it = segments.begin(); - if(segments.size() >= 3) { + if (segments.size() >= 3) { QString keyword = (*it++); QString operation = (*it++); QString value = (*it++); - if( keyword == "TEMPLATE" ) { - if( value == "lib" ) + if (keyword == "TEMPLATE") { + if (value == "lib") return Lib; - else if( value == "subdirs" ) + else if (value == "subdirs") return Subdirs; } } @@ -3932,11 +3917,11 @@ bool Configure::showLicense(QString orgLicenseFile) return false; } QStringList licenseContent = QString(file.readAll()).split('\n'); - while(i < licenseContent.size()) { + while (i < licenseContent.size()) { cout << licenseContent.at(i) << endl; if (++i % screenHeight == 0) { cout << "(Press any key for more..)"; - if(_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout) + if (_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout) exit(0); // Exit cleanly for Ctrl+C cout << "\r"; // Overwrite text above } @@ -4018,13 +4003,13 @@ void Configure::readLicense() void Configure::reloadCmdLine() { - if( dictionary[ "REDO" ] == "yes" ) { - QFile inFile( buildPath + "/configure" + dictionary[ "CUSTOMCONFIG" ] + ".cache" ); - if( inFile.open( QFile::ReadOnly ) ) { - QTextStream inStream( &inFile ); + if (dictionary[ "REDO" ] == "yes") { + QFile inFile(buildPath + "/configure" + dictionary[ "CUSTOMCONFIG" ] + ".cache"); + if (inFile.open(QFile::ReadOnly)) { + QTextStream inStream(&inFile); QString buffer; inStream >> buffer; - while( buffer.length() ) { + while (buffer.length()) { configCmdLine += buffer; inStream >> buffer; } @@ -4035,11 +4020,11 @@ void Configure::reloadCmdLine() void Configure::saveCmdLine() { - if( dictionary[ "REDO" ] != "yes" ) { - QFile outFile( buildPath + "/configure" + dictionary[ "CUSTOMCONFIG" ] + ".cache" ); - if( outFile.open( QFile::WriteOnly | QFile::Text ) ) { - QTextStream outStream( &outFile ); - for( QStringList::Iterator it = configCmdLine.begin(); it != configCmdLine.end(); ++it ) { + if (dictionary[ "REDO" ] != "yes") { + QFile outFile(buildPath + "/configure" + dictionary[ "CUSTOMCONFIG" ] + ".cache"); + if (outFile.open(QFile::WriteOnly | QFile::Text)) { + QTextStream outStream(&outFile); + for (QStringList::Iterator it = configCmdLine.begin(); it != configCmdLine.end(); ++it) { outStream << (*it) << " " << endl; } outStream.flush(); @@ -4063,23 +4048,23 @@ bool Configure::filesDiffer(const QString &fn1, const QString &fn2) { QFile file1(fn1), file2(fn2); - if(!file1.open(QFile::ReadOnly) || !file2.open(QFile::ReadOnly)) + if (!file1.open(QFile::ReadOnly) || !file2.open(QFile::ReadOnly)) return true; const int chunk = 2048; int used1 = 0, used2 = 0; char b1[chunk], b2[chunk]; - while(!file1.atEnd() && !file2.atEnd()) { - if(!used1) + while (!file1.atEnd() && !file2.atEnd()) { + if (!used1) used1 = file1.read(b1, chunk); - if(!used2) + if (!used2) used2 = file2.read(b2, chunk); - if(used1 > 0 && used2 > 0) { + if (used1 > 0 && used2 > 0) { const int cmp = qMin(used1, used2); - if(memcmp(b1, b2, cmp)) + if (memcmp(b1, b2, cmp)) return true; - if((used1 -= cmp)) + if ((used1 -= cmp)) memcpy(b1, b1+cmp, used1); - if((used2 -= cmp)) + if ((used2 -= cmp)) memcpy(b2, b2+cmp, used2); } } diff --git a/tools/designer/src/components/buddyeditor/buddyeditor.cpp b/tools/designer/src/components/buddyeditor/buddyeditor.cpp index 9da257e..e367f9a 100644 --- a/tools/designer/src/components/buddyeditor/buddyeditor.cpp +++ b/tools/designer/src/components/buddyeditor/buddyeditor.cpp @@ -405,6 +405,7 @@ QWidget *BuddyEditor::findBuddy(QLabel *l, const QWidgetList &existingBuddies) c const int y = geom.center().y(); QWidget *neighbour = 0; switch (l->layoutDirection()) { + case Qt::LayoutDirectionAuto: case Qt::LeftToRight: { // Walk right to find next managed neighbour const int xEnd = parent->size().width(); for (int x = geom.right() + 1; x < xEnd; x += DeltaX) diff --git a/tools/designer/src/components/formeditor/qmdiarea_container.cpp b/tools/designer/src/components/formeditor/qmdiarea_container.cpp index 5971094..5e266f4 100644 --- a/tools/designer/src/components/formeditor/qmdiarea_container.cpp +++ b/tools/designer/src/components/formeditor/qmdiarea_container.cpp @@ -105,6 +105,7 @@ void QMdiAreaContainer::positionNewMdiChild(const QWidget *area, QWidget *mdiChi const QPoint pos = mdiChild->pos(); const QSize areaSize = area->size(); switch (QApplication::layoutDirection()) { + case Qt::LayoutDirectionAuto: case Qt::LeftToRight: { const QSize fullSize = QSize(areaSize.width() - pos.x(), areaSize.height() - pos.y()); if (fullSize.width() > MinSize && fullSize.height() > MinSize) diff --git a/tools/designer/src/lib/shared/qdesigner_menu.cpp b/tools/designer/src/lib/shared/qdesigner_menu.cpp index ba512e4..31a226a 100644 --- a/tools/designer/src/lib/shared/qdesigner_menu.cpp +++ b/tools/designer/src/lib/shared/qdesigner_menu.cpp @@ -77,6 +77,7 @@ using namespace qdesigner_internal; static inline void extendClickableArea(QRect *subMenuRect, Qt::LayoutDirection dir) { switch (dir) { + case Qt::LayoutDirectionAuto: // Should never happen case Qt::LeftToRight: subMenuRect->setLeft(subMenuRect->left() - 20); break; @@ -931,8 +932,8 @@ void QDesignerMenu::moveUp(bool ctrl) if (ctrl) (void) swap(m_currentIndex, m_currentIndex - 1); - - m_currentIndex = qMax(0, --m_currentIndex); + --m_currentIndex; + m_currentIndex = qMax(0, m_currentIndex); // Always re-select, swapping destroys order update(); selectCurrentAction(); @@ -947,7 +948,8 @@ void QDesignerMenu::moveDown(bool ctrl) if (ctrl) (void) swap(m_currentIndex + 1, m_currentIndex); - m_currentIndex = qMin(actions().count() - 1, ++m_currentIndex); + ++m_currentIndex; + m_currentIndex = qMin(actions().count() - 1, m_currentIndex); update(); if (!ctrl) selectCurrentAction(); diff --git a/tools/designer/src/lib/shared/qdesigner_toolbar.cpp b/tools/designer/src/lib/shared/qdesigner_toolbar.cpp index 02a2f6d..e3bc64c 100644 --- a/tools/designer/src/lib/shared/qdesigner_toolbar.cpp +++ b/tools/designer/src/lib/shared/qdesigner_toolbar.cpp @@ -467,6 +467,7 @@ QRect ToolBarEventFilter::freeArea(const QToolBar *tb) switch (tb->orientation()) { case Qt::Horizontal: switch (tb->layoutDirection()) { + case Qt::LayoutDirectionAuto: // Should never happen case Qt::LeftToRight: rc.setX(exclusionRectangle.right() + 1); break; diff --git a/tools/linguist/lupdate/qdeclarative.cpp b/tools/linguist/lupdate/qdeclarative.cpp index a734e99..2377416 100644 --- a/tools/linguist/lupdate/qdeclarative.cpp +++ b/tools/linguist/lupdate/qdeclarative.cpp @@ -87,27 +87,31 @@ protected: virtual void endVisit(AST::CallExpression *node) { + m_bSource.clear(); if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(node->base)) { if (idExpr->name->asString() == QLatin1String("qsTr") || idExpr->name->asString() == QLatin1String("QT_TR_NOOP")) { - if (node->arguments && AST::cast<AST::StringLiteral *>(node->arguments->expression)) { - AST::StringLiteral *literal = AST::cast<AST::StringLiteral *>(node->arguments->expression); - const QString source = literal->value->asString(); + if (!node->arguments) + return; + AST::BinaryExpression *binary = AST::cast<AST::BinaryExpression *>(node->arguments->expression); + if (binary) { + if (!createString(binary)) + m_bSource.clear(); + } + AST::StringLiteral *literal = AST::cast<AST::StringLiteral *>(node->arguments->expression); + if (literal || !m_bSource.isEmpty()) { + const QString source = literal ? literal->value->asString() : m_bSource; QString comment; bool plural = false; AST::ArgumentList *commentNode = node->arguments->next; - if (commentNode) { + if (commentNode && AST::cast<AST::StringLiteral *>(commentNode->expression)) { literal = AST::cast<AST::StringLiteral *>(commentNode->expression); comment = literal->value->asString(); AST::ArgumentList *nNode = commentNode->next; - if (nNode) { - AST::NumericLiteral *numLiteral = AST::cast<AST::NumericLiteral *>(nNode->expression); - if (numLiteral) { - plural = true; - } - } + if (nNode) + plural = true; } TranslatorMessage msg(m_component, source, @@ -126,22 +130,25 @@ protected: QString comment; bool plural = false; AST::ArgumentList *sourceNode = node->arguments->next; - if (sourceNode) { - literal = AST::cast<AST::StringLiteral *>(sourceNode->expression); - source = literal->value->asString(); - AST::ArgumentList *commentNode = sourceNode->next; - if (commentNode) { - literal = AST::cast<AST::StringLiteral *>(commentNode->expression); - comment = literal->value->asString(); - - AST::ArgumentList *nNode = commentNode->next; - if (nNode) { - AST::NumericLiteral *numLiteral = AST::cast<AST::NumericLiteral *>(nNode->expression); - if (numLiteral) { - plural = true; - } - } - } + if (!sourceNode) + return; + literal = AST::cast<AST::StringLiteral *>(sourceNode->expression); + AST::BinaryExpression *binary = AST::cast<AST::BinaryExpression *>(sourceNode->expression); + if (binary) { + if (!createString(binary)) + m_bSource.clear(); + } + if (!literal && m_bSource.isEmpty()) + return; + source = literal ? literal->value->asString() : m_bSource; + AST::ArgumentList *commentNode = sourceNode->next; + if (commentNode && AST::cast<AST::StringLiteral *>(commentNode->expression)) { + literal = AST::cast<AST::StringLiteral *>(commentNode->expression); + comment = literal->value->asString(); + + AST::ArgumentList *nNode = commentNode->next; + if (nNode) + plural = true; } TranslatorMessage msg(context, source, @@ -156,9 +163,34 @@ protected: } private: + bool createString(AST::BinaryExpression *b) { + if (!b || b->op != 0) + return false; + AST::BinaryExpression *l = AST::cast<AST::BinaryExpression *>(b->left); + AST::BinaryExpression *r = AST::cast<AST::BinaryExpression *>(b->right); + AST::StringLiteral *ls = AST::cast<AST::StringLiteral *>(b->left); + AST::StringLiteral *rs = AST::cast<AST::StringLiteral *>(b->right); + if ((!l && !ls) || (!r && !rs)) + return false; + if (l) { + if (!createString(l)) + return false; + } else + m_bSource.prepend(ls->value->asString()); + + if (r) { + if (!createString(r)) + return false; + } else + m_bSource.append(rs->value->asString()); + + return true; + } + Translator *m_translator; QString m_fileName; QString m_component; + QString m_bSource; }; QString createErrorString(const QString &filename, const QString &code, Parser &parser) diff --git a/tools/qdoc3/doc/files/qt.qdocconf b/tools/qdoc3/doc/files/qt.qdocconf index 942d023..09c112a 100644 --- a/tools/qdoc3/doc/files/qt.qdocconf +++ b/tools/qdoc3/doc/files/qt.qdocconf @@ -8,7 +8,7 @@ project = Qt versionsym = version = %VERSION% description = Qt Reference Documentation -url = http://qt.nokia.com/doc/4.6 +url = http://qt.nokia.com/doc/4.7 edition.Console.modules = QtCore QtDBus QtNetwork QtScript QtSql QtXml \ QtXmlPatterns QtTest @@ -22,7 +22,7 @@ edition.DesktopLight.groups = -graphicsview-api qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.460 +qhp.Qt.namespace = com.trolltech.qt.470 qhp.Qt.virtualFolder = qdoc qhp.Qt.indexTitle = Qt Reference Documentation qhp.Qt.indexRoot = @@ -36,9 +36,9 @@ qhp.Qt.extraFiles = classic.css \ images/dynamiclayouts-example.png \ images/stylesheet-coffee-plastique.png -qhp.Qt.filterAttributes = qt 4.6.0 qtrefdoc -qhp.Qt.customFilters.Qt.name = Qt 4.6.0 -qhp.Qt.customFilters.Qt.filterAttributes = qt 4.6.0 +qhp.Qt.filterAttributes = qt 4.7.0 qtrefdoc +qhp.Qt.customFilters.Qt.name = Qt 4.7.0 +qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.0 qhp.Qt.subprojects = classes overviews examples qhp.Qt.subprojects.classes.title = Classes qhp.Qt.subprojects.classes.indexTitle = Qt's Classes diff --git a/tools/qdoc3/doc/qdoc-manual.qdoc b/tools/qdoc3/doc/qdoc-manual.qdoc index 57c17ba..c3ab731 100644 --- a/tools/qdoc3/doc/qdoc-manual.qdoc +++ b/tools/qdoc3/doc/qdoc-manual.qdoc @@ -8075,6 +8075,27 @@ qhp.Qt.subprojects.examples.indexTitle = Qt Examples qhp.Qt.subprojects.examples.selectors = fake:example \endcode + + To create a table of contents for a manual, create a subproject with + a \c{type} property and set it to \c{manual}. The page in the documentation + referred to by the \c{indexTitle} property must contain a list of links + that acts as a table of contents for the whole manual. QDoc will take the + information in this list and create a table of contents for the subproject. + + For example, the configuration file for Qt Creator defines only one + subproject for its documentation, including all the documentation in a + single manual: + + \code + qhp.QtCreator.subprojects = manual + qhp.QtCreator.subprojects.manual.title = Qt Creator Manual + qhp.QtCreator.subprojects.manual.indexTitle = Qt Creator Manual + qhp.QtCreator.subprojects.manual.type = manual + \endcode + + In this example, the page entitled "Qt Creator Manual" contains a nested + list of links to pages in the documentation which is duplicated in + Qt Assistant's Contents tab. */ /*! diff --git a/tools/qdoc3/helpprojectwriter.cpp b/tools/qdoc3/helpprojectwriter.cpp index edba097..98246c4 100644 --- a/tools/qdoc3/helpprojectwriter.cpp +++ b/tools/qdoc3/helpprojectwriter.cpp @@ -41,7 +41,7 @@ #include <QHash> #include <QMap> -#include <qdebug.h> +//#include <qdebug.h> #include "atom.h" #include "helpprojectwriter.h" @@ -91,6 +91,7 @@ HelpProjectWriter::HelpProjectWriter(const Config &config, const QString &defaul subproject.title = config.getString(subprefix + "title"); subproject.indexTitle = config.getString(subprefix + "indexTitle"); subproject.sortPages = config.getBool(subprefix + "sortPages"); + subproject.type = config.getString(subprefix + "type"); readSelectors(subproject, config.getStringList(subprefix + "selectors")); project.subprojects[name] = subproject; } @@ -625,44 +626,99 @@ void HelpProjectWriter::generateProject(HelpProject &project) foreach (const QString &name, project.subprojects.keys()) { SubProject subproject = project.subprojects[name]; - if (!name.isEmpty()) { - writer.writeStartElement("section"); - QString indexPath = tree->fullDocumentLocation(tree->findFakeNodeByTitle(subproject.indexTitle)); - writer.writeAttribute("ref", HtmlGenerator::cleanRef(indexPath)); - writer.writeAttribute("title", subproject.title); - project.files.insert(indexPath); - } - if (subproject.sortPages) { - QStringList titles = subproject.nodes.keys(); - titles.sort(); - foreach (const QString &title, titles) - writeNode(project, writer, subproject.nodes[title]); + if (subproject.type == QLatin1String("manual")) { + + const FakeNode *indexPage = tree->findFakeNodeByTitle(subproject.indexTitle); + if (indexPage) { + Text indexBody = indexPage->doc().body(); + const Atom *atom = indexBody.firstAtom(); + QStack<int> sectionStack; + bool inItem = false; + + while (atom) { + switch (atom->type()) { + case Atom::ListLeft: + sectionStack.push(0); + break; + case Atom::ListRight: + if (sectionStack.pop() > 0) + writer.writeEndElement(); // section + break; + case Atom::ListItemLeft: + inItem = true; + break; + case Atom::ListItemRight: + inItem = false; + break; + case Atom::Link: + if (inItem) { + if (sectionStack.top() > 0) + writer.writeEndElement(); // section + + const FakeNode *page = tree->findFakeNodeByTitle(atom->string()); + writer.writeStartElement("section"); + QString indexPath = tree->fullDocumentLocation(page); + writer.writeAttribute("ref", HtmlGenerator::cleanRef(indexPath)); + writer.writeAttribute("title", atom->string()); + project.files.insert(indexPath); + + sectionStack.top() += 1; + } + break; + default: + ; + } + + if (atom == indexBody.lastAtom()) + break; + atom = atom->next(); + } + } else + rootNode->doc().location().warning( + tr("Failed to find index: %1").arg(subproject.indexTitle) + ); + } else { - // Find a contents node and navigate from there, using the NextLink values. - foreach (const Node *node, subproject.nodes) { - QString nextTitle = node->links().value(Node::NextLink).first; - if (!nextTitle.isEmpty() && - node->links().value(Node::ContentsLink).first.isEmpty()) { - - FakeNode *nextPage = const_cast<FakeNode *>(tree->findFakeNodeByTitle(nextTitle)); - - // Write the contents node. - writeNode(project, writer, node); - - while (nextPage) { - writeNode(project, writer, nextPage); - nextTitle = nextPage->links().value(Node::NextLink).first; - if(nextTitle.isEmpty()) - break; - nextPage = const_cast<FakeNode *>(tree->findFakeNodeByTitle(nextTitle)); + + if (!name.isEmpty()) { + writer.writeStartElement("section"); + QString indexPath = tree->fullDocumentLocation(tree->findFakeNodeByTitle(subproject.indexTitle)); + writer.writeAttribute("ref", HtmlGenerator::cleanRef(indexPath)); + writer.writeAttribute("title", subproject.title); + project.files.insert(indexPath); + } + if (subproject.sortPages) { + QStringList titles = subproject.nodes.keys(); + titles.sort(); + foreach (const QString &title, titles) + writeNode(project, writer, subproject.nodes[title]); + } else { + // Find a contents node and navigate from there, using the NextLink values. + foreach (const Node *node, subproject.nodes) { + QString nextTitle = node->links().value(Node::NextLink).first; + if (!nextTitle.isEmpty() && + node->links().value(Node::ContentsLink).first.isEmpty()) { + + FakeNode *nextPage = const_cast<FakeNode *>(tree->findFakeNodeByTitle(nextTitle)); + + // Write the contents node. + writeNode(project, writer, node); + + while (nextPage) { + writeNode(project, writer, nextPage); + nextTitle = nextPage->links().value(Node::NextLink).first; + if(nextTitle.isEmpty()) + break; + nextPage = const_cast<FakeNode *>(tree->findFakeNodeByTitle(nextTitle)); + } + break; } - break; } } - } - if (!name.isEmpty()) - writer.writeEndElement(); // section + if (!name.isEmpty()) + writer.writeEndElement(); // section + } } writer.writeEndElement(); // section diff --git a/tools/qdoc3/helpprojectwriter.h b/tools/qdoc3/helpprojectwriter.h index 511a9dd..7a67dff 100644 --- a/tools/qdoc3/helpprojectwriter.h +++ b/tools/qdoc3/helpprojectwriter.h @@ -60,6 +60,7 @@ struct SubProject QString indexTitle; QHash<Node::Type, QSet<FakeNode::SubType> > selectors; bool sortPages; + QString type; QHash<QString, const Node *> nodes; }; diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index b93db4f..89b1e98 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE #define COMMAND_VERSION Doc::alias("version") int HtmlGenerator::id = 0; +bool HtmlGenerator::debugging_on = false; QString HtmlGenerator::sinceTitles[] = { @@ -443,7 +444,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, { int skipAhead = 0; static bool in_para = false; - + switch (atom->type()) { case Atom::AbstractLeft: break; @@ -1066,11 +1067,11 @@ int HtmlGenerator::generateAtom(const Atom *atom, } sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1); } - out() << "<a name=\"sec-" << sectionNumber.join("-") << "\"></a>\n"; + out() << "<a name=\"sec-" << sectionNumber.join("-") << "\"></a><div class=\"navTop\"><a href=\"#toc\"><img src=\"./images/bullet_up.png\"></a></div>\n"; } #else out() << "<a name=\"" << Doc::canonicalTitle(Text::sectionHeading(atom).toString()) - << "\"></a>\n"; + << "\"></a><div class=\"navTop\"><a href=\"#toc\"><img src=\"./images/bullet_up.png\"></a></div>\n"; #endif break; case Atom::SectionRight: @@ -1339,26 +1340,26 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, } else { if (!s->members.isEmpty()) { - out() << "<hr />\n"; + // out() << "<hr />\n"; out() << "<a name=\"" << registerRef((*s).name.toLower()) - << "\"></a>\n"; + << "\"></a><div class=\"navTop\"><a href=\"#toc\"><img src=\"./images/bullet_up.png\"></a></div>\n"; out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; generateSection(s->members, inner, marker, CodeMarker::Summary); } if (!s->reimpMembers.isEmpty()) { QString name = QString("Reimplemented ") + (*s).name; - out() << "<hr />\n"; + // out() << "<hr />\n"; out() << "<a name=\"" << registerRef(name.toLower()) - << "\"></a>\n"; + << "\"></a><div class=\"navTop\"><a href=\"#toc\"><img src=\"./images/bullet_up.png\"></a></div>\n"; out() << "<h2>" << protectEnc(name) << "</h2>\n"; generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary); } if (!s->inherited.isEmpty()) { out() << "<ul>\n"; - generateSectionInheritedList(*s, inner, marker, true); + generateSectionInheritedList(*s, inner, marker); out() << "</ul>\n"; } } @@ -1378,11 +1379,11 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, out() << "</ul>\n"; } - out() << "<a name=\"" << registerRef("details") << "\"></a>\n"; + out() << "<a name=\"" << registerRef("details") << "\"></a><div class=\"navTop\"><a href=\"#toc\"><img src=\"./images/bullet_up.png\"></a></div>\n"; if (!inner->doc().isEmpty()) { - out() << "<hr />\n" - << "<div class=\"descr\"/>\n" // QTBUG-9504 + //out() << "<hr />\n" + out() << "<div class=\"descr\"/>\n" // QTBUG-9504 << "<h2>" << "Detailed Description" << "</h2>\n"; generateBody(inner, marker); out() << "</div>\n"; // QTBUG-9504 @@ -1392,7 +1393,7 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, sections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { - out() << "<hr />\n"; + //out() << "<hr />\n"; if (!(*s).divClass.isEmpty()) out() << "<div class=\"" << (*s).divClass << "\"/>\n"; // QTBUG-9504 out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; @@ -1518,12 +1519,12 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) generateStatus(fake, marker); if (moduleNamespaceMap.contains(fake->name())) { - out() << "<a name=\"" << registerRef("namespaces") << "\"></a>\n"; + out() << "<a name=\"" << registerRef("namespaces") << "\"></a><div class=\"navTop\"><a href=\"#toc\"><img src=\"./images/bullet_up.png\"></a></div>\n"; out() << "<h2>Namespaces</h2>\n"; generateAnnotatedList(fake, marker, moduleNamespaceMap[fake->name()]); } if (moduleClassMap.contains(fake->name())) { - out() << "<a name=\"" << registerRef("classes") << "\"></a>\n"; + out() << "<a name=\"" << registerRef("classes") << "\"></a><div class=\"navTop\"><a href=\"#toc\"><img src=\"./images/bullet_up.png\"></a></div>\n"; out() << "<h2>Classes</h2>\n"; generateAnnotatedList(fake, marker, moduleClassMap[fake->name()]); } @@ -1586,19 +1587,19 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) sections = marker->qmlSections(qml_cn,CodeMarker::Summary); s = sections.begin(); while (s != sections.end()) { - out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n"; + out() << "<a name=\"" << registerRef((*s).name) << "\"></a><div class=\"navTop\"><a href=\"#toc\"><img src=\"./images/bullet_up.png\"></a></div>\n"; out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; generateQmlSummary(*s,fake,marker); ++s; } - out() << "<a name=\"" << registerRef("details") << "\"></a>\n"; + out() << "<a name=\"" << registerRef("details") << "\"></a><div class=\"navTop\"><a href=\"#toc\"><img src=\"./images/bullet_up.png\"></a></div>\n"; out() << "<h2>" << "Detailed Description" << "</h2>\n"; generateBody(fake, marker); if (cn) generateQmlText(cn->doc().body(), cn, marker, fake->name()); generateAlsoList(fake, marker); - out() << "<hr />\n"; + //out() << "<hr />\n"; sections = marker->qmlSections(qml_cn,CodeMarker::Detailed); s = sections.begin(); @@ -1622,7 +1623,7 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) sections = marker->sections(fake, CodeMarker::Summary, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { - out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n"; + out() << "<a name=\"" << registerRef((*s).name) << "\"></a><div class=\"navTop\"><a href=\"#toc\"><img src=\"./images/bullet_up.png\"></a></div>\n"; out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; generateSectionList(*s, fake, marker, CodeMarker::Summary); ++s; @@ -1630,7 +1631,7 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) Text brief = fake->doc().briefText(); if (fake->subType() == Node::Module && !brief.isEmpty()) { - out() << "<a name=\"" << registerRef("details") << "\"></a>\n"; + out() << "<a name=\"" << registerRef("details") << "\"></a><div class=\"navTop\"><a href=\"#toc\"><img src=\"./images/bullet_up.png\"></a></div>\n"; out() << "<div class=\"descr\"/>\n"; // QTBUG-9504 out() << "<h2>" << "Detailed Description" << "</h2>\n"; } @@ -1655,7 +1656,7 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) sections = marker->sections(fake, CodeMarker::Detailed, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { - out() << "<hr />\n"; + //out() << "<hr />\n"; out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; NodeList::ConstIterator m = (*s).members.begin(); @@ -1801,9 +1802,10 @@ void HtmlGenerator::generateHeader(const QString& title, if (offlineDocs) { - out() << " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/OfflineStyle.css\" />"; + out() << " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\" />"; out() << "</head>\n"; out() << "<body class=\"offline narrow\" >\n"; // narrow mainly for Creator + out() << " <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n"; } else { @@ -2039,7 +2041,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node, inLink = true; out() << "<div class=\"toc\">\n"; - out() << "<h3>Contents</h3>\n"; + out() << "<h3><a name=\"toc\">Contents</a></h3>\n"; sectionNumber.append("1"); out() << "<ul>\n"; @@ -2252,7 +2254,7 @@ QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, sections = marker->sections(inner, CodeMarker::Detailed, status); for (i = 0; i < sections.size(); ++i) { - out() << "<hr />\n"; + //out() << "<hr />\n"; out() << "<h2>" << protectEnc(sections.at(i).name) << "</h2>\n"; NodeList::ConstIterator m = sections.at(i).members.begin(); @@ -2621,7 +2623,7 @@ void HtmlGenerator::generateLegaleseList(const Node *relative, QMap<Text, const Node *>::ConstIterator it = legaleseTexts.begin(); while (it != legaleseTexts.end()) { Text text = it.key(); - out() << "<hr />\n"; + //out() << "<hr />\n"; generateText(text, relative, marker); out() << "<ul>\n"; do { @@ -2634,44 +2636,6 @@ void HtmlGenerator::generateLegaleseList(const Node *relative, } } -/*void HtmlGenerator::generateSynopsis(const Node *node, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style) -{ - QString marked = marker->markedUpSynopsis(node, relative, style); - QRegExp templateTag("(<[^@>]*>)"); - if (marked.indexOf(templateTag) != -1) { - QString contents = protectEnc(marked.mid(templateTag.pos(1), - templateTag.cap(1).length())); - marked.replace(templateTag.pos(1), templateTag.cap(1).length(), - contents); - } - marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), - "<i>\\1<sub>\\2</sub></i>"); - marked.replace("<@param>", "<i>"); - marked.replace("</@param>", "</i>"); - - if (style == CodeMarker::Summary) - marked.replace("@name>", "b>"); - - if (style == CodeMarker::SeparateList) { - QRegExp extraRegExp("<@extra>.*</@extra>"); - extraRegExp.setMinimal(true); - marked.replace(extraRegExp, ""); - } - else { - marked.replace("<@extra>", " <tt>"); - marked.replace("</@extra>", "</tt>"); - } - - if (style != CodeMarker::Detailed) { - marked.replace("<@type>", ""); - marked.replace("</@type>", ""); - } - out() << highlightedCode(marked, marker, relative); -}*/ - #ifdef QDOC_QML void HtmlGenerator::generateQmlItem(const Node *node, const Node *relative, @@ -2701,7 +2665,19 @@ void HtmlGenerator::generateQmlItem(const Node *node, marked.replace("<@type>", ""); marked.replace("</@type>", ""); } + if (node->type() == Node::QmlProperty) { + const QmlPropertyNode* qpn = static_cast<const QmlPropertyNode*>(node); + if (!summary && qpn->name() == "color" && qpn->dataType() == "color") { + if (relative && relative->name() == "GradientStop") { + qDebug() << "color : color"; + debugging_on = true; + qDebug() << " " << relative->name() << relative->type() << relative->subType(); + qDebug() << marked; + } + } + } out() << highlightedCode(marked, marker, relative); + debugging_on = false; } #endif @@ -2819,24 +2795,23 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m } } -#ifdef QDOC_NAME_ALIGNMENT void HtmlGenerator::generateSection(const NodeList& nl, const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style) { - bool name_alignment = true; + bool alignNames = true; if (!nl.isEmpty()) { bool twoColumn = false; if (style == CodeMarker::SeparateList) { - name_alignment = false; + alignNames = false; twoColumn = (nl.count() >= 16); } else if (nl.first()->type() == Node::Property) { twoColumn = (nl.count() >= 5); - name_alignment = false; + alignNames = false; } - if (name_alignment) { + if (alignNames) { out() << "<table class=\"alignedsummary\">\n"; } else { @@ -2854,7 +2829,7 @@ void HtmlGenerator::generateSection(const NodeList& nl, continue; } - if (name_alignment) { + if (alignNames) { out() << "<tr><td class=\"memItemLeft rightAlign topAlign\"> "; } else { @@ -2863,15 +2838,15 @@ void HtmlGenerator::generateSection(const NodeList& nl, out() << "<li class=\"fn\">"; } - generateSynopsis(*m, relative, marker, style, name_alignment); - if (name_alignment) + generateSynopsis(*m, relative, marker, style, alignNames); + if (alignNames) out() << "</td></tr>\n"; else out() << "</li>\n"; i++; ++m; } - if (name_alignment) + if (alignNames) out() << "</table>\n"; else { out() << "</ul>\n"; @@ -2886,18 +2861,18 @@ void HtmlGenerator::generateSectionList(const Section& section, CodeMarker *marker, CodeMarker::SynopsisStyle style) { - bool name_alignment = true; + bool alignNames = true; if (!section.members.isEmpty()) { bool twoColumn = false; if (style == CodeMarker::SeparateList) { - name_alignment = false; + alignNames = false; twoColumn = (section.members.count() >= 16); } else if (section.members.first()->type() == Node::Property) { twoColumn = (section.members.count() >= 5); - name_alignment = false; + alignNames = false; } - if (name_alignment) { + if (alignNames) { out() << "<table class=\"alignedsummary\">\n"; } else { @@ -2915,7 +2890,7 @@ void HtmlGenerator::generateSectionList(const Section& section, continue; } - if (name_alignment) { + if (alignNames) { out() << "<tr><td class=\"memItemLeft topAlign rightAlign\"> "; } else { @@ -2924,15 +2899,15 @@ void HtmlGenerator::generateSectionList(const Section& section, out() << "<li class=\"fn\">"; } - generateSynopsis(*m, relative, marker, style, name_alignment); - if (name_alignment) + generateSynopsis(*m, relative, marker, style, alignNames); + if (alignNames) out() << "</td></tr>\n"; else out() << "</li>\n"; i++; ++m; } - if (name_alignment) + if (alignNames) out() << "</table>\n"; else { out() << "</ul>\n"; @@ -2943,22 +2918,18 @@ void HtmlGenerator::generateSectionList(const Section& section, if (style == CodeMarker::Summary && !section.inherited.isEmpty()) { out() << "<ul>\n"; - generateSectionInheritedList(section, relative, marker, name_alignment); + generateSectionInheritedList(section, relative, marker); out() << "</ul>\n"; } } void HtmlGenerator::generateSectionInheritedList(const Section& section, const Node *relative, - CodeMarker *marker, - bool nameAlignment) + CodeMarker *marker) { QList<QPair<ClassNode *, int> >::ConstIterator p = section.inherited.begin(); while (p != section.inherited.end()) { - if (nameAlignment) - out() << "<li class=\"fn\">"; - else - out() << "<li class=\"fn\">"; + out() << "<li class=\"fn\">"; out() << (*p).second << " "; if ((*p).second == 1) { out() << section.singularMember; @@ -2978,7 +2949,7 @@ void HtmlGenerator::generateSynopsis(const Node *node, const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style, - bool nameAlignment) + bool alignNames) { QString marked = marker->markedUpSynopsis(node, relative, style); QRegExp templateTag("(<[^@>]*>)"); @@ -3011,14 +2982,13 @@ void HtmlGenerator::generateSynopsis(const Node *node, marked.replace("<@type>", ""); marked.replace("</@type>", ""); } - out() << highlightedCode(marked, marker, relative, style, nameAlignment); + out() << highlightedCode(marked, marker, relative, alignNames); } QString HtmlGenerator::highlightedCode(const QString& markedCode, - CodeMarker *marker, - const Node *relative, - CodeMarker::SynopsisStyle , - bool nameAlignment) + CodeMarker* marker, + const Node* relative, + bool alignNames) { QString src = markedCode; QString html; @@ -3028,20 +2998,24 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, const QChar charLangle = '<'; const QChar charAt = '@'; - // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)" + static const QString typeTag("type"); + static const QString headerTag("headerfile"); + static const QString funcTag("func"); static const QString linkTag("link"); + + // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)" bool done = false; - for (int i = 0, n = src.size(); i < n;) { + for (int i = 0, srcSize = src.size(); i < srcSize;) { if (src.at(i) == charLangle && src.at(i + 1).unicode() == '@') { - if (nameAlignment && !done) {// && (i != 0)) Why was this here? + if (alignNames && !done) {// && (i != 0)) Why was this here? html += "</td><td class=\"memItemRight bottomAlign\">"; done = true; } i += 2; - if (parseArg(src, linkTag, &i, n, &arg, &par1)) { + if (parseArg(src, linkTag, &i, srcSize, &arg, &par1)) { html += "<b>"; - QString link = linkForNode( - CodeMarker::nodeForString(par1.toString()), relative); + const Node* n = CodeMarker::nodeForString(par1.toString()); + QString link = linkForNode(n, relative); addLink(link, arg, &html); html += "</b>"; } @@ -3061,16 +3035,14 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)" src = html; html = QString(); - static const QString funcTag("func"); - for (int i = 0, n = src.size(); i < n;) { + for (int i = 0, srcSize = src.size(); i < srcSize;) { if (src.at(i) == charLangle && src.at(i + 1) == charAt) { i += 2; - if (parseArg(src, funcTag, &i, n, &arg, &par1)) { - QString link = linkForNode( - marker->resolveTarget(par1.toString(), - myTree, - relative), - relative); + if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) { + const Node* n = marker->resolveTarget(par1.toString(), + myTree, + relative); + QString link = linkForNode(n, relative); addLink(link, arg, &html); par1 = QStringRef(); } @@ -3088,296 +3060,36 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags src = html; html = QString(); - static const QString typeTags[] = { "type", "headerfile", "func" }; - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { + + for (int i=0, srcSize=src.size(); i<srcSize;) { + if (src.at(i) == charLangle && src.at(i+1) == charAt) { i += 2; bool handled = false; - for (int k = 0; k != 3; ++k) { - if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) { - par1 = QStringRef(); - QString link = linkForNode( - marker->resolveTarget(arg.toString(), myTree, relative), - relative); - addLink(link, arg, &html); - handled = true; - break; + if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) { + par1 = QStringRef(); + const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); + if (HtmlGenerator::debugging_on) { + if (n) { + qDebug() << " " << n->name() << n->type() << n->subType(); + qDebug() << " " << relative->name() << relative->type() << relative->subType(); + } } + addLink(linkForNode(n,relative), arg, &html); + handled = true; } - if (!handled) { - html += charLangle; - html += charAt; + else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) { + par1 = QStringRef(); + const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); + addLink(linkForNode(n,relative), arg, &html); + handled = true; } - } - else { - html += src.at(i++); - } - } - - // replace all - // "<@comment>" -> "<span class=\"comment\">"; - // "<@preprocessor>" -> "<span class=\"preprocessor\">"; - // "<@string>" -> "<span class=\"string\">"; - // "<@char>" -> "<span class=\"char\">"; - // "</@(?:comment|preprocessor|string|char)>" -> "</span>" - src = html; - html = QString(); - static const QString spanTags[] = { - "<@comment>", "<span class=\"comment\">", - "<@preprocessor>", "<span class=\"preprocessor\">", - "<@string>", "<span class=\"string\">", - "<@char>", "<span class=\"char\">", - "</@comment>", "</span>", - "</@preprocessor>","</span>", - "</@string>", "</span>", - "</@char>", "</span>" - // "<@char>", "<font color=blue>", - // "</@char>", "</font>", - // "<@func>", "<font color=green>", - // "</@func>", "</font>", - // "<@id>", "<i>", - // "</@id>", "</i>", - // "<@keyword>", "<b>", - // "</@keyword>", "</b>", - // "<@number>", "<font color=yellow>", - // "</@number>", "</font>", - // "<@op>", "<b>", - // "</@op>", "</b>", - // "<@param>", "<i>", - // "</@param>", "</i>", - // "<@string>", "<font color=green>", - // "</@string>", "</font>", - }; - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle) { - bool handled = false; - for (int k = 0; k != 8; ++k) { - const QString & tag = spanTags[2 * k]; - if (tag == QStringRef(&src, i, tag.length())) { - html += spanTags[2 * k + 1]; - i += tag.length(); - handled = true; - break; - } - } - if (!handled) { - ++i; - if (src.at(i) == charAt || - (src.at(i) == QLatin1Char('/') && src.at(i + 1) == charAt)) { - // drop 'our' unknown tags (the ones still containing '@') - while (i < n && src.at(i) != QLatin1Char('>')) - ++i; - ++i; - } - else { - // retain all others - html += charLangle; - } + else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) { + par1 = QStringRef(); + const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); + addLink(linkForNode(n,relative), arg, &html); + handled = true; } - } - else { - html += src.at(i); - ++i; - } - } - - return html; -} - -#else -void HtmlGenerator::generateSectionList(const Section& section, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style) -{ - if (!section.members.isEmpty()) { - bool twoColumn = false; - if (style == CodeMarker::SeparateList) { - twoColumn = (section.members.count() >= 16); - } - else if (section.members.first()->type() == Node::Property) { - twoColumn = (section.members.count() >= 5); - } - if (twoColumn) - out() << "<table class=\"generic\">\n"; - if (++numTableRows % 2 == 1) - out() << "<tr class=\"odd topAlign\">"; - else - out() << "<tr class=\"even topAlign\">"; - -// << "<tr><td class=\"topAlign\">"; - out() << "<ul>\n"; - int i = 0; - NodeList::ConstIterator m = section.members.begin(); - while (m != section.members.end()) { - if ((*m)->access() == Node::Private) { - ++m; - continue; - } - - if (twoColumn && i == (int) (section.members.count() + 1) / 2) - out() << "</ul></td><td class=\"topAlign\"><ul>\n"; - - out() << "<li class=\"fn\">"; - if (style == CodeMarker::Accessors) - out() << "<b>"; - generateSynopsis(*m, relative, marker, style); - if (style == CodeMarker::Accessors) - out() << "</b>"; - out() << "</li>\n"; - i++; - ++m; - } - out() << "</ul>\n"; - if (twoColumn) - out() << "</td></tr>\n</table>\n"; - } - - if (style == CodeMarker::Summary && !section.inherited.isEmpty()) { - out() << "<ul>\n"; - generateSectionInheritedList(section, relative, marker); - out() << "</ul>\n"; - } -} - -void HtmlGenerator::generateSectionInheritedList(const Section& section, - const Node *relative, - CodeMarker *marker) -{ - QList<QPair<ClassNode *, int> >::ConstIterator p = section.inherited.begin(); - while (p != section.inherited.end()) { - out() << "<li class=\"fn\">"; - out() << (*p).second << " "; - if ((*p).second == 1) { - out() << section.singularMember; - } else { - out() << section.pluralMember; - } - out() << " inherited from <a href=\"" << fileName((*p).first) - << "#" << HtmlGenerator::cleanRef(section.name.toLower()) << "\">" - << protectEnc(marker->plainFullName((*p).first, relative)) - << "</a></li>\n"; - ++p; - } -} - -void HtmlGenerator::generateSynopsis(const Node *node, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style) -{ - QString marked = marker->markedUpSynopsis(node, relative, style); - QRegExp templateTag("(<[^@>]*>)"); - if (marked.indexOf(templateTag) != -1) { - QString contents = protectEnc(marked.mid(templateTag.pos(1), - templateTag.cap(1).length())); - marked.replace(templateTag.pos(1), templateTag.cap(1).length(), - contents); - } - marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), "<i>\\1<sub>\\2</sub></i>"); - marked.replace("<@param>", "<i>"); - marked.replace("</@param>", "</i>"); - - if (style == CodeMarker::Summary) - marked.replace("@name>", "b>"); - - if (style == CodeMarker::SeparateList) { - QRegExp extraRegExp("<@extra>.*</@extra>"); - extraRegExp.setMinimal(true); - marked.replace(extraRegExp, ""); - } else { - marked.replace("<@extra>", "<tt>"); - marked.replace("</@extra>", "</tt>"); - } - - if (style != CodeMarker::Detailed) { - marked.replace("<@type>", ""); - marked.replace("</@type>", ""); - } - out() << highlightedCode(marked, marker, relative); -} - -QString HtmlGenerator::highlightedCode(const QString& markedCode, - CodeMarker *marker, - const Node *relative) -{ - QString src = markedCode; - QString html; - QStringRef arg; - QStringRef par1; - - const QChar charLangle = '<'; - const QChar charAt = '@'; - - // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)" - static const QString linkTag("link"); - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { - i += 2; - if (parseArg(src, linkTag, &i, n, &arg, &par1)) { - const Node* node = CodeMarker::nodeForString(par1.toString()); - QString link = linkForNode(node, relative); - addLink(link, arg, &html); - } - else { - html += charLangle; - html += charAt; - } - } - else { - html += src.at(i++); - } - } - - if (slow) { - // is this block ever used at all? - // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)" - src = html; - html = QString(); - static const QString funcTag("func"); - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { - i += 2; - if (parseArg(src, funcTag, &i, n, &arg, &par1)) { - QString link = linkForNode( - marker->resolveTarget(par1.toString(), - myTree, - relative), - relative); - addLink(link, arg, &html); - par1 = QStringRef(); - } - else { - html += charLangle; - html += charAt; - } - } - else { - html += src.at(i++); - } - } - } - - // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags - src = html; - html = QString(); - static const QString typeTags[] = { "type", "headerfile", "func" }; - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { - i += 2; - bool handled = false; - for (int k = 0; k != 3; ++k) { - if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) { - par1 = QStringRef(); - QString link = linkForNode( - marker->resolveTarget(arg.toString(), myTree, relative), - relative); - addLink(link, arg, &html); - handled = true; - break; - } - } if (!handled) { html += charLangle; html += charAt; @@ -3405,22 +3117,6 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, "</@preprocessor>","</span>", "</@string>", "</span>", "</@char>", "</span>" - // "<@char>", "<font color=blue>", - // "</@char>", "</font>", - // "<@func>", "<font color=green>", - // "</@func>", "</font>", - // "<@id>", "<i>", - // "</@id>", "</i>", - // "<@keyword>", "<b>", - // "</@keyword>", "</b>", - // "<@number>", "<font color=yellow>", - // "</@number>", "</font>", - // "<@op>", "<b>", - // "</@op>", "</b>", - // "<@param>", "<i>", - // "</@param>", "</i>", - // "<@string>", "<font color=green>", - // "</@string>", "</font>", }; for (int i = 0, n = src.size(); i < n;) { if (src.at(i) == charLangle) { @@ -3457,7 +3153,6 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, return html; } -#endif void HtmlGenerator::generateLink(const Atom* atom, const Node* /* relative */, @@ -3828,7 +3523,7 @@ void HtmlGenerator::generateDetailedMember(const Node *node, out() << "<h3 class=\"fn\">"; out() << "<a name=\"" + refForNode(node) + "\"></a>"; generateSynopsis(node, relative, marker, CodeMarker::Detailed); - out() << "</h3>\n"; + out() << "</h3><div class=\"navTop\"><a href=\"#toc\"><img src=\"./images/bullet_up.png\"></a></div>\n"; } generateStatus(node, marker); @@ -4413,6 +4108,7 @@ void HtmlGenerator::generateQmlSummary(const Section& section, bool twoColumn = false; if (section.members.first()->type() == Node::QmlProperty) { twoColumn = (count >= 5); + twoColumn = false; } if (twoColumn) out() << "<table class=\"qmlsummary\">\n"; @@ -4462,14 +4158,13 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node, while (p != qpgn->childNodes().end()) { if ((*p)->type() == Node::QmlProperty) { qpn = static_cast<const QmlPropertyNode*>(*p); - - if (++numTableRows % 2 == 1) - out() << "<tr class=\"odd\">"; - else - out() << "<tr class=\"even\">"; + if (++numTableRows % 2 == 1) + out() << "<tr class=\"odd\">"; + else + out() << "<tr class=\"even\">"; - out() << "<td><p>"; - //out() << "<tr><td>"; // old + out() << "<td><p>"; + out() << "<a name=\"" + refForNode(qpn) + "\"></a>"; if (!qpn->isWritable()) out() << "<span class=\"qmlreadonly\">read-only</span>"; diff --git a/tools/qdoc3/htmlgenerator.h b/tools/qdoc3/htmlgenerator.h index e060257..80341de 100644 --- a/tools/qdoc3/htmlgenerator.h +++ b/tools/qdoc3/htmlgenerator.h @@ -46,8 +46,6 @@ #ifndef HTMLGENERATOR_H #define HTMLGENERATOR_H -#define QDOC_NAME_ALIGNMENT - #include <qmap.h> #include <qregexp.h> #include <QXmlStreamWriter> @@ -198,7 +196,7 @@ class HtmlGenerator : public PageGenerator void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker); void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker); #endif -#ifdef QDOC_NAME_ALIGNMENT + void generateSection(const NodeList& nl, const Node *relative, CodeMarker *marker, @@ -207,28 +205,15 @@ class HtmlGenerator : public PageGenerator const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style, - bool nameAlignment = false); - void generateSectionInheritedList(const Section& section, - const Node *relative, - CodeMarker *marker, - bool nameAlignment = false); - QString highlightedCode(const QString& markedCode, - CodeMarker *marker, - const Node *relative, - CodeMarker::SynopsisStyle style = CodeMarker::Accessors, - bool nameAlignment = false); -#else - void generateSynopsis(const Node *node, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style); + bool alignNames = false); void generateSectionInheritedList(const Section& section, const Node *relative, CodeMarker *marker); QString highlightedCode(const QString& markedCode, CodeMarker *marker, - const Node *relative); -#endif + const Node *relative, + bool alignNames = false); + void generateFullName(const Node *apparentNode, const Node *relative, CodeMarker *marker, @@ -341,6 +326,8 @@ class HtmlGenerator : public PageGenerator NewClassMaps newClassMaps; NewClassMaps newQmlClassMaps; static int id; + public: + static bool debugging_on; }; #define HTMLGENERATOR_ADDRESS "address" diff --git a/tools/qdoc3/test/qdeclarative.qdocconf b/tools/qdoc3/test/qdeclarative.qdocconf index 74fd802..facec5c 100644 --- a/tools/qdoc3/test/qdeclarative.qdocconf +++ b/tools/qdoc3/test/qdeclarative.qdocconf @@ -6,7 +6,7 @@ include(qt-defines.qdocconf) project = Qml description = Qml Reference Documentation -url = http://qt.nokia.com/doc/4.6/ +url = http://qt.nokia.com/doc/4.7/ qmlonly = true edition.Console.modules = QtCore QtDBus QtNetwork QtScript QtSql QtXml \ @@ -21,7 +21,7 @@ edition.DesktopLight.groups = -graphicsview-api qhp.projects = Qml qhp.Qml.file = qml.qhp -qhp.Qml.namespace = com.trolltech.qml.460 +qhp.Qml.namespace = com.trolltech.qml.470 qhp.Qml.virtualFolder = qdoc qhp.Qml.indexTitle = Qml Reference @@ -55,9 +55,9 @@ qhp.Qml.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.Qml.filterAttributes = qt 4.6.0 qtrefdoc -qhp.Qml.customFilters.Qt.name = Qt 4.6.0 -qhp.Qml.customFilters.Qt.filterAttributes = qt 4.6.0 +qhp.Qml.filterAttributes = qt 4.7.0 qtrefdoc +qhp.Qml.customFilters.Qt.name = Qt 4.7.0 +qhp.Qml.customFilters.Qt.filterAttributes = qt 4.7.0 qhp.Qml.subprojects = classes qhp.Qml.subprojects.classes.title = Elements qhp.Qml.subprojects.classes.indexTitle = Qml Elements diff --git a/tools/qdoc3/test/qt-html-templates.qdocconf b/tools/qdoc3/test/qt-html-templates.qdocconf index b82e337..31c9d5a 100644 --- a/tools/qdoc3/test/qt-html-templates.qdocconf +++ b/tools/qdoc3/test/qt-html-templates.qdocconf @@ -11,7 +11,7 @@ HTML.postheader = " <div class=\"header\" id=\"qtdocheader\">\n" \ " <a href=\"index.html\" class=\"qtref\"><span>Qt Reference Documentation</span></a>\n" \ " <div id=\"narrowsearch\"><form onsubmit=\"return false;\" action=\"\" id=\"qtdocsearch\">\n" \ " <fieldset>\n" \ - " <input type=\"text\" value=\"\" id=\"pageType2\" name=\"searchstring\">\n" \ + " <input type=\"text\" value=\"\" id=\"pageType2\" name=\"searchstring\"/>\n" \ " </fieldset>\n" \ " </form></div>\n" \ " <div id=\"nav-topright\">\n" \ @@ -49,6 +49,7 @@ HTML.postheader = " <div class=\"header\" id=\"qtdocheader\">\n" \ " <li><a href=\"declarativeui.html\">Device UI's & Qt Quick</a></li> \n" \ " <li><a href=\"qt-gui-concepts.html\">Desktop UI components</a></li> \n" \ " <li><a href=\"platform-specific.html\">Platform-specific info</a></li> \n" \ + " <li><a href=\"best-practices.html\">How-To's and Best Practices</a></li> \n" \ " </ul> \n" \ " </li> \n" \ " <li><a href=\"#\">Examples</a> \n" \ @@ -57,7 +58,6 @@ HTML.postheader = " <div class=\"header\" id=\"qtdocheader\">\n" \ " <li><a href=\"tutorials.html\">Tutorials</a></li> \n" \ " <li><a href=\"demos.html\">Demos</a></li> \n" \ " <li><a href=\"qdeclarativeexamples.html\">QML Examples</a></li> \n" \ - " <li><a href=\"qdeclarativeexamples.html#Demos\">QML Demos</a></li> \n" \ " </ul> \n" \ " </li> \n" \ " </ul> \n" \ @@ -160,7 +160,7 @@ HTML.footer = " <!-- /div -->\n" \ " <div id=\"feedbackBox\">\n" \ " <div id=\"feedcloseX\" class=\"feedclose t_button\">X</div>\n" \ " <form id=\"feedform\" action=\"http://doc.qt.nokia.com/docFeedbck/feedback.php\" method=\"get\">\n" \ - " <p>Thank you for giving your feedback. <div class=\"note\">Make sure it is related the page. For more general bugs and \n" \ + " <p id=\"noteHead\">Thank you for giving your feedback. <div class=\"note\">Make sure it is related the page. For more general bugs and \n" \ " requests, please use the <a href=\"http://bugreports.qt.nokia.com/secure/Dashboard.jspa\">Qt Bug Tracker</a></div></p>\n" \ " <p><textarea id=\"feedbox\" name=\"feedText\" rows=\"5\" cols=\"40\"></textarea></p>\n" \ " <p><input id=\"feedsubmit\" class=\"feedclose\" type=\"submit\" name=\"feedback\" /></p>\n" \ diff --git a/tools/qdoc3/test/style/style.css b/tools/qdoc3/test/style/style.css index 9c290f5..dff0772 100644 --- a/tools/qdoc3/test/style/style.css +++ b/tools/qdoc3/test/style/style.css @@ -776,12 +776,14 @@ } .qmlreadonly { + padding-left: 3px; float: right; color: #254117; } .qmldefault { + padding-left: 3px; float: right; color: red; } diff --git a/tools/qdoc3/tree.cpp b/tools/qdoc3/tree.cpp index d31de4d..70b998f 100644 --- a/tools/qdoc3/tree.cpp +++ b/tools/qdoc3/tree.cpp @@ -134,15 +134,16 @@ Node *Tree::findNode(const QStringList &path, Node *relative, int findFlags) /*! */ -const Node *Tree::findNode(const QStringList &path, - const Node *relative, +const Node* Tree::findNode(const QStringList &path, + const Node* start, int findFlags) const { - if (!relative) - relative = root(); + const Node* current = start; + if (!current) + current = root(); do { - const Node *node = relative; + const Node *node = current; int i; for (i = 0; i < path.size(); ++i) { @@ -171,9 +172,10 @@ const Node *Tree::findNode(const QStringList &path, if (node && i == path.size() && (!(findFlags & NonFunction) || node->type() != Node::Function || ((FunctionNode *)node)->metaness() == FunctionNode::MacroWithoutParams)) - return node; - relative = relative->parent(); - } while (relative); + if ((node != start) && (node->subType() != Node::QmlPropertyGroup)) + return node; + current = current->parent(); + } while (current); return 0; } diff --git a/tools/qml/deviceorientation_maemo.cpp b/tools/qml/deviceorientation_maemo5.cpp index 443edc8..e942579 100644 --- a/tools/qml/deviceorientation_maemo.cpp +++ b/tools/qml/deviceorientation_maemo5.cpp @@ -124,4 +124,4 @@ DeviceOrientation* DeviceOrientation::instance() return o; } -#include "deviceorientation_maemo.moc" +#include "deviceorientation_maemo5.moc" diff --git a/tools/qml/deviceorientation_symbian.cpp b/tools/qml/deviceorientation_symbian.cpp new file mode 100644 index 0000000..48bfc72 --- /dev/null +++ b/tools/qml/deviceorientation_symbian.cpp @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "deviceorientation.h" + +#include <e32base.h> +#include <sensrvchannelfinder.h> +#include <sensrvdatalistener.h> +#include <sensrvchannel.h> +#include <sensrvorientationsensor.h> + +class SymbianOrientation : public DeviceOrientation, public MSensrvDataListener +{ + Q_OBJECT +public: + SymbianOrientation() + : DeviceOrientation(), m_current(UnknownOrientation), m_sensorChannel(0) + { + TRAP_IGNORE(initL()); + if (!m_sensorChannel) + qWarning("No valid sensors found."); + } + + ~SymbianOrientation() + { + if (m_sensorChannel) { + m_sensorChannel->StopDataListening(); + m_sensorChannel->CloseChannel(); + delete m_sensorChannel; + } + } + + void initL() + { + CSensrvChannelFinder *channelFinder = CSensrvChannelFinder::NewLC(); + RSensrvChannelInfoList channelInfoList; + CleanupClosePushL(channelInfoList); + + TSensrvChannelInfo searchConditions; + searchConditions.iChannelType = KSensrvChannelTypeIdOrientationData; + channelFinder->FindChannelsL(channelInfoList, searchConditions); + + for (int i = 0; i < channelInfoList.Count(); ++i) { + TRAPD(error, m_sensorChannel = CSensrvChannel::NewL(channelInfoList[i])); + if (!error) + TRAP(error, m_sensorChannel->OpenChannelL()); + if (!error) { + TRAP(error, m_sensorChannel->StartDataListeningL(this, 1, 1, 0)); + break; + } + if (error) { + delete m_sensorChannel; + m_sensorChannel = 0; + } + } + + channelInfoList.Close(); + CleanupStack::Pop(&channelInfoList); + CleanupStack::PopAndDestroy(channelFinder); + } + + Orientation orientation() const + { + return m_current; + } + + void setOrientation(Orientation) { } + +private: + DeviceOrientation::Orientation m_current; + CSensrvChannel *m_sensorChannel; + + void DataReceived(CSensrvChannel &channel, TInt count, TInt dataLost) + { + if (channel.GetChannelInfo().iChannelType == KSensrvChannelTypeIdOrientationData) { + TSensrvOrientationData data; + for (int i = 0; i < count; ++i) { + TPckgBuf<TSensrvOrientationData> dataBuf; + channel.GetData(dataBuf); + data = dataBuf(); + Orientation o = UnknownOrientation; + switch (data.iDeviceOrientation) { + case TSensrvOrientationData::EOrientationDisplayRightUp: + o = LandscapeInverted; + break; + case TSensrvOrientationData::EOrientationDisplayUp: + o = Portrait; + break; + case TSensrvOrientationData::EOrientationDisplayDown: + o = PortraitInverted; + break; + case TSensrvOrientationData::EOrientationDisplayLeftUp: + o = Landscape; + break; + case TSensrvOrientationData::EOrientationUndefined: + case TSensrvOrientationData::EOrientationDisplayUpwards: + case TSensrvOrientationData::EOrientationDisplayDownwards: + default: + break; + } + + if (m_current != o) { + m_current = o; + emit orientationChanged(); + } + } + } + } + + void DataError(CSensrvChannel& /* channel */, TSensrvErrorSeverity /* error */) + { + } + + void GetDataListenerInterfaceL(TUid /* interfaceUid */, TAny*& /* interface */) + { + } +}; + + +DeviceOrientation* DeviceOrientation::instance() +{ + static SymbianOrientation *o = 0; + if (!o) + o = new SymbianOrientation; + return o; +} + +#include "deviceorientation_symbian.moc" diff --git a/tools/qml/loggerwidget.cpp b/tools/qml/loggerwidget.cpp index 3ae2b5e..8aa029f 100644 --- a/tools/qml/loggerwidget.cpp +++ b/tools/qml/loggerwidget.cpp @@ -39,29 +39,48 @@ ** ****************************************************************************/ -#include "loggerwidget.h" #include <qglobal.h> #include <QDebug> #include <QSettings> #include <QActionGroup> #include <QMenu> +#include <QPlainTextEdit> +#ifdef Q_WS_MAEMO_5 +# include <QScrollArea> +# include <QVBoxLayout> +# include "texteditautoresizer_maemo5.h" +#endif + +#include "loggerwidget.h" QT_BEGIN_NAMESPACE LoggerWidget::LoggerWidget(QWidget *parent) : - QPlainTextEdit(parent), + QMainWindow(parent), m_visibilityOrigin(SettingsOrigin) { setAttribute(Qt::WA_QuitOnClose, false); setWindowTitle(tr("Warnings")); + m_plainTextEdit = new QPlainTextEdit(); + +#ifdef Q_WS_MAEMO_5 + new TextEditAutoResizer(m_plainTextEdit); + setAttribute(Qt::WA_Maemo5StackedWindow); + QScrollArea *area = new QScrollArea(); + area->setWidget(m_plainTextEdit); + area->setWidgetResizable(true); + setCentralWidget(area); +#else + setCentralWidget(m_plainTextEdit); +#endif readSettings(); setupPreferencesMenu(); } void LoggerWidget::append(const QString &msg) { - appendPlainText(msg); + m_plainTextEdit->appendPlainText(msg); if (!isVisible() && (defaultVisibility() == AutoShowWarnings)) setVisible(true); diff --git a/tools/qml/loggerwidget.h b/tools/qml/loggerwidget.h index fd20c41..13c319f 100644 --- a/tools/qml/loggerwidget.h +++ b/tools/qml/loggerwidget.h @@ -42,12 +42,17 @@ #ifndef LOGGERWIDGET_H #define LOGGERWIDGET_H -#include <QPlainTextEdit> +#include <QMainWindow> +#include <QMetaType> QT_BEGIN_NAMESPACE -class LoggerWidget : public QPlainTextEdit { -Q_OBJECT +class QPlainTextEdit; +class QMenu; +class QAction; + +class LoggerWidget : public QMainWindow { + Q_OBJECT public: LoggerWidget(QWidget *parent=0); @@ -80,6 +85,7 @@ private: QMenu *m_preferencesMenu; QAction *m_showWidgetAction; + QPlainTextEdit *m_plainTextEdit; enum ConfigOrigin { CommandLineOrigin, SettingsOrigin }; ConfigOrigin m_visibilityOrigin; diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index a75023b..dfd1726 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -49,12 +49,17 @@ #include <QTranslator> #include <QDebug> #include <QMessageBox> +#include <QAtomicInt> #include "qdeclarativetester.h" QT_USE_NAMESPACE QtMsgHandler systemMsgOutput = 0; +#if defined(Q_WS_S60) +#include <aknappui.h> // For locking app to portrait +#endif + #if defined (Q_OS_SYMBIAN) #include <unistd.h> #include <sys/types.h> @@ -89,19 +94,25 @@ void showWarnings() } } +static QAtomicInt recursiveLock(0); + void myMessageOutput(QtMsgType type, const char *msg) { - if (!logger.isNull()) { - QString strMsg = QString::fromAscii(msg); - QMetaObject::invokeMethod(logger.data(), "append", Q_ARG(QString, strMsg)); + QString strMsg = QString::fromLatin1(msg); + + if (!logger.isNull() && !QCoreApplication::closingDown()) { + if (recursiveLock.testAndSetOrdered(0, 1)) { + QMetaObject::invokeMethod(logger.data(), "append", Q_ARG(QString, strMsg)); + recursiveLock = 0; + } } else { - warnings += msg; + warnings += strMsg; warnings += QLatin1Char('\n'); } if (systemMsgOutput) { // Windows systemMsgOutput(type, msg); } else { // Unix - fprintf(stderr, "%s\n",msg); + fprintf(stderr, "%s\n", msg); fflush(stderr); } } @@ -119,7 +130,7 @@ void usage() qWarning(" -fullscreen............................... run fullscreen"); qWarning(" -stayontop................................ keep viewer window on top"); qWarning(" -sizeviewtorootobject .................... the view resizes to the changes in the content"); - qWarning(" -sizerootobjecttoview .................... the content resizes to the changes in the view"); + qWarning(" -sizerootobjecttoview .................... the content resizes to the changes in the view (default)"); qWarning(" -qmlbrowser .............................. use a QML-based file browser"); qWarning(" -warnings [show|hide]..................... show warnings in a separate log window"); qWarning(" -recordfile <output> ..................... set video recording file"); @@ -200,6 +211,13 @@ int main(int argc, char ** argv) app.setOrganizationName("Nokia"); app.setOrganizationDomain("nokia.com"); +#if defined(Q_WS_S60) + CAknAppUi *appUi = static_cast<CAknAppUi *>(CEikonEnv::Static()->AppUi()); + if (appUi) { + appUi->SetOrientationL(CAknAppUi::EAppUiOrientationPortrait); + } +#endif + QDeclarativeViewer::registerTypes(); QDeclarativeTester::registerTypes(); diff --git a/tools/qml/proxysettings.cpp b/tools/qml/proxysettings.cpp index 3255e42..ffaa4c0 100644 --- a/tools/qml/proxysettings.cpp +++ b/tools/qml/proxysettings.cpp @@ -48,11 +48,14 @@ QT_BEGIN_NAMESPACE ProxySettings::ProxySettings (QWidget * parent) - : QDialog (parent), Ui::ProxySettings() + : QDialog (parent), Ui::ProxySettings() { setupUi (this); +#if !defined Q_WS_MAEMO_5 + // the onscreen keyboard can't cope with masks proxyServerEdit->setInputMask ("000.000.000.000;_"); +#endif QIntValidator *validator = new QIntValidator (0, 9999, this); proxyPortEdit->setValidator (validator); diff --git a/tools/qml/proxysettings.h b/tools/qml/proxysettings.h index 325929a..5d4d137 100644 --- a/tools/qml/proxysettings.h +++ b/tools/qml/proxysettings.h @@ -44,7 +44,11 @@ #include <QDialog> #include <QNetworkProxy> +#ifdef Q_WS_MAEMO_5 +#include "ui_proxysettings_maemo5.h" +#else #include "ui_proxysettings.h" +#endif QT_BEGIN_NAMESPACE /** diff --git a/tools/qml/proxysettings_maemo5.ui b/tools/qml/proxysettings_maemo5.ui new file mode 100644 index 0000000..83f0c2a --- /dev/null +++ b/tools/qml/proxysettings_maemo5.ui @@ -0,0 +1,177 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ProxySettings</class> + <widget class="QDialog" name="ProxySettings"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>449</width> + <height>164</height> + </rect> + </property> + <property name="windowTitle"> + <string>HTTP Proxy</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <property name="leftMargin"> + <number>16</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>16</number> + </property> + <property name="bottomMargin"> + <number>8</number> + </property> + <property name="horizontalSpacing"> + <number>16</number> + </property> + <property name="verticalSpacing"> + <number>0</number> + </property> + <item row="0" column="0"> + <widget class="QCheckBox" name="proxyCheckBox"> + <property name="text"> + <string>Use HTTP Proxy</string> + </property> + </widget> + </item> + <item row="0" column="1" rowspan="2"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0" rowspan="2"> + <widget class="QWidget" name="widget" native="true"> + <layout class="QGridLayout" name="gridLayout"> + <property name="horizontalSpacing"> + <number>16</number> + </property> + <property name="verticalSpacing"> + <number>0</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="serverAddressLabel"> + <property name="text"> + <string>Server</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="proxyServerEdit"> + <property name="placeholderText"> + <string>Name or IP</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Port</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="proxyPortEdit"> + <property name="text"> + <string>8080</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="usernameLabel"> + <property name="text"> + <string>Username</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="usernameEdit"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="passwordLabel"> + <property name="text"> + <string>Password</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLineEdit" name="passwordEdit"> + <property name="echoMode"> + <enum>QLineEdit::Password</enum> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="2" column="1"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>proxyCheckBox</tabstop> + <tabstop>proxyServerEdit</tabstop> + <tabstop>proxyPortEdit</tabstop> + <tabstop>usernameEdit</tabstop> + <tabstop>passwordEdit</tabstop> + <tabstop>buttonBox</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>ProxySettings</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>318</x> + <y>100</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>116</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>ProxySettings</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>318</x> + <y>100</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>116</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tools/qml/qdeclarativetester.h b/tools/qml/qdeclarativetester.h index d49c9b8..021869d 100644 --- a/tools/qml/qdeclarativetester.h +++ b/tools/qml/qdeclarativetester.h @@ -48,6 +48,9 @@ #include <QImage> #include <QUrl> #include <qmlruntime.h> +#include <qdeclarativelist.h> +#include <qdeclarative.h> +#include <QAbstractAnimation> QT_BEGIN_NAMESPACE diff --git a/tools/qml/qml.pri b/tools/qml/qml.pri index 58d8cc1..fcd0c33 100644 --- a/tools/qml/qml.pri +++ b/tools/qml/qml.pri @@ -19,10 +19,16 @@ SOURCES += $$PWD/qmlruntime.cpp \ RESOURCES = $$PWD/qmlruntime.qrc maemo5 { QT += dbus - SOURCES += $$PWD/deviceorientation_maemo.cpp + HEADERS += $$PWD/texteditautoresizer_maemo5.h + SOURCES += $$PWD/deviceorientation_maemo5.cpp + FORMS = $$PWD/recopts_maemo5.ui \ + $$PWD/proxysettings_maemo5.ui +} symbian:!contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2) { + SOURCES += $$PWD/deviceorientation_symbian.cpp + FORMS = $$PWD/recopts.ui \ + $$PWD/proxysettings.ui } else { SOURCES += $$PWD/deviceorientation.cpp + FORMS = $$PWD/recopts.ui \ + $$PWD/proxysettings.ui } - -FORMS = $$PWD/recopts.ui \ - $$PWD/proxysettings.ui diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro index 9cdec77..0a51c0b 100644 --- a/tools/qml/qml.pro +++ b/tools/qml/qml.pro @@ -29,11 +29,18 @@ wince* { QT += webkit } } +maemo5 { + QT += maemo5 +} symbian { TARGET.UID3 = 0x20021317 include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) TARGET.EPOCHEAPSIZE = 0x20000 0x2000000 TARGET.CAPABILITY = NetworkServices ReadUserData + !contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2) { + LIBS += -lsensrvclient -lsensrvutil + contains(QT_CONFIG, s60): LIBS += -lavkon -lcone + } } mac { QMAKE_INFO_PLIST=Info_mac.plist diff --git a/tools/qml/qmlruntime.cpp b/tools/qml/qmlruntime.cpp index 676881d..03ca798 100644 --- a/tools/qml/qmlruntime.cpp +++ b/tools/qml/qmlruntime.cpp @@ -44,15 +44,23 @@ #ifdef hz #undef hz #endif -#include "ui_recopts.h" +#ifdef Q_WS_MAEMO_5 +# include <QMaemo5ValueButton> +# include <QMaemo5ListPickSelector> +# include <QWidgetAction> +# include <QStringListModel> +# include "ui_recopts_maemo5.h" +#else +# include "ui_recopts.h" +#endif #include "qmlruntime.h" #include <qdeclarativecontext.h> #include <qdeclarativeengine.h> #include <qdeclarativenetworkaccessmanagerfactory.h> #include "qdeclarative.h" -#include <private/qabstractanimation_p.h> #include <QAbstractAnimation> +#include <private/qabstractanimation_p.h> #include <QSettings> #include <QXmlStreamReader> @@ -136,24 +144,59 @@ private: }; -class SizedMenuBar : public QMenuBar -{ + +#if defined(Q_WS_MAEMO_5) + +class Maemo5PickerAction : public QWidgetAction { Q_OBJECT public: - SizedMenuBar(QWidget *parent, QWidget *referenceWidget) - : QMenuBar(parent), refWidget(referenceWidget) + Maemo5PickerAction(const QString &text, QActionGroup *actions, QObject *parent) + : QWidgetAction(parent), m_text(text), m_actions(actions) + { } + + QWidget *createWidget(QWidget *parent) { + QMaemo5ValueButton *button = new QMaemo5ValueButton(m_text, parent); + button->setValueLayout(QMaemo5ValueButton::ValueUnderTextCentered); + QMaemo5ListPickSelector *pick = new QMaemo5ListPickSelector(button); + button->setPickSelector(pick); + if (m_actions) { + QStringList sl; + int curIdx = -1, idx = 0; + foreach (QAction *a, m_actions->actions()) { + sl << a->text(); + if (a->isChecked()) + curIdx = idx; + idx++; + } + pick->setModel(new QStringListModel(sl)); + pick->setCurrentIndex(curIdx); + } else { + button->setEnabled(false); + } + connect(pick, SIGNAL(selected(QString)), this, SLOT(emitTriggered())); + return button; } - virtual QSize sizeHint() const +private slots: + void emitTriggered() { - return QSize(refWidget->sizeHint().width(), QMenuBar::sizeHint().height()); + QMaemo5ListPickSelector *pick = qobject_cast<QMaemo5ListPickSelector *>(sender()); + if (!pick) + return; + int idx = pick->currentIndex(); + + if (m_actions && idx >= 0 && idx < m_actions->actions().count()) + m_actions->actions().at(idx)->trigger(); } private: - QWidget *refWidget; + QString m_text; + QPointer<QActionGroup> m_actions; }; +#endif // Q_WS_MAEMO_5 + static struct { const char *name, *args; } ffmpegprofiles[] = { {"Maximum Quality", "-sameq"}, {"High Quality", "-qmax 2"}, @@ -170,7 +213,9 @@ public: RecordingDialog(QWidget *parent) : QDialog(parent) { setupUi(this); +#ifndef Q_WS_MAEMO_5 hz->setValidator(new QDoubleValidator(hz)); +#endif for (int i=0; ffmpegprofiles[i].name; ++i) { profile->addItem(ffmpegprofiles[i].name); } @@ -197,6 +242,132 @@ public: return ffmpegprofiles[i].args[0] ? QLatin1String(ffmpegprofiles[i].args) : customargs; } + void setOriginalSize(const QSize &s) + { + QString str = tr("Original (%1x%2)").arg(s.width()).arg(s.height()); + +#ifdef Q_WS_MAEMO_5 + sizeCombo->setItemText(0, str); +#else + sizeOriginal->setText(str); + if (sizeWidth->value()<=1) { + sizeWidth->setValue(s.width()); + sizeHeight->setValue(s.height()); + } +#endif + } + + void showffmpegOptions(bool b) + { +#ifdef Q_WS_MAEMO_5 + profileLabel->setVisible(b); + profile->setVisible(b); + ffmpegHelp->setVisible(b); + args->setVisible(b); +#else + ffmpegOptions->setVisible(b); +#endif + } + + void showRateOptions(bool b) + { +#ifdef Q_WS_MAEMO_5 + rateLabel->setVisible(b); + rateCombo->setVisible(b); +#else + rateOptions->setVisible(b); +#endif + } + + void setVideoRate(int rate) + { +#ifdef Q_WS_MAEMO_5 + int idx; + if (rate >= 60) + idx = 0; + else if (rate >= 50) + idx = 2; + else if (rate >= 25) + idx = 3; + else if (rate >= 24) + idx = 4; + else if (rate >= 20) + idx = 5; + else if (rate >= 15) + idx = 6; + else + idx = 7; + rateCombo->setCurrentIndex(idx); +#else + if (rate == 24) + hz24->setChecked(true); + else if (rate == 25) + hz25->setChecked(true); + else if (rate == 50) + hz50->setChecked(true); + else if (rate == 60) + hz60->setChecked(true); + else { + hzCustom->setChecked(true); + hz->setText(QString::number(rate)); + } +#endif + } + + int videoRate() const + { +#ifdef Q_WS_MAEMO_5 + switch (rateCombo->currentIndex()) { + case 0: return 60; + case 1: return 50; + case 2: return 25; + case 3: return 24; + case 4: return 20; + case 5: return 15; + case 7: return 10; + default: return 60; + } +#else + if (hz24->isChecked()) + return 24; + else if (hz25->isChecked()) + return 25; + else if (hz50->isChecked()) + return 50; + else if (hz60->isChecked()) + return 60; + else { + return hz->text().toInt(); + } +#endif + } + + QSize videoSize() const + { +#ifdef Q_WS_MAEMO_5 + switch (sizeCombo->currentIndex()) { + case 0: return QSize(); + case 1: return QSize(640,480); + case 2: return QSize(320,240); + case 3: return QSize(1280,720); + default: return QSize(); + } +#else + if (sizeOriginal->isChecked()) + return QSize(); + else if (size720p->isChecked()) + return QSize(1280,720); + else if (sizeVGA->isChecked()) + return QSize(640,480); + else if (sizeQVGA->isChecked()) + return QSize(320,240); + else + return QSize(sizeWidth->value(), sizeHeight->value()); +#endif + } + + + private slots: void pickProfile(int i) { @@ -260,65 +431,82 @@ private: mutable QMutex mutex; }; -class NetworkAccessManagerFactory : public QDeclarativeNetworkAccessManagerFactory +class SystemProxyFactory : public QNetworkProxyFactory { public: - NetworkAccessManagerFactory() : cacheSize(0) {} - ~NetworkAccessManagerFactory() {} - - QNetworkAccessManager *create(QObject *parent); + SystemProxyFactory() : proxyDirty(true), httpProxyInUse(false) { + } - void setupProxy(QNetworkAccessManager *nam) + virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query) { - class SystemProxyFactory : public QNetworkProxyFactory - { - public: - virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query) - { - QString protocolTag = query.protocolTag(); - if (httpProxyInUse && (protocolTag == "http" || protocolTag == "https")) { - QList<QNetworkProxy> ret; - ret << httpProxy; - return ret; - } + if (proxyDirty) + setupProxy(); + QString protocolTag = query.protocolTag(); + if (httpProxyInUse && (protocolTag == "http" || protocolTag == "https")) { + QList<QNetworkProxy> ret; + ret << httpProxy; + return ret; + } #ifdef Q_OS_WIN - // systemProxyForQuery can take insanely long on Windows (QTBUG-10106) - return QNetworkProxyFactory::proxyForQuery(query); + // systemProxyForQuery can take insanely long on Windows (QTBUG-10106) + return QNetworkProxyFactory::proxyForQuery(query); #else - return QNetworkProxyFactory::systemProxyForQuery(query); + return QNetworkProxyFactory::systemProxyForQuery(query); #endif - } - void setHttpProxy (QNetworkProxy proxy) - { - httpProxy = proxy; - httpProxyInUse = true; - } - void unsetHttpProxy () - { - httpProxyInUse = false; - } - private: - bool httpProxyInUse; - QNetworkProxy httpProxy; - }; - - SystemProxyFactory *proxyFactory = new SystemProxyFactory; - if (ProxySettings::httpProxyInUse()) - proxyFactory->setHttpProxy(ProxySettings::httpProxy()); - else - proxyFactory->unsetHttpProxy(); - nam->setProxyFactory(proxyFactory); } + void setupProxy() { + // Don't bother locking because we know that the proxy only + // changes in response to the settings dialog and that + // the view will be reloaded. + proxyDirty = false; + httpProxyInUse = ProxySettings::httpProxyInUse(); + if (httpProxyInUse) + httpProxy = ProxySettings::httpProxy(); + } + + void proxyChanged() { + proxyDirty = true; + } + +private: + volatile bool proxyDirty; + bool httpProxyInUse; + QNetworkProxy httpProxy; +}; + +class NetworkAccessManagerFactory : public QObject, public QDeclarativeNetworkAccessManagerFactory +{ + Q_OBJECT +public: + NetworkAccessManagerFactory() : cacheSize(0) {} + ~NetworkAccessManagerFactory() {} + + QNetworkAccessManager *create(QObject *parent); + void setCacheSize(int size) { if (size != cacheSize) { cacheSize = size; } } + void proxyChanged() { + foreach (QNetworkAccessManager *nam, namList) { + static_cast<SystemProxyFactory*>(nam->proxyFactory())->proxyChanged(); + } + } + static PersistentCookieJar *cookieJar; + +private slots: + void managerDestroyed(QObject *obj) { + namList.removeOne(static_cast<QNetworkAccessManager*>(obj)); + } + +private: QMutex mutex; int cacheSize; + QList<QNetworkAccessManager*> namList; }; PersistentCookieJar *NetworkAccessManagerFactory::cookieJar = 0; @@ -339,7 +527,7 @@ QNetworkAccessManager *NetworkAccessManagerFactory::create(QObject *parent) } manager->setCookieJar(cookieJar); cookieJar->setParent(0); - setupProxy(manager); + manager->setProxyFactory(new SystemProxyFactory); if (cacheSize > 0) { QNetworkDiskCache *cache = new QNetworkDiskCache; cache->setCacheDirectory(QDir::tempPath()+QLatin1String("/qml-viewer-network-cache")); @@ -348,6 +536,8 @@ QNetworkAccessManager *NetworkAccessManagerFactory::create(QObject *parent) } else { manager->setCache(0); } + connect(manager, SIGNAL(destroyed(QObject*)), this, SLOT(managerDestroyed(QObject*))); + namList.append(manager); qDebug() << "created new network access manager for" << parent; return manager; } @@ -363,15 +553,10 @@ QString QDeclarativeViewer::getVideoFileName() return QFileDialog::getSaveFileName(this, title, "", types.join(";; ")); } - QDeclarativeViewer::QDeclarativeViewer(QWidget *parent, Qt::WindowFlags flags) -#if defined(Q_OS_SYMBIAN) : QMainWindow(parent, flags) -#else - : QWidget(parent, flags) -#endif - , loggerWindow(new LoggerWidget()) - , frame_stream(0), mb(0) + , loggerWindow(new LoggerWidget(this)) + , frame_stream(0) , orientation(0) , showWarningsWindow(0) , m_scriptOptions(0) @@ -381,6 +566,10 @@ QDeclarativeViewer::QDeclarativeViewer(QWidget *parent, Qt::WindowFlags flags) { QDeclarativeViewer::registerTypes(); setWindowTitle(tr("Qt QML Viewer")); +#ifdef Q_WS_MAEMO_5 + setAttribute(Qt::WA_Maemo5StackedWindow); +// setPalette(QApplication::palette("QLabel")); +#endif devicemode = false; canvas = 0; @@ -393,9 +582,9 @@ QDeclarativeViewer::QDeclarativeViewer(QWidget *parent, Qt::WindowFlags flags) senseFfmpeg(); senseImageMagick(); if (!ffmpegAvailable) - recdlg->ffmpegOptions->hide(); + recdlg->showffmpegOptions(false); if (!ffmpegAvailable && !convertAvailable) - recdlg->rateOptions->hide(); + recdlg->showRateOptions(false); QString warn; if (!ffmpegAvailable) { if (!convertAvailable) @@ -422,33 +611,27 @@ QDeclarativeViewer::QDeclarativeViewer(QWidget *parent, Qt::WindowFlags flags) QObject::connect(warningsWidget(), SIGNAL(closed()), this, SLOT(warningsWidgetClosed())); if (!(flags & Qt::FramelessWindowHint)) { - createMenu(menuBar(),0); + createMenu(); changeOrientation(orientation->actions().value(0)); + } else { + setMenuBar(0); } -#if !defined(Q_OS_SYMBIAN) - QVBoxLayout *layout = new QVBoxLayout; - layout->setMargin(0); - layout->setSpacing(0); - setLayout(layout); - if (mb) - layout->addWidget(mb); - layout->addWidget(canvas); -#else setCentralWidget(canvas); -#endif + namFactory = new NetworkAccessManagerFactory; canvas->engine()->setNetworkAccessManagerFactory(namFactory); - connect(&autoStartTimer, SIGNAL(triggered()), this, SLOT(autoStartRecording())); - connect(&autoStopTimer, SIGNAL(triggered()), this, SLOT(autoStopRecording())); - connect(&recordTimer, SIGNAL(triggered()), this, SLOT(recordFrame())); + connect(&autoStartTimer, SIGNAL(timeout()), this, SLOT(autoStartRecording())); + connect(&autoStopTimer, SIGNAL(timeout()), this, SLOT(autoStopRecording())); + connect(&recordTimer, SIGNAL(timeout()), this, SLOT(recordFrame())); connect(DeviceOrientation::instance(), SIGNAL(orientationChanged()), this, SLOT(orientationChanged()), Qt::QueuedConnection); - autoStartTimer.setRunning(false); - autoStopTimer.setRunning(false); - recordTimer.setRunning(false); - recordTimer.setRepeating(true); + autoStartTimer.setSingleShot(true); + autoStopTimer.setSingleShot(true); + recordTimer.setSingleShot(false); + + QObject::connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(appAboutToQuit())); } QDeclarativeViewer::~QDeclarativeViewer() @@ -468,26 +651,6 @@ void QDeclarativeViewer::enableExperimentalGestures() canvas->viewport()->setAttribute(Qt::WA_AcceptTouchEvents); } -int QDeclarativeViewer::menuBarHeight() const -{ - if (!(windowFlags() & Qt::FramelessWindowHint)) - return menuBar()->height(); - else - return 0; // don't create menu -} - -QMenuBar *QDeclarativeViewer::menuBar() const -{ -#if !defined(Q_OS_SYMBIAN) - if (!mb) - mb = new SizedMenuBar((QWidget*)this, canvas); -#else - mb = QMainWindow::menuBar(); -#endif - - return mb; -} - QDeclarativeView *QDeclarativeViewer::view() const { return canvas; @@ -498,120 +661,128 @@ LoggerWidget *QDeclarativeViewer::warningsWidget() const return loggerWindow; } -void QDeclarativeViewer::createMenu(QMenuBar *menu, QMenu *flatmenu) +void QDeclarativeViewer::createMenu() { - QObject *parent = flatmenu ? (QObject*)flatmenu : (QObject*)menu; - - QMenu *fileMenu = flatmenu ? flatmenu : menu->addMenu(tr("&File")); - - QAction *openAction = new QAction(tr("&Open..."), parent); + QAction *openAction = new QAction(tr("&Open..."), this); openAction->setShortcut(QKeySequence("Ctrl+O")); connect(openAction, SIGNAL(triggered()), this, SLOT(openFile())); - fileMenu->addAction(openAction); - QAction *reloadAction = new QAction(tr("&Reload"), parent); + QAction *reloadAction = new QAction(tr("&Reload"), this); reloadAction->setShortcut(QKeySequence("Ctrl+R")); connect(reloadAction, SIGNAL(triggered()), this, SLOT(reload())); - fileMenu->addAction(reloadAction); - -#if !defined(Q_OS_SYMBIAN) - if (flatmenu) flatmenu->addSeparator(); - - QMenu *recordMenu = flatmenu ? flatmenu : menu->addMenu(tr("&Recording")); - QAction *snapshotAction = new QAction(tr("&Take Snapshot\tF3"), parent); + QAction *snapshotAction = new QAction(tr("&Take Snapshot"), this); + snapshotAction->setShortcut(QKeySequence("F3")); connect(snapshotAction, SIGNAL(triggered()), this, SLOT(takeSnapShot())); - recordMenu->addAction(snapshotAction); - recordAction = new QAction(tr("Start Recording &Video\tF9"), parent); + recordAction = new QAction(tr("Start Recording &Video"), this); + recordAction->setShortcut(QKeySequence("F9")); connect(recordAction, SIGNAL(triggered()), this, SLOT(toggleRecordingWithSelection())); - recordMenu->addAction(recordAction); - QAction *recordOptions = new QAction(tr("Video &Options..."), parent); + QAction *recordOptions = new QAction(tr("Video &Options..."), this); connect(recordOptions, SIGNAL(triggered()), this, SLOT(chooseRecordingOptions())); - if (flatmenu) - flatmenu->addAction(recordOptions); - - if (flatmenu) flatmenu->addSeparator(); - - QMenu *debugMenu = flatmenu ? flatmenu->addMenu(tr("&Debugging")) : menu->addMenu(tr("&Debugging")); - - QAction *slowAction = new QAction(tr("&Slow Down Animations"), parent); + QAction *slowAction = new QAction(tr("&Slow Down Animations"), this); slowAction->setShortcut(QKeySequence("Ctrl+.")); slowAction->setCheckable(true); connect(slowAction, SIGNAL(triggered(bool)), this, SLOT(setSlowMode(bool))); - debugMenu->addAction(slowAction); - showWarningsWindow = new QAction(tr("Show Warnings"), parent); + showWarningsWindow = new QAction(tr("Show Warnings"), this); showWarningsWindow->setCheckable((true)); showWarningsWindow->setChecked(loggerWindow->isVisible()); connect(showWarningsWindow, SIGNAL(triggered(bool)), this, SLOT(showWarnings(bool))); -#if !defined(Q_OS_SYMBIAN) - debugMenu->addAction(showWarningsWindow); -#endif - - if (flatmenu) flatmenu->addSeparator(); - -#endif // Q_OS_SYMBIAN - - QMenu *settingsMenu = flatmenu ? flatmenu : menu->addMenu(tr("S&ettings")); - QAction *proxyAction = new QAction(tr("Http &proxy..."), parent); + QAction *proxyAction = new QAction(tr("HTTP &Proxy..."), this); connect(proxyAction, SIGNAL(triggered()), this, SLOT(showProxySettings())); - settingsMenu->addAction(proxyAction); -#if !defined(Q_OS_SYMBIAN) - if (!flatmenu) - settingsMenu->addAction(recordOptions); - settingsMenu->addMenu(loggerWindow->preferencesMenu()); -#else - QAction *fullscreenAction = new QAction(tr("Full Screen"), parent); + QAction *fullscreenAction = new QAction(tr("Full Screen"), this); fullscreenAction->setCheckable(true); connect(fullscreenAction, SIGNAL(triggered()), this, SLOT(toggleFullScreen())); - settingsMenu->addAction(fullscreenAction); -#endif - - if (flatmenu) flatmenu->addSeparator(); - - QMenu *propertiesMenu = settingsMenu->addMenu(tr("Properties")); - - orientation = new QActionGroup(parent); - QAction *rotateOrientation = new QAction(tr("Rotate orientation"), parent); + QAction *rotateOrientation = new QAction(tr("Rotate orientation"), this); rotateOrientation->setShortcut(QKeySequence("Ctrl+T")); - settingsMenu->addAction(rotateOrientation); connect(rotateOrientation, SIGNAL(triggered()), this, SLOT(rotateOrientation())); + orientation = new QActionGroup(this); orientation->setExclusive(true); connect(orientation, SIGNAL(triggered(QAction*)), this, SLOT(changeOrientation(QAction*))); - orientation->addAction(tr("orientation: Portrait")); - orientation->addAction(tr("orientation: Landscape")); - orientation->addAction(tr("orientation: Portrait (Inverted)")); - orientation->addAction(tr("orientation: Landscape (Inverted)")); - QList<QAction *> actions = orientation->actions(); - for (int i=0; i<actions.count(); i++) { - propertiesMenu->addAction(actions[i]); - actions[i]->setCheckable(true); - } - - if (flatmenu) flatmenu->addSeparator(); + QAction *portraitAction = new QAction(tr("Portrait"), this); + portraitAction->setCheckable(true); + QAction *landscapeAction = new QAction(tr("Landscape"), this); + landscapeAction->setCheckable(true); + QAction *portraitInvAction = new QAction(tr("Portrait (inverted)"), this); + portraitInvAction->setCheckable(true); + QAction *landscapeInvAction = new QAction(tr("Landscape (inverted)"), this); + landscapeInvAction->setCheckable(true); - QMenu *helpMenu = flatmenu ? flatmenu : menu->addMenu(tr("&Help")); - QAction *aboutAction = new QAction(tr("&About Qt..."), parent); + QAction *aboutAction = new QAction(tr("&About Qt..."), this); connect(aboutAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); - helpMenu->addAction(aboutAction); - QAction *quitAction = new QAction(tr("&Quit"), parent); + QAction *quitAction = new QAction(tr("&Quit"), this); quitAction->setShortcut(QKeySequence("Ctrl+Q")); connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); + + QMenuBar *menu = menuBar(); + if (!menu) + return; + +#if defined(Q_WS_MAEMO_5) + menu->addAction(openAction); + menu->addAction(reloadAction); + + menu->addAction(snapshotAction); + menu->addAction(recordAction); + + menu->addAction(recordOptions); + menu->addAction(proxyAction); + + menu->addAction(slowAction); + menu->addAction(showWarningsWindow); + + orientation->addAction(landscapeAction); + orientation->addAction(portraitAction); + menu->addAction(new Maemo5PickerAction(tr("Set orientation"), orientation, this)); + menu->addAction(fullscreenAction); + return; +#endif // Q_WS_MAEMO_5 + + QMenu *fileMenu = menu->addMenu(tr("&File")); + fileMenu->addAction(openAction); + fileMenu->addAction(reloadAction); fileMenu->addSeparator(); fileMenu->addAction(quitAction); - if (menu) { - menu->setFixedHeight(menu->sizeHint().height()); - menu->setMinimumWidth(10); - } + +#if !defined(Q_OS_SYMBIAN) + QMenu *recordMenu = menu->addMenu(tr("&Recording")); + recordMenu->addAction(snapshotAction); + recordMenu->addAction(recordAction); + + QMenu *debugMenu = menu->addMenu(tr("&Debugging")); + debugMenu->addAction(slowAction); + debugMenu->addAction(showWarningsWindow); +#endif // ! Q_OS_SYMBIAN + + QMenu *settingsMenu = menu->addMenu(tr("S&ettings")); + settingsMenu->addAction(proxyAction); +#if !defined(Q_OS_SYMBIAN) + settingsMenu->addAction(recordOptions); + settingsMenu->addMenu(loggerWindow->preferencesMenu()); +#else // ! Q_OS_SYMBIAN + settingsMenu->addAction(fullscreenAction); +#endif // Q_OS_SYMBIAN + settingsMenu->addAction(rotateOrientation); + + QMenu *propertiesMenu = settingsMenu->addMenu(tr("Properties")); + + orientation->addAction(portraitAction); + orientation->addAction(landscapeAction); + orientation->addAction(portraitInvAction); + orientation->addAction(landscapeInvAction); + propertiesMenu->addActions(orientation->actions()); + + QMenu *helpMenu = menu->addMenu(tr("&Help")); + helpMenu->addAction(aboutAction); } void QDeclarativeViewer::showProxySettings() @@ -625,6 +796,7 @@ void QDeclarativeViewer::showProxySettings() void QDeclarativeViewer::proxySettingsChanged() { + namFactory->proxyChanged(); reload (); } @@ -685,25 +857,11 @@ void QDeclarativeViewer::chooseRecordingOptions() recdlg->file->setText(record_file); // Size - recdlg->sizeOriginal->setText(tr("Original (%1x%2)").arg(canvas->width()).arg(canvas->height())); - if (recdlg->sizeWidth->value()<=1) { - recdlg->sizeWidth->setValue(canvas->width()); - recdlg->sizeHeight->setValue(canvas->height()); - } + recdlg->setOriginalSize(canvas->size()); // Rate - if (record_rate == 24) - recdlg->hz24->setChecked(true); - else if (record_rate == 25) - recdlg->hz25->setChecked(true); - else if (record_rate == 50) - recdlg->hz50->setChecked(true); - else if (record_rate == 60) - recdlg->hz60->setChecked(true); - else { - recdlg->hzCustom->setChecked(true); - recdlg->hz->setText(QString::number(record_rate)); - } + recdlg->setVideoRate(record_rate); + // Profile recdlg->setArguments(record_args.join(" ")); @@ -711,28 +869,9 @@ void QDeclarativeViewer::chooseRecordingOptions() // File record_file = recdlg->file->text(); // Size - if (recdlg->sizeOriginal->isChecked()) - record_outsize = QSize(); - else if (recdlg->size720p->isChecked()) - record_outsize = QSize(1280,720); - else if (recdlg->sizeVGA->isChecked()) - record_outsize = QSize(640,480); - else if (recdlg->sizeQVGA->isChecked()) - record_outsize = QSize(320,240); - else - record_outsize = QSize(recdlg->sizeWidth->value(),recdlg->sizeHeight->value()); + record_outsize = recdlg->videoSize(); // Rate - if (recdlg->hz24->isChecked()) - record_rate = 24; - else if (recdlg->hz25->isChecked()) - record_rate = 25; - else if (recdlg->hz50->isChecked()) - record_rate = 50; - else if (recdlg->hz60->isChecked()) - record_rate = 60; - else { - record_rate = recdlg->hz->text().toDouble(); - } + record_rate = recdlg->videoRate(); // Profile record_args = recdlg->arguments().split(" ",QString::SkipEmptyParts); } @@ -740,7 +879,7 @@ void QDeclarativeViewer::chooseRecordingOptions() void QDeclarativeViewer::toggleRecordingWithSelection() { - if (!recordTimer.isRunning()) { + if (!recordTimer.isActive()) { if (record_file.isEmpty()) { QString fileName = getVideoFileName(); if (fileName.isEmpty()) @@ -759,7 +898,7 @@ void QDeclarativeViewer::toggleRecording() toggleRecordingWithSelection(); return; } - bool recording = !recordTimer.isRunning(); + bool recording = !recordTimer.isActive(); recordAction->setText(recording ? tr("&Stop Recording Video\tF9") : tr("&Start Recording Video\tF9")); setRecording(recording); } @@ -807,8 +946,9 @@ void QDeclarativeViewer::statusChanged() initialSize = canvas->initialSize(); if (canvas->resizeMode() == QDeclarativeView::SizeRootObjectToView) { if (!isFullScreen() && !isMaximized()) { - resize(QSize(initialSize.width(), initialSize.height()+menuBarHeight())); - updateSizeHints(); + canvas->setFixedSize(initialSize); + resize(1, 1); // workaround for QMainWindowLayout NOT shrinking the window if the centralWidget() shrink + QTimer::singleShot(0, this, SLOT(updateSizeHints())); } } } @@ -917,7 +1057,7 @@ void QDeclarativeViewer::setAutoRecord(int from, int to) if (from==0) from=1; // ensure resized record_autotime = to-from; autoStartTimer.setInterval(from); - autoStartTimer.setRunning(true); + autoStartTimer.start(); } void QDeclarativeViewer::setRecordArgs(const QStringList& a) @@ -1019,7 +1159,7 @@ void QDeclarativeViewer::senseFfmpeg() void QDeclarativeViewer::setRecording(bool on) { - if (on == recordTimer.isRunning()) + if (on == recordTimer.isActive()) return; int period = int(1000/record_rate+0.5); @@ -1028,7 +1168,7 @@ void QDeclarativeViewer::setRecording(bool on) if (on) { canvas->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); recordTimer.setInterval(period); - recordTimer.setRunning(true); + recordTimer.start(); frame_fmt = record_file.right(4).toLower(); frame = QImage(canvas->width(),canvas->height(),QImage::Format_RGB32); if (frame_fmt != ".png" && (!convertAvailable || frame_fmt != ".gif")) { @@ -1059,7 +1199,7 @@ void QDeclarativeViewer::setRecording(bool on) } } else { canvas->setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate); - recordTimer.setRunning(false); + recordTimer.stop(); if (frame_stream) { qDebug() << "Saving video..."; frame_stream->close(); @@ -1139,7 +1279,7 @@ void QDeclarativeViewer::setRecording(bool on) frames.clear(); } } - qDebug() << "Recording: " << (recordTimer.isRunning()?"ON":"OFF"); + qDebug() << "Recording: " << (recordTimer.isActive()?"ON":"OFF"); } void QDeclarativeViewer::ffmpegFinished(int code) @@ -1147,11 +1287,21 @@ void QDeclarativeViewer::ffmpegFinished(int code) qDebug() << "ffmpeg returned" << code << frame_stream->readAllStandardError(); } +void QDeclarativeViewer::appAboutToQuit() +{ + // avoid QGLContext errors about invalid contexts on exit + canvas->setViewport(0); + + // avoid crashes if messages are received after app has closed + delete loggerWindow; + loggerWindow = 0; +} + void QDeclarativeViewer::autoStartRecording() { setRecording(true); autoStopTimer.setInterval(record_autotime); - autoStopTimer.setRunning(true); + autoStopTimer.start(); } void QDeclarativeViewer::autoStopRecording() @@ -1181,14 +1331,14 @@ void QDeclarativeViewer::changeOrientation(QAction *action) return; action->setChecked(true); - QString o = action->text().split(QLatin1Char(':')).value(1).trimmed(); + QString o = action->text(); if (o == QLatin1String("Portrait")) DeviceOrientation::instance()->setOrientation(DeviceOrientation::Portrait); else if (o == QLatin1String("Landscape")) DeviceOrientation::instance()->setOrientation(DeviceOrientation::Landscape); - else if (o == QLatin1String("Portrait (Inverted)")) + else if (o == QLatin1String("Portrait (inverted)")) DeviceOrientation::instance()->setOrientation(DeviceOrientation::PortraitInverted); - else if (o == QLatin1String("Landscape (Inverted)")) + else if (o == QLatin1String("Landscape (inverted)")) DeviceOrientation::instance()->setOrientation(DeviceOrientation::LandscapeInverted); } @@ -1197,9 +1347,11 @@ void QDeclarativeViewer::orientationChanged() if (canvas->resizeMode() == QDeclarativeView::SizeRootObjectToView) { if (canvas->rootObject()) { QSizeF rootObjectSize = canvas->rootObject()->boundingRect().size(); - QSize newSize(rootObjectSize.width(), rootObjectSize.height()+menuBarHeight()); - if (size() != newSize) { - resize(newSize); + if (size() != rootObjectSize.toSize()) { + canvas->setMinimumSize(rootObjectSize.toSize()); + canvas->resize(rootObjectSize.toSize()); + resize(rootObjectSize.toSize()); + resize(1, 1); // workaround for QMainWindowLayout NOT shrinking the window if the centralWidget() shrinks } } } @@ -1232,6 +1384,8 @@ void QDeclarativeViewer::setUseGL(bool useGL) canvas->setViewport(glWidget); } +#else + Q_UNUSED(useGL) #endif } @@ -1253,16 +1407,15 @@ void QDeclarativeViewer::updateSizeHints() { if (canvas->resizeMode() == QDeclarativeView::SizeViewToRootObject) { QSize newWindowSize = canvas->sizeHint(); - newWindowSize.setHeight(newWindowSize.height()+menuBarHeight()); if (!isFullScreen() && !isMaximized()) { - resize(newWindowSize); - setFixedSize(newWindowSize); + canvas->setMinimumSize(newWindowSize); + canvas->resize(newWindowSize); + resize(1, 1); // workaround for QMainWindowLayout NOT shrinking the window if the centralWidget() shrinks + canvas->setMinimumSize(QSize(0, 0)); } } else { // QDeclarativeView::SizeRootObjectToView canvas->setMinimumSize(QSize(0,0)); canvas->setMaximumSize(QSize(16777215,16777215)); - setMinimumSize(QSize(0,0)); - setMaximumSize(QSize(16777215,16777215)); } } diff --git a/tools/qml/qmlruntime.h b/tools/qml/qmlruntime.h index 27bd217..e70e69f 100644 --- a/tools/qml/qmlruntime.h +++ b/tools/qml/qmlruntime.h @@ -43,8 +43,7 @@ #define QDECLARATIVEVIEWER_H #include <QMainWindow> -#include <QMenuBar> -#include <private/qdeclarativetimer_p.h> +#include <QTimer> #include <QTime> #include <QList> @@ -62,17 +61,16 @@ class QNetworkReply; class QNetworkCookieJar; class NetworkAccessManagerFactory; class QTranslator; +class QActionGroup; +class QMenuBar; class QDeclarativeViewer -#if defined(Q_OS_SYMBIAN) : public QMainWindow -#else - : public QWidget -#endif { -Q_OBJECT + Q_OBJECT + public: - QDeclarativeViewer(QWidget *parent=0, Qt::WindowFlags flags=0); + QDeclarativeViewer(QWidget *parent = 0, Qt::WindowFlags flags = 0); ~QDeclarativeViewer(); static void registerTypes(); @@ -95,7 +93,7 @@ public: void setRecordFile(const QString&); void setRecordArgs(const QStringList&); void setRecording(bool on); - bool isRecording() const { return recordTimer.isRunning(); } + bool isRecording() const { return recordTimer.isActive(); } void setAutoRecord(int from, int to); void setDeviceKeys(bool); void setNetworkCacheSize(int size); @@ -103,11 +101,8 @@ public: void addPluginPath(const QString& plugin); void setUseGL(bool use); void setUseNativeFileBrowser(bool); - void updateSizeHints(); void setSizeToView(bool sizeToView); - QMenuBar *menuBar() const; - QDeclarativeView *view() const; LoggerWidget *warningsWidget() const; @@ -132,9 +127,11 @@ public slots: protected: virtual void keyPressEvent(QKeyEvent *); virtual bool event(QEvent *); - void createMenu(QMenuBar *menu, QMenu *flatmenu); + void createMenu(); private slots: + void appAboutToQuit(); + void autoStartRecording(); void autoStopRecording(); void recordFrame(); @@ -148,21 +145,22 @@ private slots: void warningsWidgetOpened(); void warningsWidgetClosed(); + void updateSizeHints(); + private: QString getVideoFileName(); - int menuBarHeight() const; LoggerWidget *loggerWindow; QDeclarativeView *canvas; QSize initialSize; QString currentFileOrUrl; - QDeclarativeTimer recordTimer; + QTimer recordTimer; QString frame_fmt; QImage frame; QList<QImage*> frames; QProcess* frame_stream; - QDeclarativeTimer autoStartTimer; - QDeclarativeTimer autoStopTimer; + QTimer autoStartTimer; + QTimer autoStopTimer; QString record_dither; QString record_file; QSize record_outsize; @@ -173,7 +171,6 @@ private: QAction *recordAction; QString currentSkin; bool scaleSkin; - mutable QMenuBar *mb; RecordingDialog *recdlg; void senseImageMagick(); diff --git a/tools/qml/recopts_maemo5.ui b/tools/qml/recopts_maemo5.ui new file mode 100644 index 0000000..3bb5eca --- /dev/null +++ b/tools/qml/recopts_maemo5.ui @@ -0,0 +1,254 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>RecordingOptions</class> + <widget class="QDialog" name="RecordingOptions"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>469</width> + <height>142</height> + </rect> + </property> + <property name="windowTitle"> + <string>Video options</string> + </property> + <layout class="QGridLayout" name="gridLayout" columnstretch="0,2,0"> + <property name="sizeConstraint"> + <enum>QLayout::SetMinAndMaxSize</enum> + </property> + <property name="leftMargin"> + <number>16</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>16</number> + </property> + <property name="bottomMargin"> + <number>8</number> + </property> + <property name="horizontalSpacing"> + <number>16</number> + </property> + <property name="verticalSpacing"> + <number>0</number> + </property> + <item row="0" column="1"> + <widget class="QLineEdit" name="file"/> + </item> + <item row="0" column="2" rowspan="3"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>72</width> + <height>56</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Size</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="sizeCombo"> + <item> + <property name="text"> + <string/> + </property> + </item> + <item> + <property name="text"> + <string>VGA</string> + </property> + </item> + <item> + <property name="text"> + <string>QVGA</string> + </property> + </item> + <item> + <property name="text"> + <string>720p</string> + </property> + </item> + </widget> + </item> + <item row="2" column="0" rowspan="2"> + <widget class="QLabel" name="rateLabel"> + <property name="text"> + <string>Rate</string> + </property> + </widget> + </item> + <item row="2" column="1" rowspan="2"> + <widget class="QComboBox" name="rateCombo"> + <item> + <property name="text"> + <string>60 Hz</string> + </property> + </item> + <item> + <property name="text"> + <string>50 Hz</string> + </property> + </item> + <item> + <property name="text"> + <string>25 Hz</string> + </property> + </item> + <item> + <property name="text"> + <string>24 Hz</string> + </property> + </item> + <item> + <property name="text"> + <string>20 Hz</string> + </property> + </item> + <item> + <property name="text"> + <string>15 Hz</string> + </property> + </item> + <item> + <property name="text"> + <string>10 Hz</string> + </property> + </item> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLineEdit" name="args"/> + </item> + <item row="4" column="1"> + <widget class="QComboBox" name="profile"/> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="profileLabel"> + <property name="text"> + <string>Profile</string> + </property> + </widget> + </item> + <item row="6" column="0" colspan="2"> + <widget class="QLabel" name="warning"> + <property name="text"> + <string notr="true">warning</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="4" column="2" rowspan="3"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QPushButton" name="pickfile"> + <property name="text"> + <string>File</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QPushButton" name="ffmpegHelp"> + <property name="text"> + <string>Options</string> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>RecordingOptions</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>258</x> + <y>424</y> + </hint> + <hint type="destinationlabel"> + <x>60</x> + <y>219</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>RecordingOptions</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>258</x> + <y>424</y> + </hint> + <hint type="destinationlabel"> + <x>92</x> + <y>219</y> + </hint> + </hints> + </connection> + <connection> + <sender>profile</sender> + <signal>activated(int)</signal> + <receiver>RecordingOptions</receiver> + <slot>pickProfile(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>92</x> + <y>329</y> + </hint> + <hint type="destinationlabel"> + <x>48</x> + <y>194</y> + </hint> + </hints> + </connection> + <connection> + <sender>args</sender> + <signal>textEdited(QString)</signal> + <receiver>RecordingOptions</receiver> + <slot>storeCustomArgs(QString)</slot> + <hints> + <hint type="sourcelabel"> + <x>128</x> + <y>357</y> + </hint> + <hint type="destinationlabel"> + <x>102</x> + <y>189</y> + </hint> + </hints> + </connection> + </connections> + <slots> + <signal>filePicked(QString)</signal> + <signal>argumentsPicked(QString)</signal> + <slot>pickFile()</slot> + <slot>pickProfile(int)</slot> + <slot>storeCustomArgs(QString)</slot> + </slots> +</ui> diff --git a/tools/qml/texteditautoresizer_maemo5.h b/tools/qml/texteditautoresizer_maemo5.h new file mode 100644 index 0000000..bb5567a --- /dev/null +++ b/tools/qml/texteditautoresizer_maemo5.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/qplaintextedit.h> +#include <QtGui/qtextedit.h> +#include <QtGui/qabstractkineticscroller.h> +#include <QtGui/qscrollarea.h> +#include <QtDebug> + +#ifndef TEXTEDITAUTORESIZER_H +#define TEXTEDITAUTORESIZER_H + +class TextEditAutoResizer : public QObject +{ + Q_OBJECT +public: + TextEditAutoResizer(QWidget *parent) + : QObject(parent), plainTextEdit(qobject_cast<QPlainTextEdit *>(parent)), + textEdit(qobject_cast<QTextEdit *>(parent)), edit(qobject_cast<QFrame *>(parent)) + { + // parent must either inherit QPlainTextEdit or QTextEdit! + Q_ASSERT(plainTextEdit || textEdit); + + connect(parent, SIGNAL(textChanged()), this, SLOT(textEditChanged())); + connect(parent, SIGNAL(cursorPositionChanged()), this, SLOT(textEditChanged())); + + textEditChanged(); + } + +private Q_SLOTS: + inline void textEditChanged(); + +private: + QPlainTextEdit *plainTextEdit; + QTextEdit *textEdit; + QFrame *edit; +}; + +void TextEditAutoResizer::textEditChanged() +{ + QTextDocument *doc = textEdit ? textEdit->document() : plainTextEdit->document(); + QRect cursor = textEdit ? textEdit->cursorRect() : plainTextEdit->cursorRect(); + + QSize s = doc->size().toSize(); + if (plainTextEdit) + s.setHeight((s.height() + 2) * edit->fontMetrics().lineSpacing()); + + const QRect fr = edit->frameRect(); + const QRect cr = edit->contentsRect(); + + edit->setMinimumHeight(qMax(70, s.height() + (fr.height() - cr.height() - 1))); + + // make sure the cursor is visible in case we have a QAbstractScrollArea parent + QPoint pos = edit->pos(); + QWidget *pw = edit->parentWidget(); + while (pw) { + if (qobject_cast<QScrollArea *>(pw)) + break; + pw = pw->parentWidget(); + } + + if (pw) { + QScrollArea *area = static_cast<QScrollArea *>(pw); + QPoint scrollto = area->widget()->mapFrom(edit, cursor.center()); + QPoint margin(10 + cursor.width(), 2 * cursor.height()); + + if (QAbstractKineticScroller *scroller = area->property("kineticScroller").value<QAbstractKineticScroller *>()) { + scroller->ensureVisible(scrollto, margin.x(), margin.y()); + } else { + area->ensureVisible(scrollto.x(), scrollto.y(), margin.x(), margin.y()); + } + } +} + +#endif diff --git a/tools/runonphone/main.cpp b/tools/runonphone/main.cpp index 885d029..7767e4b 100644 --- a/tools/runonphone/main.cpp +++ b/tools/runonphone/main.cpp @@ -62,6 +62,8 @@ void printUsage(QTextStream& outstream, QString exeName) << "-v, --verbose show debugging output" << endl << "-q, --quiet hide progress messages" << endl << "-d, --download <remote file> <local file> copy file from phone to PC after running test" << endl + << "--nocrashlog Don't capture call stack if test crashes" << endl + << "--crashlogpath <dir> Path to save crash logs (default=working dir)" << endl << endl << "USB COM ports can usually be autodetected, use -p or -f to force a specific port." << endl << "If using System TRK, it is possible to copy the program directly to sys/bin on the phone." << endl @@ -85,6 +87,8 @@ int main(int argc, char *argv[]) QString downloadLocalFile; int loglevel=1; int timeout=0; + bool crashlog = true; + QString crashlogpath; QListIterator<QString> it(args); it.next(); //skip name of program while (it.hasNext()) { @@ -126,6 +130,12 @@ int main(int argc, char *argv[]) loglevel=2; else if (arg == "--quiet" || arg == "-q") loglevel=0; + else if (arg == "--nocrashlog") + crashlog = false; + else if (arg == "--crashlogpath") { + CHECK_PARAMETER_EXISTS + crashlogpath = it.next(); + } else errstream << "unknown command line option " << arg << endl; } else { @@ -145,7 +155,7 @@ int main(int argc, char *argv[]) if (serialPortName.isEmpty()) { if (loglevel > 0) outstream << "Detecting serial ports" << endl; - foreach (const SerialPortId &id, enumerateSerialPorts()) { + foreach (const SerialPortId &id, enumerateSerialPorts(loglevel)) { if (loglevel > 0) outstream << "Port Name: " << id.portName << ", " << "Friendly Name:" << id.friendlyName << endl; @@ -199,6 +209,8 @@ int main(int argc, char *argv[]) TrkSignalHandler handler; handler.setLogLevel(loglevel); + handler.setCrashLogging(crashlog); + handler.setCrashLogPath(crashlogpath); QObject::connect(launcher.data(), SIGNAL(copyingStarted()), &handler, SLOT(copyingStarted())); QObject::connect(launcher.data(), SIGNAL(canNotConnect(const QString &)), &handler, SLOT(canNotConnect(const QString &))); @@ -215,8 +227,12 @@ int main(int argc, char *argv[]) QObject::connect(launcher.data(), SIGNAL(copyProgress(int)), &handler, SLOT(copyProgress(int))); QObject::connect(launcher.data(), SIGNAL(stateChanged(int)), &handler, SLOT(stateChanged(int))); QObject::connect(launcher.data(), SIGNAL(processStopped(uint,uint,uint,QString)), &handler, SLOT(stopped(uint,uint,uint,QString))); + QObject::connect(launcher.data(), SIGNAL(libraryLoaded(trk::Library)), &handler, SLOT(libraryLoaded(trk::Library))); + QObject::connect(launcher.data(), SIGNAL(libraryUnloaded(trk::Library)), &handler, SLOT(libraryUnloaded(trk::Library))); + QObject::connect(launcher.data(), SIGNAL(registersAndCallStackReadComplete(const QList<uint> &,const QByteArray &)), &handler, SLOT(registersAndCallStackReadComplete(const QList<uint> &,const QByteArray &))); QObject::connect(&handler, SIGNAL(resume(uint,uint)), launcher.data(), SLOT(resumeProcess(uint,uint))); QObject::connect(&handler, SIGNAL(terminate()), launcher.data(), SLOT(terminate())); + QObject::connect(&handler, SIGNAL(getRegistersAndCallStack(uint,uint)), launcher.data(), SLOT(getRegistersAndCallStack(uint,uint))); QObject::connect(launcher.data(), SIGNAL(finished()), &handler, SLOT(finished())); QTimer timer; diff --git a/tools/runonphone/serenum.h b/tools/runonphone/serenum.h index b794b97..a65c8cb 100644 --- a/tools/runonphone/serenum.h +++ b/tools/runonphone/serenum.h @@ -51,6 +51,6 @@ struct SerialPortId QString friendlyName; }; -QList<SerialPortId> enumerateSerialPorts(); +QList<SerialPortId> enumerateSerialPorts(int loglevel); #endif // WIN32SERENUM_H diff --git a/tools/runonphone/serenum_unix.cpp b/tools/runonphone/serenum_unix.cpp index b6f0293..db6375e 100644 --- a/tools/runonphone/serenum_unix.cpp +++ b/tools/runonphone/serenum_unix.cpp @@ -48,9 +48,32 @@ #include <usb.h> -QList<SerialPortId> enumerateSerialPorts() +class InterfaceInfo { - QList<QString> eligableInterfaces; +public: + InterfaceInfo(const QString &mf, const QString &pr, int mfid, int prid); + QString manufacturer; + QString product; + int manufacturerid; + int productid; +}; + +InterfaceInfo::InterfaceInfo(const QString &mf, const QString &pr, int mfid, int prid) : + manufacturer(mf), + product(pr), + manufacturerid(mfid), + productid(prid) +{ + if(mf.isEmpty()) + manufacturer = QString("[%1]").arg(mfid, 4, 16, QChar('0')); + if(pr.isEmpty()) + product = QString("[%1]").arg(prid, 4, 16, QChar('0')); +} + +QList<SerialPortId> enumerateSerialPorts(int loglevel) +{ + QList<QString> eligibleInterfaces; + QList<InterfaceInfo> eligibleInterfacesInfo; QList<SerialPortId> list; usb_init(); @@ -85,6 +108,41 @@ QList<SerialPortId> enumerateSerialPorts() } } } + + if (usableInterfaces.isEmpty()) + continue; + + QString manufacturerString; + QString productString; + + usb_dev_handle *devh = usb_open(device); + if (devh) { + QByteArray buf; + buf.resize(256); + int err = usb_get_string_simple(devh, device->descriptor.iManufacturer, buf.data(), buf.size()); + if (err < 0) { + if (loglevel > 1) + qDebug() << " can't read manufacturer name, error:" << err; + } else { + manufacturerString = QString::fromAscii(buf); + if (loglevel > 1) + qDebug() << " manufacturer:" << manufacturerString; + } + + buf.resize(256); + err = usb_get_string_simple(devh, device->descriptor.iProduct, buf.data(), buf.size()); + if (err < 0) { + if (loglevel > 1) + qDebug() << " can't read product name, error:" << err; + } else { + productString = QString::fromAscii(buf); + if (loglevel > 1) + qDebug() << " product:" << productString; + } + usb_close(devh); + } else if (loglevel > 0) { + qDebug() << " can't open usb device"; + } // second loop to find the actual data interface. foreach (int i, usableInterfaces) { @@ -94,11 +152,22 @@ QList<SerialPortId> enumerateSerialPorts() if (descriptor.bInterfaceNumber != i) continue; if (descriptor.bInterfaceClass == 10) { // "CDC Data" - // qDebug() << " found the data port" - // << "bus:" << bus->dirname - // << "device" << device->filename - // << "interface" << descriptor.bInterfaceNumber; - eligableInterfaces << QString("if%1").arg(QString::number(i), 2, QChar('0')); // fix! + if (loglevel > 1) { + qDebug() << " found the data port" + << "bus:" << bus->dirname + << "device" << device->filename + << "interface" << descriptor.bInterfaceNumber; + } + // ### manufacturer and product strings are only readable as root :( + if (!manufacturerString.isEmpty() && !productString.isEmpty()) { + eligibleInterfaces << QString("usb-%1_%2-if%3") + .arg(manufacturerString.replace(QChar(' '), QChar('_'))) + .arg(productString.replace(QChar(' '), QChar('_'))) + .arg(i, 2, 16, QChar('0')); + } else { + eligibleInterfaces << QString("if%1").arg(i, 2, 16, QChar('0')); // fix! + } + eligibleInterfacesInfo << InterfaceInfo(manufacturerString, productString, device->descriptor.idVendor, device->descriptor.idProduct); } } } @@ -106,13 +175,18 @@ QList<SerialPortId> enumerateSerialPorts() } } } + + if (loglevel > 1) + qDebug() << " searching for interfaces:" << eligibleInterfaces; QDir dir("/dev/serial/by-id/"); foreach (const QFileInfo &info, dir.entryInfoList()) { if (!info.isDir()) { - bool usable = eligableInterfaces.isEmpty(); - foreach (const QString &iface, eligableInterfaces) { + bool usable = eligibleInterfaces.isEmpty(); + foreach (const QString &iface, eligibleInterfaces) { if (info.fileName().contains(iface)) { + if (loglevel > 1) + qDebug() << " found device file:" << info.fileName() << endl; usable = true; break; } @@ -126,6 +200,21 @@ QList<SerialPortId> enumerateSerialPorts() list << id; } } + + if (list.isEmpty() && !eligibleInterfacesInfo.isEmpty() && loglevel > 0) { + qDebug() << "Possible USB devices found, but without serial drivers:"; + foreach(const InterfaceInfo &iface, eligibleInterfacesInfo) { + qDebug() << " Manufacturer:" + << iface.manufacturer + << "Product:" + << iface.product + << endl + << " Load generic driver using:" + << QString("sudo modprobe usbserial vendor=0x%1 product=0x%2") + .arg(iface.manufacturerid, 4, 16, QChar('0')) + .arg(iface.productid, 4, 16, QChar('0')); + } + } return list; } diff --git a/tools/runonphone/serenum_win.cpp b/tools/runonphone/serenum_win.cpp index 572161c..070cac2 100644 --- a/tools/runonphone/serenum_win.cpp +++ b/tools/runonphone/serenum_win.cpp @@ -53,7 +53,7 @@ //{4d36e978-e325-11ce-bfc1-08002be10318} //DEFINE_GUID(GUID_DEVCLASS_PORTS, 0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 ); -QList<SerialPortId> enumerateSerialPorts() +QList<SerialPortId> enumerateSerialPorts(int) { DWORD index=0; SP_DEVINFO_DATA info; diff --git a/tools/runonphone/symbianutils/json.cpp b/tools/runonphone/symbianutils/json.cpp new file mode 100644 index 0000000..2d58824 --- /dev/null +++ b/tools/runonphone/symbianutils/json.cpp @@ -0,0 +1,490 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "json.h" + +#ifdef TODO_USE_CREATOR +#include <utils/qtcassert.h> +#endif // TODO_USE_CREATOR + +#include <QtCore/QByteArray> +#include <QtCore/QTextStream> +#include <QtCore/QDebug> +#include <QtCore/QStringList> + +#include <ctype.h> + +//#define DEBUG_JASON +#ifdef DEBUG_JASON +#define JDEBUG(s) qDebug() << s +#else +#define JDEBUG(s) +#endif + +namespace tcftrk { + +static void skipSpaces(const char *&from, const char *to) +{ + while (from != to && isspace(*from)) + ++from; +} + +QTextStream &operator<<(QTextStream &os, const JsonValue &mi) +{ + return os << mi.toString(); +} + +void JsonValue::parsePair(const char *&from, const char *to) +{ + skipSpaces(from, to); + JDEBUG("parsePair: " << QByteArray(from, to - from)); + m_name = parseCString(from, to); + skipSpaces(from, to); + while (from < to && *from != ':') { + JDEBUG("not a colon" << *from); + ++from; + } + ++from; + parseValue(from, to); + skipSpaces(from, to); +} + +QByteArray JsonValue::parseNumber(const char *&from, const char *to) +{ + QByteArray result; + if (from < to && *from == '-') // Leading '-'. + result.append(*from++); + while (from < to && *from >= '0' && *from <= '9') + result.append(*from++); + return result; +} + +QByteArray JsonValue::parseCString(const char *&from, const char *to) +{ + QByteArray result; + JDEBUG("parseCString: " << QByteArray(from, to - from)); + if (*from != '"') { + qDebug() << "JSON Parse Error, double quote expected"; + ++from; // So we don't hang + return QByteArray(); + } + const char *ptr = from; + ++ptr; + while (ptr < to) { + if (*ptr == '"') { + ++ptr; + result = QByteArray(from + 1, ptr - from - 2); + break; + } + if (*ptr == '\\') { + ++ptr; + if (ptr == to) { + qDebug() << "JSON Parse Error, unterminated backslash escape"; + from = ptr; // So we don't hang + return QByteArray(); + } + } + ++ptr; + } + from = ptr; + + int idx = result.indexOf('\\'); + if (idx >= 0) { + char *dst = result.data() + idx; + const char *src = dst + 1, *end = result.data() + result.length(); + do { + char c = *src++; + switch (c) { + case 'a': *dst++ = '\a'; break; + case 'b': *dst++ = '\b'; break; + case 'f': *dst++ = '\f'; break; + case 'n': *dst++ = '\n'; break; + case 'r': *dst++ = '\r'; break; + case 't': *dst++ = '\t'; break; + case 'v': *dst++ = '\v'; break; + case '"': *dst++ = '"'; break; + case '\\': *dst++ = '\\'; break; + default: + { + int chars = 0; + uchar prod = 0; + forever { + if (c < '0' || c > '7') { + --src; + break; + } + prod = prod * 8 + c - '0'; + if (++chars == 3 || src == end) + break; + c = *src++; + } + if (!chars) { + qDebug() << "JSON Parse Error, unrecognized backslash escape"; + return QByteArray(); + } + *dst++ = prod; + } + } + while (src != end) { + char c = *src++; + if (c == '\\') + break; + *dst++ = c; + } + } while (src != end); + *dst = 0; + result.truncate(dst - result.data()); + } + + JDEBUG("parseCString, got " << result); + return result; +} + + + +void JsonValue::parseValue(const char *&from, const char *to) +{ + JDEBUG("parseValue: " << QByteArray(from, to - from)); + switch (*from) { + case '{': + parseObject(from, to); + break; + case 't': + if (to - from >= 4 && qstrncmp(from, "true", 4) == 0) { + m_data = QByteArray(from, 4); + from += m_data.size(); + m_type = Boolean; + } + break; + case 'f': + if (to - from >= 5 && qstrncmp(from, "false", 5) == 0) { + m_data = QByteArray(from, 5); + from += m_data.size(); + m_type = Boolean; + } + break; + case 'n': + if (to - from >= 4 && qstrncmp(from, "null", 4) == 0) { + m_data = QByteArray(from, 4); + from += m_data.size(); + m_type = NullObject; + } + break; + case '[': + parseArray(from, to); + break; + case '"': + m_type = String; + m_data = parseCString(from, to); + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '-': + m_type = Number; + m_data = parseNumber(from, to); + default: + break; + } +} + +void JsonValue::parseObject(const char *&from, const char *to) +{ + JDEBUG("parseObject: " << QByteArray(from, to - from)); +#ifdef TODO_USE_CREATOR + QTC_ASSERT(*from == '{', /**/); +#endif + ++from; + m_type = Object; + while (from < to) { + if (*from == '}') { + ++from; + break; + } + JsonValue child; + child.parsePair(from, to); + if (!child.isValid()) + return; + m_children += child; + if (*from == ',') + ++from; + } +} + +void JsonValue::parseArray(const char *&from, const char *to) +{ + JDEBUG("parseArray: " << QByteArray(from, to - from)); +#ifdef TODO_USE_CREATOR + QTC_ASSERT(*from == '[', /**/); +#endif + ++from; + m_type = Array; + while (from < to) { + if (*from == ']') { + ++from; + break; + } + JsonValue child; + child.parseValue(from, to); + if (child.isValid()) + m_children += child; + if (*from == ',') + ++from; + } +} + +void JsonValue::setStreamOutput(const QByteArray &name, const QByteArray &content) +{ + if (content.isEmpty()) + return; + JsonValue child; + child.m_type = String; + child.m_name = name; + child.m_data = content; + m_children += child; + if (m_type == Invalid) + m_type = Object; +} + +static QByteArray ind(int indent) +{ + return QByteArray(2 * indent, ' '); +} + +void JsonValue::dumpChildren(QByteArray * str, bool multiline, int indent) const +{ + for (int i = 0; i < m_children.size(); ++i) { + if (i != 0) { + *str += ','; + if (multiline) + *str += '\n'; + } + if (multiline) + *str += ind(indent); + *str += m_children.at(i).toString(multiline, indent); + } +} + +class MyString : public QString { +public: + ushort at(int i) const { return constData()[i].unicode(); } +}; + +template<class ST, typename CT> +inline ST escapeCStringTpl(const ST &ba) +{ + ST ret; + ret.reserve(ba.length() * 2); + for (int i = 0; i < ba.length(); ++i) { + CT c = ba.at(i); + switch (c) { + case '\\': ret += "\\\\"; break; + case '\a': ret += "\\a"; break; + case '\b': ret += "\\b"; break; + case '\f': ret += "\\f"; break; + case '\n': ret += "\\n"; break; + case '\r': ret += "\\r"; break; + case '\t': ret += "\\t"; break; + case '\v': ret += "\\v"; break; + case '"': ret += "\\\""; break; + default: + if (c < 32 || c == 127) { + ret += '\\'; + ret += '0' + (c >> 6); + ret += '0' + ((c >> 3) & 7); + ret += '0' + (c & 7); + } else { + ret += c; + } + } + } + return ret; +} + +QString JsonValue::escapeCString(const QString &ba) +{ + return escapeCStringTpl<MyString, ushort>(static_cast<const MyString &>(ba)); +} + +QByteArray JsonValue::escapeCString(const QByteArray &ba) +{ + return escapeCStringTpl<QByteArray, uchar>(ba); +} + +QByteArray JsonValue::toString(bool multiline, int indent) const +{ + QByteArray result; + switch (m_type) { + case Invalid: + if (multiline) + result += ind(indent) + "Invalid\n"; + else + result += "Invalid"; + break; + case String: + if (!m_name.isEmpty()) + result += m_name + "="; + result += '"' + escapeCString(m_data) + '"'; + break; + case Number: + if (!m_name.isEmpty()) + result += '"' + m_name + "\":"; + result += m_data; + break; + case Boolean: + case NullObject: + if (!m_name.isEmpty()) + result += '"' + m_name + "\":"; + result += m_data; + break; + case Object: + if (!m_name.isEmpty()) + result += m_name + '='; + if (multiline) { + result += "{\n"; + dumpChildren(&result, multiline, indent + 1); + result += '\n' + ind(indent) + "}"; + } else { + result += "{"; + dumpChildren(&result, multiline, indent + 1); + result += "}"; + } + break; + case Array: + if (!m_name.isEmpty()) + result += m_name + "="; + if (multiline) { + result += "[\n"; + dumpChildren(&result, multiline, indent + 1); + result += '\n' + ind(indent) + "]"; + } else { + result += "["; + dumpChildren(&result, multiline, indent + 1); + result += "]"; + } + break; + } + return result; +} + +void JsonValue::fromString(const QByteArray &ba) +{ + const char *from = ba.constBegin(); + const char *to = ba.constEnd(); + parseValue(from, to); +} + +JsonValue JsonValue::findChild(const char *name) const +{ + for (int i = 0; i < m_children.size(); ++i) + if (m_children.at(i).m_name == name) + return m_children.at(i); + return JsonValue(); +} + +void JsonInputStream::appendCString(const char *s) +{ + m_target.append('"'); + for (const char *p = s; *p; p++) { + if (*p == '"' || *p == '\\') + m_target.append('\\'); + m_target.append(*p); + } + m_target.append('"'); +} + +void JsonInputStream::appendString(const QString &in) +{ + if (in.isEmpty()) { + m_target.append("\"\""); + return; + } + + const QChar doubleQuote('"'); + const QChar backSlash('\\'); + QString rc; + const int inSize = in.size(); + rc.reserve(in.size() + 5); + rc.append(doubleQuote); + for (int i = 0; i < inSize; i++) { + const QChar c = in.at(i); + if (c == doubleQuote || c == backSlash) + rc.append(backSlash); + rc.append(c); + } + rc.append(doubleQuote); + m_target.append(rc.toUtf8()); + return; +} + +JsonInputStream &JsonInputStream::operator<<(const QStringList &in) +{ + m_target.append('['); + const int count = in.size(); + for (int i = 0 ; i < count; i++) { + if (i) + m_target.append(','); + appendString(in.at(i)); + } + m_target.append(']'); + return *this; +} + +JsonInputStream &JsonInputStream::operator<<(const QVector<QByteArray> &ba) +{ + m_target.append('['); + const int count = ba.size(); + for (int i = 0 ; i < count; i++) { + if (i) + m_target.append(','); + appendCString(ba.at(i).constData()); + } + m_target.append(']'); + return *this; +} + +JsonInputStream &JsonInputStream::operator<<(bool b) +{ + m_target.append(b ? "true" : "false"); + return *this; +} + +} // namespace tcftrk + diff --git a/tools/runonphone/symbianutils/json.h b/tools/runonphone/symbianutils/json.h new file mode 100644 index 0000000..ffcb7ab --- /dev/null +++ b/tools/runonphone/symbianutils/json.h @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SYMBIANUTILS_JSON_H +#define SYMBIANUTILS_JSON_H + +#include "symbianutils_global.h" + +#include <QtCore/QByteArray> +#include <QtCore/QStringList> +#include <QtCore/QVector> + +namespace tcftrk { + +class SYMBIANUTILS_EXPORT JsonValue +{ +public: + JsonValue() : m_type(Invalid) {} + explicit JsonValue(const QByteArray &str) { fromString(str); } + + QByteArray m_name; + QByteArray m_data; + QList<JsonValue> m_children; + + enum Type { + Invalid, + String, + Number, + Boolean, + Object, + NullObject, + Array, + }; + + Type m_type; + + inline Type type() const { return m_type; } + inline QByteArray name() const { return m_name; } + inline bool hasName(const char *name) const { return m_name == name; } + + inline bool isValid() const { return m_type != Invalid; } + inline bool isNumber() const { return m_type == Number; } + inline bool isString() const { return m_type == String; } + inline bool isObject() const { return m_type == Object; } + inline bool isArray() const { return m_type == Array; } + + + inline QByteArray data() const { return m_data; } + inline const QList<JsonValue> &children() const { return m_children; } + inline int childCount() const { return m_children.size(); } + + const JsonValue &childAt(int index) const { return m_children[index]; } + JsonValue &childAt(int index) { return m_children[index]; } + JsonValue findChild(const char *name) const; + + QByteArray toString(bool multiline = false, int indent = 0) const; + void fromString(const QByteArray &str); + void setStreamOutput(const QByteArray &name, const QByteArray &content); + +private: + static QByteArray parseCString(const char *&from, const char *to); + static QByteArray parseNumber(const char *&from, const char *to); + static QByteArray escapeCString(const QByteArray &ba); + static QString escapeCString(const QString &ba); + void parsePair(const char *&from, const char *to); + void parseValue(const char *&from, const char *to); + void parseObject(const char *&from, const char *to); + void parseArray(const char *&from, const char *to); + + void dumpChildren(QByteArray *str, bool multiline, int indent) const; +}; + +/* Thin wrapper around QByteArray for formatting JSON input. Use as in: + * JsonInputStream(byteArray) << '{' << "bla" << ':' << "blup" << '}'; + * Note that strings get double quotes and JSON-escaping, characters should be + * used for the array/hash delimiters. + * */ +class SYMBIANUTILS_EXPORT JsonInputStream { +public: + explicit JsonInputStream(QByteArray &a) : m_target(a) {} + + JsonInputStream &operator<<(char c) { m_target.append(c); return *this; } + JsonInputStream &operator<<(const char *c) { appendCString(c); return *this; } + JsonInputStream &operator<<(const QByteArray &a) { appendCString(a.constData()); return *this; } + JsonInputStream &operator<<(const QString &c) { appendString(c); return *this; } + + // Format as array + JsonInputStream &operator<<(const QStringList &c); + + // Format as array + JsonInputStream &operator<<(const QVector<QByteArray> &ba); + + JsonInputStream &operator<<(bool b); + + JsonInputStream &operator<<(int i) + { m_target.append(QByteArray::number(i)); return *this; } + JsonInputStream &operator<<(unsigned i) + { m_target.append(QByteArray::number(i)); return *this; } + JsonInputStream &operator<<(quint64 i) + { m_target.append(QByteArray::number(i)); return *this; } + +private: + void appendString(const QString &); + void appendCString(const char *c); + + QByteArray &m_target; +}; + +} // namespace tcftrk + +#endif // SYMBIANUTILS_JSON_H diff --git a/tools/runonphone/symbianutils/launcher.cpp b/tools/runonphone/symbianutils/launcher.cpp index ecb067e..ee87480 100644 --- a/tools/runonphone/symbianutils/launcher.cpp +++ b/tools/runonphone/symbianutils/launcher.cpp @@ -58,6 +58,33 @@ namespace trk { +struct CrashReportState { + CrashReportState(); + void clear(); + + typedef uint Thread; + typedef QList<Thread> Threads; + Threads threads; + + QList<uint> registers; + QByteArray stack; + uint sp; + uint fetchingStackPID; + uint fetchingStackTID; +}; + +CrashReportState::CrashReportState() +{ + clear(); +} + +void CrashReportState::clear() +{ + threads.clear(); + stack.clear(); + sp = fetchingStackPID = fetchingStackTID = 0; +} + struct LauncherPrivate { struct CopyState { QString sourceFileName; @@ -86,6 +113,7 @@ struct LauncherPrivate { int m_verbose; Launcher::Actions m_startupActions; bool m_closeDevice; + CrashReportState m_crashReportState; }; LauncherPrivate::LauncherPrivate(const TrkDevicePtr &d) : @@ -202,6 +230,7 @@ void Launcher::setCloseDevice(bool c) bool Launcher::startServer(QString *errorMessage) { errorMessage->clear(); + d->m_crashReportState.clear(); if (d->m_verbose) { QString msg; QTextStream str(&msg); @@ -375,7 +404,7 @@ void Launcher::handleResult(const TrkResult &result) logMessage("TEXT TRACE: " + msg); } } else { - logMessage("APPLICATION OUTPUT: " + result.data); + logMessage("APPLICATION OUTPUT: " + stringFromArray(result.data)); msg = result.data; } msg.replace("\r\n", "\n"); @@ -416,49 +445,54 @@ void Launcher::handleResult(const TrkResult &result) // target->host OS notification case TrkNotifyCreated: { // Notify Created - /* - const char *data = result.data.data(); - byte error = result.data.at(0); - byte type = result.data.at(1); // type: 1 byte; for dll item, this value is 2. - uint pid = extractInt(data + 2); // ProcessID: 4 bytes; - uint tid = extractInt(data + 6); //threadID: 4 bytes - uint codeseg = extractInt(data + 10); //code address: 4 bytes; code base address for the library - uint dataseg = extractInt(data + 14); //data address: 4 bytes; data base address for the library - uint len = extractShort(data + 18); //length: 2 bytes; length of the library name string to follow - QByteArray name = result.data.mid(20, len); // name: library name - - logMessage(prefix + "NOTE: LIBRARY LOAD: " + str); - logMessage(prefix + "TOKEN: " + result.token); - logMessage(prefix + "ERROR: " + int(error)); - logMessage(prefix + "TYPE: " + int(type)); - logMessage(prefix + "PID: " + pid); - logMessage(prefix + "TID: " + tid); - logMessage(prefix + "CODE: " + codeseg); - logMessage(prefix + "DATA: " + dataseg); - logMessage(prefix + "LEN: " + len); - logMessage(prefix + "NAME: " + name); - */ if (result.data.size() < 10) break; + const char *data = result.data.constData(); + const byte error = result.data.at(0); + Q_UNUSED(error) + const byte type = result.data.at(1); // type: 1 byte; for dll item, this value is 2. + const uint tid = extractInt(data + 6); //threadID: 4 bytes + Q_UNUSED(tid) + if (type == kDSOSDLLItem && result.data.size() >=20) { + const Library lib = Library(result); + d->m_session.libraries.push_back(lib); + emit libraryLoaded(lib); + } QByteArray ba; ba.append(result.data.mid(2, 8)); d->m_device->sendTrkMessage(TrkContinue, TrkCallback(), ba, "CONTINUE"); - //d->m_device->sendTrkAck(result.token) break; } case TrkNotifyDeleted: { // NotifyDeleted const ushort itemType = (unsigned char)result.data.at(1); - const ushort len = result.data.size() > 12 ? extractShort(result.data.data() + 10) : ushort(0); + const uint pid = result.data.size() >= 6 ? extractShort(result.data.constData() + 2) : 0; + const uint tid = result.data.size() >= 10 ? extractShort(result.data.constData() + 6) : 0; + Q_UNUSED(tid) + const ushort len = result.data.size() > 12 ? extractShort(result.data.constData() + 10) : ushort(0); const QString name = len ? QString::fromAscii(result.data.mid(12, len)) : QString(); logMessage(QString::fromLatin1("%1 %2 UNLOAD: %3"). arg(QString::fromAscii(prefix)).arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS")). arg(name)); d->m_device->sendTrkAck(result.token); - if (itemType == 0 // process + if (itemType == kDSOSProcessItem // process && result.data.size() >= 10 && d->m_session.pid == extractInt(result.data.data() + 6)) { - copyFileFromRemote(); + if (d->m_startupActions & ActionDownload) + copyFileFromRemote(); + else + disconnectTrk(); + } + else if (itemType == kDSOSDLLItem && len) { + // Remove libraries of process. + for (QList<Library>::iterator it = d->m_session.libraries.begin(); it != d->m_session.libraries.end(); ) { + if ((*it).pid == pid && (*it).name == name) { + emit libraryUnloaded(*it); + it = d->m_session.libraries.erase(it); + } else { + ++it; + } + } } break; } @@ -705,6 +739,15 @@ void Launcher::handleCreateProcess(const TrkResult &result) logMessage(msg); } emit applicationRunning(d->m_session.pid); + //create a "library" entry for the executable which launched the process + Library lib; + lib.pid = d->m_session.pid; + lib.codeseg = d->m_session.codeseg; + lib.dataseg = d->m_session.dataseg; + lib.name = d->m_fileName.toUtf8(); + d->m_session.libraries << lib; + emit libraryLoaded(lib); + QByteArray ba; appendInt(&ba, d->m_session.pid); appendInt(&ba, d->m_session.tid); @@ -856,6 +899,30 @@ QByteArray Launcher::startProcessMessage(const QString &executable, return ba; } +QByteArray Launcher::readMemoryMessage(uint pid, uint tid, uint from, uint len) +{ + QByteArray ba; + ba.reserve(11); + ba.append(char(0x8)); // Options, FIXME: why? + appendShort(&ba, len); + appendInt(&ba, from); + appendInt(&ba, pid); + appendInt(&ba, tid); + return ba; +} + +QByteArray Launcher::readRegistersMessage(uint pid, uint tid) +{ + QByteArray ba; + ba.reserve(15); + ba.append(char(0)); // Register set, only 0 supported + appendShort(&ba, 0); //R0 + appendShort(&ba, 16); // last register CPSR + appendInt(&ba, pid); + appendInt(&ba, tid); + return ba; +} + void Launcher::startInferiorIfNeeded() { emit startingApplication(); @@ -907,4 +974,63 @@ void Launcher::releaseToDeviceManager(Launcher *launcher) sdm->releaseDevice(launcher->trkServerName()); } +void Launcher::getRegistersAndCallStack(uint pid, uint tid) +{ + d->m_device->sendTrkMessage(TrkReadRegisters, + TrkCallback(this, &Launcher::handleReadRegisters), + Launcher::readRegistersMessage(pid, tid)); + d->m_crashReportState.fetchingStackPID = pid; + d->m_crashReportState.fetchingStackTID = tid; +} + +void Launcher::handleReadRegisters(const TrkResult &result) +{ + if(result.errorCode() || result.data.size() < (17*4)) { + terminate(); + return; + } + const char* data = result.data.constData() + 1; + d->m_crashReportState.registers.clear(); + d->m_crashReportState.stack.clear(); + for (int i=0;i<17;i++) { + uint r = extractInt(data); + data += 4; + d->m_crashReportState.registers.append(r); + } + d->m_crashReportState.sp = d->m_crashReportState.registers.at(13); + + const ushort len = 1024 - (d->m_crashReportState.sp % 1024); //read to 1k boundary first + const QByteArray ba = Launcher::readMemoryMessage(d->m_crashReportState.fetchingStackPID, + d->m_crashReportState.fetchingStackTID, + d->m_crashReportState.sp, + len); + d->m_device->sendTrkMessage(TrkReadMemory, TrkCallback(this, &Launcher::handleReadStack), ba); + d->m_crashReportState.sp += len; +} + +void Launcher::handleReadStack(const TrkResult &result) +{ + if (result.errorCode()) { + //error implies memory fault when reaching end of stack + emit registersAndCallStackReadComplete(d->m_crashReportState.registers, d->m_crashReportState.stack); + return; + } + + const uint len = extractShort(result.data.constData() + 1); + d->m_crashReportState.stack.append(result.data.mid(3, len)); + + if (d->m_crashReportState.sp - d->m_crashReportState.registers.at(13) > 0x10000) { + //read enough stack, stop here + emit registersAndCallStackReadComplete(d->m_crashReportState.registers, d->m_crashReportState.stack); + return; + } + //read 1k more + const QByteArray ba = Launcher::readMemoryMessage(d->m_crashReportState.fetchingStackPID, + d->m_crashReportState.fetchingStackTID, + d->m_crashReportState.sp, + 1024); + d->m_device->sendTrkMessage(TrkReadMemory, TrkCallback(this, &Launcher::handleReadStack), ba); + d->m_crashReportState.sp += 1024; +} + } // namespace trk diff --git a/tools/runonphone/symbianutils/launcher.h b/tools/runonphone/symbianutils/launcher.h index 6db69d0..230a122 100644 --- a/tools/runonphone/symbianutils/launcher.h +++ b/tools/runonphone/symbianutils/launcher.h @@ -43,6 +43,7 @@ #define LAUNCHER_H #include "trkdevice.h" +#include "trkutils.h" #include <QtCore/QObject> #include <QtCore/QVariant> @@ -122,6 +123,9 @@ public: // Create Trk message to start a process. static QByteArray startProcessMessage(const QString &executable, const QStringList &arguments); + // Create Trk message to read memory + static QByteArray readMemoryMessage(uint pid, uint tid, uint from, uint len); + static QByteArray readRegistersMessage(uint pid, uint tid); // Parse a TrkNotifyStopped message static bool parseNotifyStopped(const QByteArray &a, uint *pid, uint *tid, uint *address, @@ -149,12 +153,18 @@ signals: void copyProgress(int percent); void stateChanged(int); void processStopped(uint pc, uint pid, uint tid, const QString& reason); + void processResumed(uint pid, uint tid); + void libraryLoaded(const trk::Library &lib); + void libraryUnloaded(const trk::Library &lib); + void registersAndCallStackReadComplete(const QList<uint>& registers, const QByteArray& stack); // Emitted by the destructor, for releasing devices of SymbianDeviceManager by name void destroyed(const QString &serverName); public slots: void terminate(); void resumeProcess(uint pid, uint tid); + //can be used to obtain traceback after a breakpoint / exception + void getRegistersAndCallStack(uint pid, uint tid); private slots: void handleResult(const trk::TrkResult &data); @@ -182,6 +192,8 @@ private: void handleStop(const TrkResult &result); void handleSupportMask(const TrkResult &result); void handleTrkVersion(const TrkResult &result); + void handleReadRegisters(const TrkResult &result); + void handleReadStack(const TrkResult &result); void copyFileToRemote(); void copyFileFromRemote(); diff --git a/tools/runonphone/symbianutils/symbianutils.pri b/tools/runonphone/symbianutils/symbianutils.pri index 6309517..f07e494 100644 --- a/tools/runonphone/symbianutils/symbianutils.pri +++ b/tools/runonphone/symbianutils/symbianutils.pri @@ -1,5 +1,7 @@ INCLUDEPATH *= $$PWD +QT += network + # Input HEADERS += $$PWD/symbianutils_global.h \ $$PWD/callback.h \ @@ -9,14 +11,20 @@ HEADERS += $$PWD/symbianutils_global.h \ $$PWD/launcher.h \ $$PWD/bluetoothlistener.h \ $$PWD/communicationstarter.h \ - $$PWD/symbiandevicemanager.h + $$PWD/symbiandevicemanager.h \ + $$PWD/tcftrkdevice.h \ + $$PWD/tcftrkmessage.h \ + $$PWD/json.h SOURCES += $$PWD/trkutils.cpp \ $$PWD/trkdevice.cpp \ $$PWD/launcher.cpp \ $$PWD/bluetoothlistener.cpp \ $$PWD/communicationstarter.cpp \ - $$PWD/symbiandevicemanager.cpp + $$PWD/symbiandevicemanager.cpp \ + $$PWD/tcftrkdevice.cpp \ + $$PWD/tcftrkmessage.cpp \ + $$PWD/json.cpp # Tests/trklauncher is a console application contains(QT, gui) { diff --git a/tools/runonphone/symbianutils/tcftrkdevice.cpp b/tools/runonphone/symbianutils/tcftrkdevice.cpp new file mode 100644 index 0000000..50e3937 --- /dev/null +++ b/tools/runonphone/symbianutils/tcftrkdevice.cpp @@ -0,0 +1,929 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "tcftrkdevice.h" +#include "json.h" + +#include <QtNetwork/QAbstractSocket> +#include <QtCore/QDebug> +#include <QtCore/QVector> +#include <QtCore/QQueue> +#include <QtCore/QTextStream> +#include <QtCore/QDateTime> +#include <QtCore/QFileInfo> + +enum { debug = 0 }; + +static const char messageTerminatorC[] = "\003\001"; + +namespace tcftrk { +// ------------- TcfTrkCommandError + +TcfTrkCommandError::TcfTrkCommandError() : timeMS(0), code(0), alternativeCode(0) +{ +} + +void TcfTrkCommandError::clear() +{ + timeMS = 0; + code = alternativeCode = 0; + format.clear(); + alternativeOrganization.clear(); +} + +void TcfTrkCommandError::write(QTextStream &str) const +{ + if (timeMS) { + const QDateTime time(QDate(1970, 1, 1)); + str << time.addMSecs(timeMS).toString(Qt::ISODate) << ": Error code: " << code + << " '" << format << '\''; + if (!alternativeOrganization.isEmpty()) + str << " ('" << alternativeOrganization << "', code: " << alternativeCode << ')'; + } else{ + str << "<No error>"; + } +} + +QString TcfTrkCommandError::toString() const +{ + QString rc; + QTextStream str(&rc); + write(str); + return rc; +} + +/* {"Time":1277459762255,"Code":1,"AltCode":-6,"AltOrg":"POSIX","Format":"Unknown error: -6"} */ +bool TcfTrkCommandError::parse(const QVector<JsonValue> &values) +{ + // Parse an arbitrary hash (that could as well be a command response) + // and check for error elements. + unsigned errorKeyCount = 0; + clear(); + do { + if (values.isEmpty() || values.front().type() != JsonValue::Object) + break; + foreach (const JsonValue &c, values.front().children()) { + if (c.name() == "Time") { + timeMS = c.data().toULongLong(); + errorKeyCount++; + } else if (c.name() == "Code") { + code = c.data().toInt(); + errorKeyCount++; + } else if (c.name() == "Format") { + format = c.data(); + errorKeyCount++; + } else if (c.name() == "AltCode") { + alternativeCode = c.data().toInt(); + errorKeyCount++; + } else if (c.name() == "AltOrg") { + alternativeOrganization = c.data(); + errorKeyCount++; + } + } + } while (false); + const bool errorFound = errorKeyCount >= 2u; // Should be at least 'Time', 'Code'. + if (!errorFound) + clear(); + if (debug) { + qDebug() << "TcfTrkCommandError::parse: Found error: " << errorFound; + if (!values.isEmpty()) + qDebug() << values.front().toString(); + } + return errorFound; +} + +// ------------ TcfTrkCommandResult + +TcfTrkCommandResult::TcfTrkCommandResult(Type t) : + type(t), service(LocatorService) +{ +} + +TcfTrkCommandResult::TcfTrkCommandResult(char typeChar, Services s, + const QByteArray &r, + const QVector<JsonValue> &v, + const QVariant &ck) : + type(FailReply), service(s), request(r), values(v), cookie(ck) +{ + switch (typeChar) { + case 'N': + type = FailReply; + break; + case 'P': + type = ProgressReply; + break; + case 'R': + type = commandError.parse(values) ? CommandErrorReply : SuccessReply; + break; + default: + qWarning("Unknown TCF reply type '%c'", typeChar); + } +} + +QString TcfTrkCommandResult::errorString() const +{ + QString rc; + QTextStream str(&rc); + + switch (type) { + case SuccessReply: + case ProgressReply: + str << "<No error>"; + return rc; + case FailReply: + str << "NAK"; + case CommandErrorReply: + commandError.write(str); + break; + } + // Append the failed command for reference + str << " (Command was: '"; + QByteArray printableRequest = request; + printableRequest.replace('\0', '|'); + str << printableRequest << "')"; + return rc; +} + +QString TcfTrkCommandResult::toString() const +{ + QString rc; + QTextStream str(&rc); + str << "Command answer "; + switch (type) { + case SuccessReply: + str << "[success]"; + break; + case CommandErrorReply: + str << "[command error]"; + break; + case FailReply: + str << "[fail (NAK)]"; + break; + case ProgressReply: + str << "[progress]"; + break; + } + str << ", " << values.size() << " values(s) to request: '"; + QByteArray printableRequest = request; + printableRequest.replace('\0', '|'); + str << printableRequest << "' "; + if (cookie.isValid()) + str << " cookie: " << cookie.toString(); + str << '\n'; + for (int i = 0, count = values.size(); i < count; i++) + str << '#' << i << ' ' << values.at(i).toString() << '\n'; + if (type == CommandErrorReply) + str << "Error: " << errorString(); + return rc; +} + +struct TcfTrkSendQueueEntry +{ + typedef TcfTrkDevice::MessageType MessageType; + + explicit TcfTrkSendQueueEntry(MessageType mt, + int tok, + Services s, + const QByteArray &d, + const TcfTrkCallback &cb= TcfTrkCallback(), + const QVariant &ck = QVariant()) : + messageType(mt), service(s), data(d), token(tok), cookie(ck), callback(cb) {} + + MessageType messageType; + Services service; + QByteArray data; + int token; + QVariant cookie; + TcfTrkCallback callback; +}; + +struct TcfTrkDevicePrivate { + typedef TcfTrkDevice::IODevicePtr IODevicePtr; + typedef QHash<int, TcfTrkSendQueueEntry> TokenWrittenMessageMap; + + TcfTrkDevicePrivate(); + + const QByteArray m_messageTerminator; + + IODevicePtr m_device; + unsigned m_verbose; + QByteArray m_readBuffer; + int m_token; + QQueue<TcfTrkSendQueueEntry> m_sendQueue; + TokenWrittenMessageMap m_writtenMessages; + QVector<QByteArray> m_registerNames; +}; + +TcfTrkDevicePrivate::TcfTrkDevicePrivate() : + m_messageTerminator(messageTerminatorC), + m_verbose(0), m_token(0) +{ +} + +TcfTrkDevice::TcfTrkDevice(QObject *parent) : + QObject(parent), d(new TcfTrkDevicePrivate) +{ +} + +TcfTrkDevice::~TcfTrkDevice() +{ + delete d; +} + +QVector<QByteArray> TcfTrkDevice::registerNames() const +{ + return d->m_registerNames; +} + +void TcfTrkDevice::setRegisterNames(const QVector<QByteArray>& n) +{ + d->m_registerNames = n; + if (d->m_verbose) { + QString msg; + QTextStream str(&msg); + const int count = n.size(); + str << "Registers (" << count << "): "; + for (int i = 0; i < count; i++) + str << '#' << i << '=' << n.at(i) << ' '; + emitLogMessage(msg); + } +} + +TcfTrkDevice::IODevicePtr TcfTrkDevice::device() const +{ + return d->m_device; +} + +TcfTrkDevice::IODevicePtr TcfTrkDevice::takeDevice() +{ + const IODevicePtr old = d->m_device; + if (!old.isNull()) { + old.data()->disconnect(this); + d->m_device = IODevicePtr(); + } + d->m_readBuffer.clear(); + d->m_token = 0; + d->m_sendQueue.clear(); + return old; +} + +void TcfTrkDevice::setDevice(const IODevicePtr &dp) +{ + if (dp.data() == d->m_device.data()) + return; + if (dp.isNull()) { + emitLogMessage(QLatin1String("Internal error: Attempt to set NULL device.")); + return; + } + takeDevice(); + d->m_device = dp; + connect(dp.data(), SIGNAL(readyRead()), this, SLOT(slotDeviceReadyRead())); + if (QAbstractSocket *s = qobject_cast<QAbstractSocket *>(dp.data())) { + connect(s, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotDeviceError())); + connect(s, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(slotDeviceSocketStateChanged())); + } +} + +void TcfTrkDevice::slotDeviceError() +{ + const QString message = d->m_device->errorString(); + emitLogMessage(message); + emit error(message); +} + +void TcfTrkDevice::slotDeviceSocketStateChanged() +{ + if (const QAbstractSocket *s = qobject_cast<const QAbstractSocket *>(d->m_device.data())) { + const QAbstractSocket::SocketState st = s->state(); + switch (st) { + case QAbstractSocket::UnconnectedState: + emitLogMessage(QLatin1String("Unconnected")); + break; + case QAbstractSocket::HostLookupState: + emitLogMessage(QLatin1String("HostLookupState")); + break; + case QAbstractSocket::ConnectingState: + emitLogMessage(QLatin1String("Connecting")); + break; + case QAbstractSocket::ConnectedState: + emitLogMessage(QLatin1String("Connected")); + break; + case QAbstractSocket::ClosingState: + emitLogMessage(QLatin1String("Closing")); + break; + default: + emitLogMessage(QString::fromLatin1("State %1").arg(st)); + break; + } + } +} + +static inline QString debugMessage(QByteArray message, const char *prefix = 0) +{ + message.replace('\0', '|'); + const QString messageS = QString::fromLatin1(message); + return prefix ? + (QLatin1String(prefix) + messageS) : messageS; +} + +void TcfTrkDevice::slotDeviceReadyRead() +{ + d->m_readBuffer += d->m_device->readAll(); + // Take complete message off front of readbuffer. + do { + const int messageEndPos = d->m_readBuffer.indexOf(d->m_messageTerminator); + if (messageEndPos == -1) + break; + const QByteArray message = d->m_readBuffer.left(messageEndPos); + if (debug) + qDebug("Read:\n%s", qPrintable(formatData(message))); + if (const int errorCode = parseMessage(message)) { + emitLogMessage(QString::fromLatin1("Parse error %1 for: %2").arg(errorCode).arg(debugMessage(message))); + } + d->m_readBuffer.remove(0, messageEndPos + d->m_messageTerminator.size()); + } while (!d->m_readBuffer.isEmpty()); + checkSendQueue(); // Send off further message +} + +// Split \0-terminated message into tokens, skipping the initial type character +static inline QVector<QByteArray> splitMessage(const QByteArray &message) +{ + QVector<QByteArray> tokens; + tokens.reserve(7); + const int messageSize = message.size(); + for (int pos = 2; pos < messageSize; ) { + const int nextPos = message.indexOf('\0', pos); + if (nextPos == -1) + break; + tokens.push_back(message.mid(pos, nextPos - pos)); + pos = nextPos + 1; + } + return tokens; +} + +int TcfTrkDevice::parseMessage(const QByteArray &message) +{ + if (d->m_verbose) + emitLogMessage(debugMessage(message, "TCF ->")); + // Special JSON parse error message or protocol format error. + // The port is usually closed after receiving it. + // "\3\2{"Time":1276096098255,"Code":3,"Format": "Protocol format error"}" + if (message.startsWith("\003\002")) { + QByteArray text = message.mid(2); + const QString errorMessage = QString::fromLatin1("Parse error received: %1").arg(QString::fromAscii(text)); + emit error(errorMessage); + return 0; + } + if (message.size() < 4 || message.at(1) != '\0') + return 1; + // Split into tokens + const char type = message.at(0); + const QVector<QByteArray> tokens = splitMessage(message); + switch (type) { + case 'E': + return parseTcfEvent(tokens); + case 'R': // Command replies + case 'N': + case 'P': + return parseTcfCommandReply(type, tokens); + default: + emitLogMessage(QString::fromLatin1("Unhandled message type: %1").arg(debugMessage(message))); + return 756; + } + return 0; +} + +int TcfTrkDevice::parseTcfCommandReply(char type, const QVector<QByteArray> &tokens) +{ + typedef TcfTrkDevicePrivate::TokenWrittenMessageMap::iterator TokenWrittenMessageMapIterator; + // Find the corresponding entry in the written messages hash. + const int tokenCount = tokens.size(); + if (tokenCount < 1) + return 234; + bool tokenOk; + const int token = tokens.at(0).toInt(&tokenOk); + if (!tokenOk) + return 235; + const TokenWrittenMessageMapIterator it = d->m_writtenMessages.find(token); + if (it == d->m_writtenMessages.end()) { + qWarning("TcfTrkDevice: Internal error: token %d not found for '%s'", + token, qPrintable(joinByteArrays(tokens))); + return 236; + } + // No callback: remove entry from map, happy + if (!it.value().callback) { + d->m_writtenMessages.erase(it); + return 0; + } + // Parse values into JSON + QVector<JsonValue> values; + values.reserve(tokenCount); + for (int i = 1; i < tokenCount; i++) { + if (!tokens.at(i).isEmpty()) { // Strange: Empty tokens occur. + const JsonValue value(tokens.at(i)); + if (value.isValid()) { + values.push_back(value); + } else { + qWarning("JSON parse error for reply to command token %d: #%d '%s'", + token, i, tokens.at(i).constData()); + d->m_writtenMessages.erase(it); + return -1; + } + } + } + + // Construct result and invoke callback, remove entry from map. + TcfTrkCallback callback = it.value().callback; + TcfTrkCommandResult result(type, it.value().service, it.value().data, + values, it.value().cookie); + d->m_writtenMessages.erase(it); + callback(result); + return 0; +} + +static const char locatorAnswerC[] = "E\0Locator\0Hello\0[\"Locator\"]"; + +int TcfTrkDevice::parseTcfEvent(const QVector<QByteArray> &tokens) +{ + // Event: Ignore the periodical heartbeat event, answer 'Hello', + // emit signal for the rest + if (tokens.size() < 3) + return 433; + const Services service = serviceFromName(tokens.at(0).constData()); + if (service == LocatorService && tokens.at(1) == "peerHeartBeat") + return 0; + QVector<JsonValue> values; + for (int i = 2; i < tokens.size(); i++) { + const JsonValue value(tokens.at(i)); + if (!value.isValid()) + return 434; + values.push_back(value); + } + // Parse known events, emit signals + QScopedPointer<TcfTrkEvent> knownEvent(TcfTrkEvent::parseEvent(service, tokens.at(1), values)); + if (!knownEvent.isNull()) { + // Answer hello event. + if (knownEvent->type() == TcfTrkEvent::LocatorHello) + writeMessage(QByteArray(locatorAnswerC, sizeof(locatorAnswerC))); + emit tcfEvent(*knownEvent); + } + emit genericTcfEvent(service, tokens.at(1), values); + + if (debug || d->m_verbose) { + QString msg; + QTextStream str(&msg); + if (knownEvent.isNull()) { + str << "Event: " << tokens.at(0) << ' ' << tokens.at(1) << '\n'; + foreach(const JsonValue &val, values) + str << " " << val.toString() << '\n'; + } else { + str << knownEvent->toString(); + } + emitLogMessage(msg); + } + + return 0; +} + +unsigned TcfTrkDevice::verbose() const +{ + return d->m_verbose; +} + +void TcfTrkDevice::setVerbose(unsigned v) +{ + d->m_verbose = v; +} + +void TcfTrkDevice::emitLogMessage(const QString &m) +{ + if (debug) + qWarning("%s", qPrintable(m)); + emit logMessage(m); +} + +bool TcfTrkDevice::checkOpen() +{ + if (d->m_device.isNull()) { + emitLogMessage(QLatin1String("Internal error: No device set on TcfTrkDevice.")); + return false; + } + if (!d->m_device->isOpen()) { + emitLogMessage(QLatin1String("Internal error: Device not open in TcfTrkDevice.")); + return false; + } + return true; +} + +void TcfTrkDevice::sendTcfTrkMessage(MessageType mt, Services service, const char *command, + const char *commandParameters, int commandParametersLength, + const TcfTrkCallback &callBack, + const QVariant &cookie) + +{ + if (!checkOpen()) + return; + // Format the message + const int token = d->m_token++; + QByteArray data; + data.reserve(30 + commandParametersLength); + data.append('C'); + data.append('\0'); + data.append(QByteArray::number(token)); + data.append('\0'); + data.append(serviceName(service)); + data.append('\0'); + data.append(command); + data.append('\0'); + if (commandParametersLength) + data.append(commandParameters, commandParametersLength); + const TcfTrkSendQueueEntry entry(mt, token, service, data, callBack, cookie); + d->m_sendQueue.enqueue(entry); + checkSendQueue(); +} + +void TcfTrkDevice::sendTcfTrkMessage(MessageType mt, Services service, const char *command, + const QByteArray &commandParameters, + const TcfTrkCallback &callBack, + const QVariant &cookie) +{ + sendTcfTrkMessage(mt, service, command, commandParameters.constData(), commandParameters.size(), + callBack, cookie); +} + +// Enclose in message frame and write. +void TcfTrkDevice::writeMessage(QByteArray data) +{ + if (!checkOpen()) + return; + + if (d->m_verbose) + emitLogMessage(debugMessage(data, "TCF <-")); + + // Ensure \0-termination which easily gets lost in QByteArray CT. + if (!data.endsWith('\0')) + data.append('\0'); + data += d->m_messageTerminator; + + if (debug > 1) + qDebug("Writing:\n%s", qPrintable(formatData(data))); + + d->m_device->write(data); + if (QAbstractSocket *as = qobject_cast<QAbstractSocket *>(d->m_device.data())) + as->flush(); +} + +void TcfTrkDevice::checkSendQueue() +{ + // Fire off messages or invoke noops until a message with reply is found + // and an entry to writtenMessages is made. + while (d->m_writtenMessages.empty()) { + if (d->m_sendQueue.isEmpty()) + break; + TcfTrkSendQueueEntry entry = d->m_sendQueue.dequeue(); + switch (entry.messageType) { + case MessageWithReply: + d->m_writtenMessages.insert(entry.token, entry); + writeMessage(entry.data); + break; + case MessageWithoutReply: + writeMessage(entry.data); + break; + case NoopMessage: // Invoke the noop-callback for synchronization + if (entry.callback) { + TcfTrkCommandResult noopResult(TcfTrkCommandResult::SuccessReply); + noopResult.cookie = entry.cookie; + entry.callback(noopResult); + } + break; + } + } +} + +// Fix slashes +static inline QString fixFileName(QString in) +{ + in.replace(QLatin1Char('/'), QLatin1Char('\\')); + return in; +} + +// Start a process (consisting of a non-reply setSettings and start). +void TcfTrkDevice::sendProcessStartCommand(const TcfTrkCallback &callBack, + const QString &binaryIn, + unsigned uid, + QStringList arguments, + QString workingDirectory, + bool debugControl, + const QStringList &additionalLibraries, + const QVariant &cookie) +{ + // Obtain the bin directory, expand by c:/sys/bin if missing + const QChar backSlash('\\'); + int slashPos = binaryIn.lastIndexOf(QLatin1Char('/')); + if (slashPos == -1) + slashPos = binaryIn.lastIndexOf(backSlash); + const QString sysBin = QLatin1String("c:/sys/bin"); + const QString binaryFileName = slashPos == -1 ? binaryIn : binaryIn.mid(slashPos + 1); + const QString binaryDirectory = slashPos == -1 ? sysBin : binaryIn.left(slashPos); + const QString binary = fixFileName(binaryDirectory + QLatin1Char('/') + binaryFileName); + + // Fixup: Does argv[0] convention exist on Symbian? + arguments.push_front(binary); + if (workingDirectory.isEmpty()) + workingDirectory = sysBin; + + // Format settings with empty dummy parameter + QByteArray setData; + JsonInputStream setStr(setData); + setStr << "" << '\0' + << '[' << "exeToLaunch" << ',' << "addExecutables" << ',' << "addLibraries" << ']' + << '\0' << '[' + << binary << ',' + << '{' << binaryFileName << ':' << QString::number(uid, 16) << '}' << ',' + << additionalLibraries + << ']'; + sendTcfTrkMessage(MessageWithoutReply, SettingsService, "set", setData); + + QByteArray startData; + JsonInputStream startStr(startData); + startStr << fixFileName(workingDirectory) + << '\0' << binary << '\0' << arguments << '\0' + << QStringList() << '\0' // Env is an array ["PATH=value"] (non-standard) + << debugControl; + sendTcfTrkMessage(MessageWithReply, ProcessesService, "start", startData, callBack, cookie); +} + +void TcfTrkDevice::sendProcessTerminateCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << id; + sendTcfTrkMessage(MessageWithReply, ProcessesService, "terminate", data, callBack, cookie); +} + +void TcfTrkDevice::sendRunControlTerminateCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << id; + sendTcfTrkMessage(MessageWithReply, RunControlService, "terminate", data, callBack, cookie); +} + +// Non-standard: Remove executable from settings +void TcfTrkDevice::sendSettingsRemoveExecutableCommand(const QString &binaryIn, + unsigned uid, + const QStringList &additionalLibraries, + const QVariant &cookie) +{ + QByteArray setData; + JsonInputStream setStr(setData); + setStr << "" << '\0' + << '[' << "removedExecutables" << ',' << "removedLibraries" << ']' + << '\0' << '[' + << '{' << QFileInfo(binaryIn).fileName() << ':' << QString::number(uid, 16) << '}' << ',' + << additionalLibraries + << ']'; + sendTcfTrkMessage(MessageWithoutReply, SettingsService, "set", setData, TcfTrkCallback(), cookie); +} + +void TcfTrkDevice::sendRunControlResumeCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + RunControlResumeMode mode, + unsigned count, + quint64 rangeStart, + quint64 rangeEnd, + const QVariant &cookie) +{ + QByteArray resumeData; + JsonInputStream str(resumeData); + str << id << '\0' << int(mode) << '\0' << count; + switch (mode) { + case RM_STEP_OVER_RANGE: + case RM_STEP_INTO_RANGE: + case RM_REVERSE_STEP_OVER_RANGE: + case RM_REVERSE_STEP_INTO_RANGE: + str << '\0' << '{' << "RANGE_START" << ':' << rangeStart + << ',' << "RANGE_END" << ':' << rangeEnd << '}'; + break; + default: + break; + } + sendTcfTrkMessage(MessageWithReply, RunControlService, "resume", resumeData, callBack, cookie); +} + +void TcfTrkDevice::sendRunControlSuspendCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << id; + sendTcfTrkMessage(MessageWithReply, RunControlService, "suspend", data, callBack, cookie); +} + +void TcfTrkDevice::sendRunControlResumeCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + sendRunControlResumeCommand(callBack, id, RM_RESUME, 1, 0, 0, cookie); +} + +void TcfTrkDevice::sendBreakpointsAddCommand(const TcfTrkCallback &callBack, + const Breakpoint &bp, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << bp; + sendTcfTrkMessage(MessageWithReply, BreakpointsService, "add", data, callBack, cookie); +} + +void TcfTrkDevice::sendBreakpointsRemoveCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + sendBreakpointsRemoveCommand(callBack, QVector<QByteArray>(1, id), cookie); +} + +void TcfTrkDevice::sendBreakpointsRemoveCommand(const TcfTrkCallback &callBack, + const QVector<QByteArray> &ids, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << ids; + sendTcfTrkMessage(MessageWithReply, BreakpointsService, "remove", data, callBack, cookie); +} + +void TcfTrkDevice::sendBreakpointsEnableCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + bool enable, + const QVariant &cookie) +{ + sendBreakpointsEnableCommand(callBack, QVector<QByteArray>(1, id), enable, cookie); +} + +void TcfTrkDevice::sendBreakpointsEnableCommand(const TcfTrkCallback &callBack, + const QVector<QByteArray> &ids, + bool enable, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << ids; + sendTcfTrkMessage(MessageWithReply, BreakpointsService, + enable ? "enable" : "disable", + data, callBack, cookie); +} + +void TcfTrkDevice::sendMemorySetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + quint64 start, const QByteArray& data, + const QVariant &cookie) +{ + QByteArray getData; + JsonInputStream str(getData); + // start/word size/mode. Mode should ideally be 1 (continue on error?) + str << contextId << '\0' << start << '\0' << 1 << '\0' << data.size() << '\0' << 1 + << '\0' << data.toBase64(); + sendTcfTrkMessage(MessageWithReply, MemoryService, "set", getData, callBack, cookie); +} + +void TcfTrkDevice::sendMemoryGetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + quint64 start, quint64 size, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + // start/word size/mode. Mode should ideally be 1 (continue on error?) + str << contextId << '\0' << start << '\0' << 1 << '\0' << size << '\0' << 1; + sendTcfTrkMessage(MessageWithReply, MemoryService, "get", data, callBack, cookie); +} + +QByteArray TcfTrkDevice::parseMemoryGet(const TcfTrkCommandResult &r) +{ + if (r.type != TcfTrkCommandResult::SuccessReply || r.values.size() < 1) + return QByteArray(); + const JsonValue &memoryV = r.values.front(); + + if (memoryV.type() != JsonValue::String || memoryV.data().size() < 2 + || !memoryV.data().endsWith('=')) + return QByteArray(); + // Catch errors reported as hash: + // R.4."TlVMTA==".{"Time":1276786871255,"Code":1,"AltCode":-38,"AltOrg":"POSIX","Format":"BadDescriptor"} + // Not sure what to make of it. + if (r.values.size() >= 2 && r.values.at(1).type() == JsonValue::Object) + qWarning("Error retrieving memory: %s", r.values.at(1).toString(false).constData()); + // decode + const QByteArray memory = QByteArray::fromBase64(memoryV.data()); + if (memory.isEmpty()) + qWarning("Base64 decoding of %s failed.", memoryV.data().constData()); + if (debug) + qDebug("TcfTrkDevice::parseMemoryGet: received %d bytes", memory.size()); + return memory; +} + +void TcfTrkDevice::sendRegistersGetMCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + const QVector<QByteArray> &ids, + const QVariant &cookie) +{ + // TODO: use "Registers" (which uses base64-encoded values) + QByteArray data; + JsonInputStream str(data); + str << contextId << '\0' << ids; + sendTcfTrkMessage(MessageWithReply, SimpleRegistersService, "get", data, callBack, cookie); +} + +void TcfTrkDevice::sendRegistersGetMRangeCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + unsigned start, unsigned count) +{ + const unsigned end = start + count; + if (end > (unsigned)d->m_registerNames.size()) { + qWarning("TcfTrkDevice: No register name set for index %u (size: %d).", end, d->m_registerNames.size()); + return; + } + + QVector<QByteArray> ids; + ids.reserve(count); + for (unsigned i = start; i < end; i++) + ids.push_back(d->m_registerNames.at(i)); + sendRegistersGetMCommand(callBack, contextId, ids, QVariant(start)); +} + +// Set register +void TcfTrkDevice::sendRegistersSetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + const QByteArray &id, + unsigned value, + const QVariant &cookie) +{ + // TODO: use "Registers" (which uses base64-encoded values) + QByteArray data; + JsonInputStream str(data); + str << contextId << '\0' << QVector<QByteArray>(1, id) + << '\0' << QVector<QByteArray>(1, QByteArray::number(value, 16)); + sendTcfTrkMessage(MessageWithReply, SimpleRegistersService, "set", data, callBack, cookie); +} + +// Set register +void TcfTrkDevice::sendRegistersSetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + unsigned registerNumber, + unsigned value, + const QVariant &cookie) +{ + if (registerNumber >= (unsigned)d->m_registerNames.size()) { + qWarning("TcfTrkDevice: No register name set for index %u (size: %d).", registerNumber, d->m_registerNames.size()); + return; + } + sendRegistersSetCommand(callBack, contextId, + d->m_registerNames[registerNumber], + value, cookie); +} + +} // namespace tcftrk diff --git a/tools/runonphone/symbianutils/tcftrkdevice.h b/tools/runonphone/symbianutils/tcftrkdevice.h new file mode 100644 index 0000000..67955e5 --- /dev/null +++ b/tools/runonphone/symbianutils/tcftrkdevice.h @@ -0,0 +1,295 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TCFTRKENGINE_H +#define TCFTRKENGINE_H + +#include "symbianutils_global.h" +#include "tcftrkmessage.h" +#include "callback.h" +#include "json.h" + +#include <QtCore/QObject> +#include <QtCore/QSharedPointer> +#include <QtCore/QVector> +#include <QtCore/QVariant> +#include <QtCore/QStringList> + +QT_BEGIN_NAMESPACE +class QIODevice; +class QTextStream; +QT_END_NAMESPACE + +namespace tcftrk { + +struct TcfTrkDevicePrivate; +struct Breakpoint; + +/* Command error handling in TCF: + * 1) 'Severe' errors (JSON format, parameter format): Trk emits a + * nonstandard message (\3\2 error paramaters) and closes the connection. + * 2) Protocol errors: 'N' without error message is returned. + * 3) Errors in command execution: 'R' with a TCF error hash is returned + * (see TcfTrkCommandError). */ + +/* Error code return in 'R' reply to command + * (see top of 'Services' documentation). */ +struct SYMBIANUTILS_EXPORT TcfTrkCommandError { + TcfTrkCommandError(); + void clear(); + operator bool() const { return timeMS != 0; } + QString toString() const; + void write(QTextStream &str) const; + bool parse(const QVector<JsonValue> &values); + + quint64 timeMS; // Since 1.1.1970 + int code; + QByteArray format; // message + // 'Alternative' meaning, like altOrg="POSIX"/altCode=<some errno> + QByteArray alternativeOrganization; + int alternativeCode; +}; + +/* Answer to a Tcf command passed to the callback. */ +struct SYMBIANUTILS_EXPORT TcfTrkCommandResult { + enum Type { + SuccessReply, // 'R' and no error -> all happy. + CommandErrorReply, // 'R' with TcfTrkCommandError received + ProgressReply, // 'P', progress indicator + FailReply // 'N' Protocol NAK, severe error + }; + + explicit TcfTrkCommandResult(Type t = SuccessReply); + explicit TcfTrkCommandResult(char typeChar, Services service, + const QByteArray &request, + const QVector<JsonValue> &values, + const QVariant &cookie); + + QString toString() const; + QString errorString() const; + operator bool() const { return type == SuccessReply || type == ProgressReply; } + + Type type; + Services service; + QByteArray request; + TcfTrkCommandError commandError; + QVector<JsonValue> values; + QVariant cookie; +}; + +typedef trk::Callback<const TcfTrkCommandResult &> TcfTrkCallback; + +/* TcfTrkDevice: TCF communication helper using an asynchronous QIODevice + * implementing the TCF protocol according to: +http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Specification.html +http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Services.html + * Commands can be sent along with callbacks that are passed a + * TcfTrkCommandResult and an opaque QVariant cookie. In addition, events are emitted. +*/ + +class SYMBIANUTILS_EXPORT TcfTrkDevice : public QObject +{ + Q_PROPERTY(unsigned verbose READ verbose WRITE setVerbose) + Q_OBJECT +public: + enum MessageType { MessageWithReply, + MessageWithoutReply, /* Non-standard: "Settings:set" command does not reply */ + NoopMessage }; + + typedef QSharedPointer<QIODevice> IODevicePtr; + + explicit TcfTrkDevice(QObject *parent = 0); + virtual ~TcfTrkDevice(); + + unsigned verbose() const; + + // Mapping of register names for indices + QVector<QByteArray> registerNames() const; + void setRegisterNames(const QVector<QByteArray>& n); + + IODevicePtr device() const; + IODevicePtr takeDevice(); + void setDevice(const IODevicePtr &dp); + + void sendTcfTrkMessage(MessageType mt, Services service, + const char *command, + const char *commandParameters, int commandParametersLength, + const TcfTrkCallback &callBack = TcfTrkCallback(), + const QVariant &cookie = QVariant()); + + void sendTcfTrkMessage(MessageType mt, Services service, const char *command, + const QByteArray &commandParameters, + const TcfTrkCallback &callBack = TcfTrkCallback(), + const QVariant &cookie = QVariant()); + + // Convenience messages: Start a process + void sendProcessStartCommand(const TcfTrkCallback &callBack, + const QString &binary, + unsigned uid, + QStringList arguments = QStringList(), + QString workingDirectory = QString(), + bool debugControl = true, + const QStringList &additionalLibraries = QStringList(), + const QVariant &cookie = QVariant()); + + // Preferred over Processes:Terminate by TCF TRK. + void sendRunControlTerminateCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + void sendProcessTerminateCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + // Non-standard: Remove executable from settings. + // Probably needs to be called after stopping. This command has no response. + void sendSettingsRemoveExecutableCommand(const QString &binaryIn, + unsigned uid, + const QStringList &additionalLibraries = QStringList(), + const QVariant &cookie = QVariant()); + + void sendRunControlSuspendCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + // Resume / Step (see RunControlResumeMode). + void sendRunControlResumeCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + RunControlResumeMode mode, + unsigned count /* = 1, currently ignored. */, + quint64 rangeStart, quint64 rangeEnd, + const QVariant &cookie = QVariant()); + + // Convenience to resume a suspended process + void sendRunControlResumeCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + void sendBreakpointsAddCommand(const TcfTrkCallback &callBack, + const Breakpoint &b, + const QVariant &cookie = QVariant()); + + void sendBreakpointsRemoveCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + void sendBreakpointsRemoveCommand(const TcfTrkCallback &callBack, + const QVector<QByteArray> &id, + const QVariant &cookie = QVariant()); + + void sendBreakpointsEnableCommand(const TcfTrkCallback &callBack, + const QByteArray &id, + bool enable, + const QVariant &cookie = QVariant()); + + void sendBreakpointsEnableCommand(const TcfTrkCallback &callBack, + const QVector<QByteArray> &id, + bool enable, + const QVariant &cookie = QVariant()); + + + void sendMemoryGetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + quint64 start, quint64 size, + const QVariant &cookie = QVariant()); + + void sendMemorySetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + quint64 start, const QByteArray& data, + const QVariant &cookie = QVariant()); + + // Reply is an array of hexvalues + void sendRegistersGetMCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + const QVector<QByteArray> &ids, + const QVariant &cookie = QVariant()); + + // Convenience to get a range of register "R0" .. "R<n>". + // Cookie will be an int containing "start". + void sendRegistersGetMRangeCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + unsigned start, unsigned count); + + // Set register + void sendRegistersSetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + const QByteArray &ids, + unsigned value, + const QVariant &cookie = QVariant()); + // Set register + void sendRegistersSetCommand(const TcfTrkCallback &callBack, + const QByteArray &contextId, + unsigned registerNumber, + unsigned value, + const QVariant &cookie = QVariant()); + + static QByteArray parseMemoryGet(const TcfTrkCommandResult &r); + +signals: + void genericTcfEvent(int service, const QByteArray &name, const QVector<tcftrk::JsonValue> &value); + void tcfEvent(const tcftrk::TcfTrkEvent &knownEvent); + + void logMessage(const QString &); + void error(const QString &); + +public slots: + void setVerbose(unsigned v); + +private slots: + void slotDeviceError(); + void slotDeviceSocketStateChanged(); + void slotDeviceReadyRead(); + +private: + bool checkOpen(); + void checkSendQueue(); + void writeMessage(QByteArray data); + void emitLogMessage(const QString &); + int parseMessage(const QByteArray &); + int parseTcfCommandReply(char type, const QVector<QByteArray> &tokens); + int parseTcfEvent(const QVector<QByteArray> &tokens); + + TcfTrkDevicePrivate *d; +}; + +} // namespace tcftrk + +#endif // TCFTRKENGINE_H diff --git a/tools/runonphone/symbianutils/tcftrkmessage.cpp b/tools/runonphone/symbianutils/tcftrkmessage.cpp new file mode 100644 index 0000000..06035ab --- /dev/null +++ b/tools/runonphone/symbianutils/tcftrkmessage.cpp @@ -0,0 +1,562 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "tcftrkmessage.h" +#include "json.h" + +#include <QtCore/QString> +#include <QtCore/QTextStream> + +// Names matching the enum +static const char *serviceNamesC[] = +{ "Locator", "RunControl", "Processes", "Memory", "Settings", "Breakpoints", + "Registers", "SimpleRegisters", + "UnknownService"}; + +namespace tcftrk { + +SYMBIANUTILS_EXPORT QString joinByteArrays(const QVector<QByteArray> &a, char sep) +{ + QString rc; + const int count = a.size(); + for (int i = 0; i < count; i++) { + if (i) + rc += QLatin1Char(sep); + rc += QString::fromUtf8(a.at(i)); + } + return rc; +} + +static inline bool jsonToBool(const JsonValue& js) +{ + return js.type() == JsonValue::Boolean && js.data() == "true"; +} + +SYMBIANUTILS_EXPORT const char *serviceName(Services s) +{ + return serviceNamesC[s]; +} + +SYMBIANUTILS_EXPORT Services serviceFromName(const char *n) +{ + const int count = sizeof(serviceNamesC)/sizeof(char *); + for (int i = 0; i < count; i++) + if (!qstrcmp(serviceNamesC[i], n)) + return static_cast<Services>(i); + return UnknownService; +} + +SYMBIANUTILS_EXPORT QString formatData(const QByteArray &a) +{ + const int columns = 16; + QString rc; + QTextStream str(&rc); + str.setIntegerBase(16); + str.setPadChar(QLatin1Char('0')); + const unsigned char *start = reinterpret_cast<const unsigned char *>(a.constData()); + const unsigned char *end = start + a.size(); + for (const unsigned char *p = start; p < end ; ) { + str << "0x"; + str.setFieldWidth(4); + str << (p - start); + str.setFieldWidth(0); + str << ' '; + QString asc; + int c = 0; + for ( ; c < columns && p < end; c++, p++) { + const unsigned u = *p; + str.setFieldWidth(2); + str << u; + str.setFieldWidth(0); + str << ' '; + switch (u) { + case '\n': + asc += QLatin1String("\\n"); + break; + case '\r': + asc += QLatin1String("\\r"); + break; + case '\t': + asc += QLatin1String("\\t"); + break; + default: + if (u >= 32 && u < 128) { + asc += QLatin1Char(' '); + asc += QLatin1Char(u); + } else { + asc += QLatin1String(" ."); + } + break; + } + } + if (const int remainder = columns - c) + str << QString(3 * remainder, QLatin1Char(' ')); + str << ' ' << asc << '\n'; + } + return rc; +} + +// ----------- RunControlContext +RunControlContext::RunControlContext() : + flags(0), resumeFlags(0) +{ +} + +void RunControlContext::clear() +{ + flags =0; + resumeFlags = 0; + id.clear(); + osid.clear(); + parentId.clear(); +} + +RunControlContext::Type RunControlContext::typeFromTcfId(const QByteArray &id) +{ + // "p12" or "p12.t34"? + return id.contains(".t") ? Thread : Process; +} + +unsigned RunControlContext::processId() const +{ + return processIdFromTcdfId(id); +} + +unsigned RunControlContext::threadId() const +{ + return threadIdFromTcdfId(id); +} + +unsigned RunControlContext::processIdFromTcdfId(const QByteArray &id) +{ + // Cut out process id from "p12" or "p12.t34"? + if (!id.startsWith('p')) + return 0; + const int dotPos = id.indexOf('.'); + const int pLen = dotPos == -1 ? id.size() : dotPos; + return id.mid(1, pLen - 1).toUInt(); +} + +unsigned RunControlContext::threadIdFromTcdfId(const QByteArray &id) +{ + const int tPos = id.indexOf(".t"); + return tPos != -1 ? id.mid(tPos + 2).toUInt() : uint(0); +} + +QByteArray RunControlContext::tcfId(unsigned processId, unsigned threadId /* = 0 */) +{ + QByteArray rc("p"); + rc += QByteArray::number(processId); + if (threadId) { + rc += ".t"; + rc += QByteArray::number(threadId); + } + return rc; +} + +RunControlContext::Type RunControlContext::type() const +{ + return RunControlContext::typeFromTcfId(id); +} + +bool RunControlContext::parse(const JsonValue &val) +{ + clear(); + if (val.type() != JsonValue::Object) + return false; + foreach(const JsonValue &c, val.children()) { + if (c.name() == "ID") { + id = c.data(); + } else if (c.name() == "OSID") { + osid = c.data(); + } else if (c.name() == "ParentID") { + parentId = c.data(); + } else if (c.name() == "IsContainer") { + if (jsonToBool(c)) + flags |= Container; + } else if (c.name() == "CanTerminate") { + if (jsonToBool(c)) + flags |= CanTerminate; + } else if (c.name() == "CanResume") { + resumeFlags = c.data().toUInt(); + } else if (c.name() == "HasState") { + if (jsonToBool(c)) + flags |= HasState; + } else if (c.name() == "CanSuspend") { + if (jsonToBool(c)) + flags |= CanSuspend; + } + } + return true; +} + +QString RunControlContext::toString() const +{ + QString rc; + QTextStream str(&rc); + format(str); + return rc; +} + +void RunControlContext::format(QTextStream &str) const +{ + str << " id='" << id << "' osid='" << osid + << "' parentId='" << parentId <<"' "; + if (flags & Container) + str << "[container] "; + if (flags & HasState) + str << "[has state] "; + if (flags & CanSuspend) + str << "[can suspend] "; + if (flags & CanSuspend) + str << "[can terminate] "; + str.setIntegerBase(16); + str << " resume_flags: 0x" << resumeFlags; + str.setIntegerBase(10); +} + +// ------ ModuleLoadEventInfo +ModuleLoadEventInfo::ModuleLoadEventInfo() : + loaded(false), codeAddress(0), dataAddress(0), requireResume(false) +{ +} + +void ModuleLoadEventInfo::clear() +{ + loaded = requireResume = false; + codeAddress = dataAddress =0; +} + +bool ModuleLoadEventInfo::parse(const JsonValue &val) +{ + clear(); + if (val.type() != JsonValue::Object) + return false; + foreach(const JsonValue &c, val.children()) { + if (c.name() == "Name") { + name = c.data(); + } else if (c.name() == "File") { + file = c.data(); + } else if (c.name() == "CodeAddress") { + codeAddress = c.data().toULongLong(); + } else if (c.name() == "DataAddress") { + dataAddress = c.data().toULongLong(); + } else if (c.name() == "Loaded") { + loaded = jsonToBool(c); + } else if (c.name() == "RequireResume") { + requireResume =jsonToBool(c); + } + } + return true; +} +void ModuleLoadEventInfo::format(QTextStream &str) const +{ + str << "name='" << name << "' file='" << file << "' " << + (loaded ? "[loaded] " : "[not loaded] "); + if (requireResume) + str << "[requires resume] "; + str.setIntegerBase(16); + str << " code: 0x" << codeAddress << " data: 0x" << dataAddress; + str.setIntegerBase(10); +} + +// ---------------------- Breakpoint + +// Types matching enum +static const char *breakPointTypesC[] = {"Software", "Hardware", "Auto"}; + +Breakpoint::Breakpoint(quint64 loc) : + type(Auto), enabled(true), ignoreCount(0), location(loc), size(1), thumb(true) +{ + if (loc) + id = idFromLocation(location); +} + +void Breakpoint::setContextId(unsigned processId, unsigned threadId) +{ + contextIds = QVector<QByteArray>(1, RunControlContext::tcfId(processId, threadId)); +} + +QByteArray Breakpoint::idFromLocation(quint64 loc) +{ + return QByteArray("BP_0x") + QByteArray::number(loc, 16); +} + +QString Breakpoint::toString() const +{ + QString rc; + QTextStream str(&rc); + str.setIntegerBase(16); + str << "Breakpoint '" << id << "' " << breakPointTypesC[type] << " for contexts '" + << joinByteArrays(contextIds, ',') << "' at 0x" << location; + str.setIntegerBase(10); + str << " size " << size; + if (enabled) + str << " [enabled]"; + if (thumb) + str << " [thumb]"; + if (ignoreCount) + str << " IgnoreCount " << ignoreCount; + return rc; +} + +JsonInputStream &operator<<(JsonInputStream &str, const Breakpoint &b) +{ + if (b.contextIds.isEmpty()) + qWarning("tcftrk::Breakpoint: No context ids specified"); + + str << '{' << "ID" << ':' << QString::fromUtf8(b.id) << ',' + << "BreakpointType" << ':' << breakPointTypesC[b.type] << ',' + << "Enabled" << ':' << b.enabled << ',' + << "IgnoreCount" << ':' << b.ignoreCount << ',' + << "ContextIds" << ':' << b.contextIds << ',' + << "Location" << ':' << QString::number(b.location) << ',' + << "Size" << ':' << b.size << ',' + << "THUMB_BREAKPOINT" << ':' << b.thumb + << '}'; + return str; +} + +// --- Events +TcfTrkEvent::TcfTrkEvent(Type type) : m_type(type) +{ +} + +TcfTrkEvent::~TcfTrkEvent() +{ +} + +TcfTrkEvent::Type TcfTrkEvent::type() const +{ + return m_type; +} + +QString TcfTrkEvent::toString() const +{ + return QString(); +} + +static const char sharedLibrarySuspendReasonC[] = "Shared Library"; + +TcfTrkEvent *TcfTrkEvent::parseEvent(Services s, const QByteArray &nameBA, const QVector<JsonValue> &values) +{ + switch (s) { + case LocatorService: + if (nameBA == "Hello" && values.size() == 1 && values.front().type() == JsonValue::Array) { + QStringList services; + foreach (const JsonValue &jv, values.front().children()) + services.push_back(QString::fromUtf8(jv.data())); + return new TcfTrkLocatorHelloEvent(services); + } + break; + case RunControlService: + if (values.empty()) + return 0; + // "id/PC/Reason/Data" + if (nameBA == "contextSuspended" && values.size() == 4) { + const QByteArray idBA = values.at(0).data(); + const quint64 pc = values.at(1).data().toULongLong(); + const QByteArray reasonBA = values.at(2).data(); + // Module load: Special + if (reasonBA == sharedLibrarySuspendReasonC) { + ModuleLoadEventInfo info; + if (!info.parse(values.at(3))) + return 0; + return new TcfTrkRunControlModuleLoadContextSuspendedEvent(idBA, reasonBA, pc, info); + } + return new TcfTrkRunControlContextSuspendedEvent(idBA, reasonBA, pc); + } // "contextSuspended" + if (nameBA == "contextAdded") + return TcfTrkRunControlContextAddedEvent::parseEvent(values); + if (nameBA == "contextRemoved" && values.front().type() == JsonValue::Array) { + QVector<QByteArray> ids; + foreach(const JsonValue &c, values.front().children()) + ids.push_back(c.data()); + return new TcfTrkRunControlContextRemovedEvent(ids); + } + break; + default: + break; + } + return 0; +} + +// -------------- TcfTrkServiceHelloEvent +TcfTrkLocatorHelloEvent::TcfTrkLocatorHelloEvent(const QStringList &s) : + TcfTrkEvent(LocatorHello), + m_services(s) +{ +} + +QString TcfTrkLocatorHelloEvent::toString() const +{ + return QLatin1String("ServiceHello: ") + m_services.join(QLatin1String(", ")); +} + +// -------------- TcfTrkIdEvent +TcfTrkIdEvent::TcfTrkIdEvent(Type t, const QByteArray &id) : + TcfTrkEvent(t), m_id(id) +{ +} + +// ---------- TcfTrkIdsEvent +TcfTrkIdsEvent::TcfTrkIdsEvent(Type t, const QVector<QByteArray> &ids) : + TcfTrkEvent(t), m_ids(ids) +{ +} + +QString TcfTrkIdsEvent::joinedIdString(const char sep) const +{ + return joinByteArrays(m_ids, sep); +} + +// ---------------- TcfTrkRunControlContextAddedEvent +TcfTrkRunControlContextAddedEvent::TcfTrkRunControlContextAddedEvent(const RunControlContexts &c) : + TcfTrkEvent(RunControlContextAdded), m_contexts(c) +{ +} + +TcfTrkRunControlContextAddedEvent + *TcfTrkRunControlContextAddedEvent::parseEvent(const QVector<JsonValue> &values) +{ + // Parse array of contexts + if (values.size() < 1 || values.front().type() != JsonValue::Array) + return 0; + + RunControlContexts contexts; + foreach (const JsonValue &v, values.front().children()) { + RunControlContext context; + if (context.parse(v)) + contexts.push_back(context); + } + return new TcfTrkRunControlContextAddedEvent(contexts); +} + +QString TcfTrkRunControlContextAddedEvent::toString() const +{ + QString rc; + QTextStream str(&rc); + str << "RunControl: " << m_contexts.size() << " context(s) " + << (type() == RunControlContextAdded ? "added" : "removed") + << '\n'; + foreach (const RunControlContext &c, m_contexts) { + c.format(str); + str << '\n'; + } + return rc; +} + +// --------------- TcfTrkRunControlContextRemovedEvent +TcfTrkRunControlContextRemovedEvent::TcfTrkRunControlContextRemovedEvent(const QVector<QByteArray> &ids) : + TcfTrkIdsEvent(RunControlContextRemoved, ids) +{ +} + +QString TcfTrkRunControlContextRemovedEvent::toString() const +{ + return QLatin1String("RunControl: Removed contexts '") + joinedIdString() + ("'."); +} + +// --------------- TcfTrkRunControlContextSuspendedEvent +TcfTrkRunControlContextSuspendedEvent::TcfTrkRunControlContextSuspendedEvent(const QByteArray &id, + const QByteArray &reason, + quint64 pc) : + TcfTrkIdEvent(RunControlSuspended, id), m_pc(pc), m_reason(reason) +{ +} + +TcfTrkRunControlContextSuspendedEvent::TcfTrkRunControlContextSuspendedEvent(Type t, + const QByteArray &id, + const QByteArray &reason, + quint64 pc) : + TcfTrkIdEvent(t, id), m_pc(pc), m_reason(reason) +{ +} + +void TcfTrkRunControlContextSuspendedEvent::format(QTextStream &str) const +{ + str.setIntegerBase(16); + str << "RunControl: '" << idString() << "' suspended at 0x" + << m_pc << ": '" << m_reason << "'."; + str.setIntegerBase(10); +} + +QString TcfTrkRunControlContextSuspendedEvent::toString() const +{ + QString rc; + QTextStream str(&rc); + format(str); + return rc; +} + +TcfTrkRunControlContextSuspendedEvent::Reason TcfTrkRunControlContextSuspendedEvent::reason() const +{ + if (m_reason == sharedLibrarySuspendReasonC) + return ModuleLoad; + if (m_reason == "Breakpoint") + return BreakPoint; + // 'Data abort exception'/'Thread has panicked' ... unfortunately somewhat unspecific. + if (m_reason.contains("exception") || m_reason.contains("panick")) + return Crash; + return Other; +} + +TcfTrkRunControlModuleLoadContextSuspendedEvent::TcfTrkRunControlModuleLoadContextSuspendedEvent(const QByteArray &id, + const QByteArray &reason, + quint64 pc, + const ModuleLoadEventInfo &mi) : + TcfTrkRunControlContextSuspendedEvent(RunControlModuleLoadSuspended, id, reason, pc), + m_mi(mi) +{ +} + +QString TcfTrkRunControlModuleLoadContextSuspendedEvent::toString() const +{ + QString rc; + QTextStream str(&rc); + TcfTrkRunControlContextSuspendedEvent::format(str); + str << ' '; + m_mi.format(str); + return rc; +} + + +} // namespace tcftrk diff --git a/tools/runonphone/symbianutils/tcftrkmessage.h b/tools/runonphone/symbianutils/tcftrkmessage.h new file mode 100644 index 0000000..510b485 --- /dev/null +++ b/tools/runonphone/symbianutils/tcftrkmessage.h @@ -0,0 +1,296 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TRCFTRKMESSAGE_H +#define TRCFTRKMESSAGE_H + +#include "symbianutils_global.h" + +#include <QtCore/QStringList> +#include <QtCore/QVector> + +QT_BEGIN_NAMESPACE +class QTextStream; +QT_END_NAMESPACE + +namespace tcftrk { + +class JsonValue; +class JsonInputStream; + +enum Services { + LocatorService, + RunControlService, + ProcessesService, + MemoryService, + SettingsService, // non-standard, trk specific + BreakpointsService, + RegistersService, + SimpleRegistersService, // non-standard, trk specific + UnknownService +}; // Note: Check string array 'serviceNamesC' of same size when modifying this. + +// Modes of RunControl/'Resume' (see EDF documentation). +// As of 24.6.2010, RM_RESUME, RM_STEP_OVER, RM_STEP_INTO, +// RM_STEP_OVER_RANGE, RM_STEP_INTO_RANGE are supported with +// RANG_START/RANGE_END parameters. +enum RunControlResumeMode { + RM_RESUME = 0, + RM_STEP_OVER = 1, RM_STEP_INTO = 2, + RM_STEP_OVER_LINE = 3, RM_STEP_INTO_LINE = 4, + RM_STEP_OUT = 5, RM_REVERSE_RESUME = 6, + RM_REVERSE_STEP_OVER = 7, RM_REVERSE_STEP_INTO = 8, + RM_REVERSE_STEP_OVER_LINE = 9, RM_REVERSE_STEP_INTO_LINE = 10, + RM_REVERSE_STEP_OUT = 11, RM_STEP_OVER_RANGE = 12, + RM_STEP_INTO_RANGE = 13, RM_REVERSE_STEP_OVER_RANGE = 14, + RM_REVERSE_STEP_INTO_RANGE = 15 +}; + +SYMBIANUTILS_EXPORT const char *serviceName(Services s); +SYMBIANUTILS_EXPORT Services serviceFromName(const char *); + +// Debug helpers +SYMBIANUTILS_EXPORT QString formatData(const QByteArray &a); +SYMBIANUTILS_EXPORT QString joinByteArrays(const QVector<QByteArray> &a, char sep = ','); + +// Context used in 'RunControl contextAdded' events and in reply +// to 'Processes start'. Could be thread or process. +struct SYMBIANUTILS_EXPORT RunControlContext { + enum Flags { + Container = 0x1, HasState = 0x2, CanSuspend = 0x4, + CanTerminate = 0x8 + }; + enum Type { Process, Thread }; + + RunControlContext(); + Type type() const; + unsigned processId() const; + unsigned threadId() const; + + void clear(); + bool parse(const JsonValue &v); + void format(QTextStream &str) const; + QString toString() const; + + // Helper for converting the TCF ids ("p12" or "p12.t34") + static Type typeFromTcfId(const QByteArray &id); + static unsigned processIdFromTcdfId(const QByteArray &id); + static unsigned threadIdFromTcdfId(const QByteArray &id); + static QByteArray tcfId(unsigned processId, unsigned threadId = 0); + + unsigned flags; + unsigned resumeFlags; + QByteArray id; // "p434.t699" + QByteArray osid; // Non-standard: Process or thread id + QByteArray parentId; // Parent process id of a thread. +}; + +// Module load information occuring with 'RunControl contextSuspended' events +struct SYMBIANUTILS_EXPORT ModuleLoadEventInfo { + ModuleLoadEventInfo(); + void clear(); + bool parse(const JsonValue &v); + void format(QTextStream &str) const; + + QByteArray name; + QByteArray file; + bool loaded; + quint64 codeAddress; + quint64 dataAddress; + bool requireResume; +}; + +// Breakpoint as supported by TcfTrk source June 2010 +// TODO: Add watchpoints,etc once they are implemented +struct SYMBIANUTILS_EXPORT Breakpoint { + enum Type { Software, Hardware, Auto }; + + explicit Breakpoint(quint64 loc = 0); + void setContextId(unsigned processId, unsigned threadId = 0); + QString toString() const; + + static QByteArray idFromLocation(quint64 loc); // Automagically determine from location + + Type type; + bool enabled; + int ignoreCount; + QVector<QByteArray> contextIds; // Process or thread ids. + QByteArray id; // Id of the breakpoint; + quint64 location; + unsigned size; + bool thumb; +}; + +SYMBIANUTILS_EXPORT JsonInputStream &operator<<(JsonInputStream &str, const Breakpoint &b); + +// Event hierarchy +class SYMBIANUTILS_EXPORT TcfTrkEvent { + Q_DISABLE_COPY(TcfTrkEvent) +public: + enum Type { None, + LocatorHello, + RunControlContextAdded, + RunControlContextRemoved, + RunControlSuspended, + RunControlBreakpointSuspended, + RunControlModuleLoadSuspended, + RunControlResumed + }; + + virtual ~TcfTrkEvent(); + + Type type() const; + virtual QString toString() const; + + static TcfTrkEvent *parseEvent(Services s, const QByteArray &name, const QVector<JsonValue> &val); + +protected: + explicit TcfTrkEvent(Type type = None); + +private: + const Type m_type; +}; + +// ServiceHello +class SYMBIANUTILS_EXPORT TcfTrkLocatorHelloEvent : public TcfTrkEvent { +public: + explicit TcfTrkLocatorHelloEvent(const QStringList &); + + const QStringList &services() { return m_services; } + virtual QString toString() const; + +private: + QStringList m_services; +}; + +// Base for events that just have one id as parameter +// (simple suspend) +class SYMBIANUTILS_EXPORT TcfTrkIdEvent : public TcfTrkEvent { +protected: + explicit TcfTrkIdEvent(Type t, const QByteArray &id); +public: + QByteArray id() const { return m_id; } + QString idString() const { return QString::fromUtf8(m_id); } + +private: + const QByteArray m_id; +}; + +// Base for events that just have some ids as parameter +// (context removed) +class SYMBIANUTILS_EXPORT TcfTrkIdsEvent : public TcfTrkEvent { +protected: + explicit TcfTrkIdsEvent(Type t, const QVector<QByteArray> &ids); + +public: + QVector<QByteArray> ids() const { return m_ids; } + QString joinedIdString(const char sep = ',') const; + +private: + const QVector<QByteArray> m_ids; +}; + +// RunControlContextAdded +class SYMBIANUTILS_EXPORT TcfTrkRunControlContextAddedEvent : public TcfTrkEvent { +public: + typedef QVector<RunControlContext> RunControlContexts; + + explicit TcfTrkRunControlContextAddedEvent(const RunControlContexts &c); + + const RunControlContexts &contexts() const { return m_contexts; } + virtual QString toString() const; + + static TcfTrkRunControlContextAddedEvent *parseEvent(const QVector<JsonValue> &val); + +private: + const RunControlContexts m_contexts; +}; + +// RunControlContextRemoved +class SYMBIANUTILS_EXPORT TcfTrkRunControlContextRemovedEvent : public TcfTrkIdsEvent { +public: + explicit TcfTrkRunControlContextRemovedEvent(const QVector<QByteArray> &id); + virtual QString toString() const; +}; + +// Simple RunControlContextSuspended (process/thread) +class SYMBIANUTILS_EXPORT TcfTrkRunControlContextSuspendedEvent : public TcfTrkIdEvent { +public: + enum Reason { BreakPoint, ModuleLoad, Crash, Other } ; + + explicit TcfTrkRunControlContextSuspendedEvent(const QByteArray &id, + const QByteArray &reason, + quint64 pc = 0); + virtual QString toString() const; + + quint64 pc() const { return m_pc; } + QByteArray reasonID() const { return m_reason; } + Reason reason() const; + +protected: + explicit TcfTrkRunControlContextSuspendedEvent(Type t, + const QByteArray &id, + const QByteArray &reason, + quint64 pc = 0); + void format(QTextStream &str) const; + +private: + const quint64 m_pc; + const QByteArray m_reason; +}; + +// RunControlContextSuspended due to module load +class SYMBIANUTILS_EXPORT TcfTrkRunControlModuleLoadContextSuspendedEvent : public TcfTrkRunControlContextSuspendedEvent { +public: + explicit TcfTrkRunControlModuleLoadContextSuspendedEvent(const QByteArray &id, + const QByteArray &reason, + quint64 pc, + const ModuleLoadEventInfo &mi); + + virtual QString toString() const; + const ModuleLoadEventInfo &info() const { return m_mi; } + +private: + const ModuleLoadEventInfo m_mi; +}; + +} // namespace tcftrk +#endif // TRCFTRKMESSAGE_H diff --git a/tools/runonphone/symbianutils/trkdevice.cpp b/tools/runonphone/symbianutils/trkdevice.cpp index bd24300..9039184 100644 --- a/tools/runonphone/symbianutils/trkdevice.cpp +++ b/tools/runonphone/symbianutils/trkdevice.cpp @@ -636,10 +636,11 @@ private: void readMessages(); QByteArray m_trkReadBuffer; + bool linkEstablishmentMode; }; ReaderThreadBase::ReaderThreadBase(const QSharedPointer<DeviceContext> &context) : - m_context(context) + m_context(context), linkEstablishmentMode(true) { static const int trkResultMetaId = qRegisterMetaType<trk::TrkResult>(); Q_UNUSED(trkResultMetaId) @@ -662,7 +663,7 @@ void ReaderThreadBase::readMessages() { TrkResult r; QByteArray rawData; - while (extractResult(&m_trkReadBuffer, m_context->serialFrame, &r, &rawData)) { + while (extractResult(&m_trkReadBuffer, m_context->serialFrame, &r, linkEstablishmentMode, &rawData)) { emit messageReceived(r, rawData); } } diff --git a/tools/runonphone/symbianutils/trkutils.cpp b/tools/runonphone/symbianutils/trkutils.cpp index 60e391e..d89da20 100644 --- a/tools/runonphone/symbianutils/trkutils.cpp +++ b/tools/runonphone/symbianutils/trkutils.cpp @@ -52,6 +52,25 @@ namespace trk { +Library::Library() : codeseg(0), dataseg(0), pid(0) +{ +} + +Library::Library(const TrkResult &result) : codeseg(0), dataseg(0), pid(0) +{ + if (result.data.size() < 20) { + qWarning("Invalid trk creation notification received."); + return; + } + + const char *data = result.data.constData(); + pid = extractInt(data + 2); + codeseg = extractInt(data + 10); + dataseg = extractInt(data + 14); + const uint len = extractShort(data + 18); + name = result.data.mid(20, len); +} + TrkAppVersion::TrkAppVersion() { reset(); @@ -77,11 +96,11 @@ void Session::reset() extended1TypeSize = 0; extended2TypeSize = 0; pid = 0; + mainTid = 0; tid = 0; codeseg = 0; dataseg = 0; - currentThread = 0; libraries.clear(); trkAppVersion.reset(); } @@ -143,6 +162,90 @@ QString Session::deviceDescription(unsigned verbose) const return msg.arg(formatTrkVersion(trkAppVersion)); } +QByteArray Session::gdbLibraryList() const +{ + const int count = libraries.size(); + QByteArray response = "l<library-list>"; + for (int i = 0; i != count; ++i) { + const trk::Library &lib = libraries.at(i); + response += "<library name=\""; + response += lib.name; + response += "\">"; + response += "<section address=\"0x"; + response += trk::hexNumber(lib.codeseg); + response += "\"/>"; + response += "<section address=\"0x"; + response += trk::hexNumber(lib.dataseg); + response += "\"/>"; + response += "<section address=\"0x"; + response += trk::hexNumber(lib.dataseg); + response += "\"/>"; + response += "</library>"; + } + response += "</library-list>"; + return response; +} + +QByteArray Session::gdbQsDllInfo(int start, int count) const +{ + // Happens with gdb 6.4.50.20060226-cvs / CodeSourcery. + // Never made it into FSF gdb that got qXfer:libraries:read instead. + // http://sourceware.org/ml/gdb/2007-05/msg00038.html + // Name=hexname,TextSeg=textaddr[,DataSeg=dataaddr] + const int libraryCount = libraries.size(); + const int end = count < 0 ? libraryCount : qMin(libraryCount, start + count); + QByteArray response(1, end == libraryCount ? 'l' : 'm'); + for (int i = start; i < end; ++i) { + if (i != start) + response += ';'; + const Library &lib = libraries.at(i); + response += "Name="; + response += lib.name.toHex(); + response += ",TextSeg="; + response += hexNumber(lib.codeseg); + response += ",DataSeg="; + response += hexNumber(lib.dataseg); + } + return response; +} + +QString Session::toString() const +{ + QString rc; + QTextStream str(&rc); + str << "Session: " << deviceDescription(false) << '\n' + << "pid: " << pid << "main thread: " << mainTid + << " current thread: " << tid << ' '; + str.setIntegerBase(16); + str << " code: 0x" << codeseg << " data: 0x" << dataseg << '\n'; + if (const int libCount = libraries.size()) { + str << "Libraries:\n"; + for (int i = 0; i < libCount; i++) + str << " #" << i << ' ' << libraries.at(i).name + << " code: 0x" << libraries.at(i).codeseg + << " data: 0x" << libraries.at(i).dataseg << '\n'; + } + if (const int moduleCount = modules.size()) { + str << "Modules:\n"; + for (int i = 0; i < moduleCount; i++) + str << " #" << i << ' ' << modules.at(i) << '\n'; + } + str.setIntegerBase(10); + if (!addressToBP.isEmpty()) { + typedef QHash<uint, uint>::const_iterator BP_ConstIterator; + str << "Breakpoints:\n"; + const BP_ConstIterator cend = addressToBP.constEnd(); + for (BP_ConstIterator it = addressToBP.constBegin(); it != cend; ++it) { + str.setIntegerBase(16); + str << " 0x" << it.key(); + str.setIntegerBase(10); + str << ' ' << it.value() << '\n'; + } + } + + return rc; +} + // -------------- QByteArray decode7d(const QByteArray &ba) @@ -188,18 +291,15 @@ SYMBIANUTILS_EXPORT QString stringFromArray(const QByteArray &ba, int maxLen) QString ascii; const int size = maxLen == -1 ? ba.size() : qMin(ba.size(), maxLen); for (int i = 0; i < size; ++i) { - //if (i == 5 || i == ba.size() - 2) - // str += " "; - int c = byte(ba.at(i)); - str += QString("%1 ").arg(c, 2, 16, QChar('0')); - if (i >= 8 && i < ba.size() - 2) - ascii += QChar(c).isPrint() ? QChar(c) : QChar('.'); + const int c = byte(ba.at(i)); + str += QString::fromAscii("%1 ").arg(c, 2, 16, QChar('0')); + ascii += QChar(c).isPrint() ? QChar(c) : QChar('.'); } if (size != ba.size()) { - str += "..."; - ascii += "..."; + str += QLatin1String("..."); + ascii += QLatin1String("..."); } - return str + " " + ascii; + return str + QLatin1String(" ") + ascii; } SYMBIANUTILS_EXPORT QByteArray hexNumber(uint n, int digits) @@ -299,20 +399,30 @@ ushort isValidTrkResult(const QByteArray &buffer, bool serialFrame, ushort& mux) return firstDelimiterPos != -1 ? firstDelimiterPos : buffer.size(); } -bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *result, QByteArray *rawData) +bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *result, bool &linkEstablishmentMode, QByteArray *rawData) { result->clear(); if(rawData) rawData->clear(); - const ushort len = isValidTrkResult(*buffer, serialFrame, result->multiplex); - if (!len) - return false; + ushort len = isValidTrkResult(*buffer, serialFrame, result->multiplex); // handle receiving application output, which is not a regular command const int delimiterPos = serialFrame ? 4 : 0; + if (linkEstablishmentMode) { + //when "hot connecting" a device, we can receive partial frames. + //this code resyncs by discarding data until a TRK frame is found + while (buffer->length() > delimiterPos + && result->multiplex != MuxTextTrace + && !(result->multiplex == MuxTrk && buffer->at(delimiterPos) == 0x7e)) { + buffer->remove(0,1); + len = isValidTrkResult(*buffer, serialFrame, result->multiplex); + } + } + if (!len) + return false; if (buffer->at(delimiterPos) != 0x7e) { result->isDebugOutput = true; result->data = buffer->mid(delimiterPos, len); - *buffer->remove(0, delimiterPos + len); + buffer->remove(0, delimiterPos + len); return true; } // FIXME: what happens if the length contains 0xfe? @@ -320,7 +430,7 @@ bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *result, QByt const QByteArray data = decode7d(buffer->mid(delimiterPos + 1, len - 2)); if(rawData) *rawData = data; - *buffer->remove(0, delimiterPos + len); + buffer->remove(0, delimiterPos + len); byte sum = 0; for (int i = 0; i < data.size(); ++i) // 3 = 2 * 0xfe + sum @@ -335,6 +445,7 @@ bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *result, QByt //logMessage(" CURR DATA: " << stringFromArray(data)); //QByteArray prefix = "READ BUF: "; //logMessage((prefix + "HEADER: " + stringFromArray(header).toLatin1()).data()); + linkEstablishmentMode = false; //have received a good TRK packet, therefore in sync return true; } diff --git a/tools/runonphone/symbianutils/trkutils.h b/tools/runonphone/symbianutils/trkutils.h index e571028..d365f0d 100644 --- a/tools/runonphone/symbianutils/trkutils.h +++ b/tools/runonphone/symbianutils/trkutils.h @@ -56,6 +56,7 @@ QT_END_NAMESPACE namespace trk { typedef unsigned char byte; +struct TrkResult; enum Command { //meta commands @@ -135,6 +136,20 @@ enum Command { TrkDSPositionFile = 0xd4 }; +enum DSOSItemTypes { + kDSOSProcessItem = 0x0000, + kDSOSThreadItem = 0x0001, + kDSOSDLLItem = 0x0002, + kDSOSAppItem = 0x0003, + kDSOSMemBlockItem = 0x0004, + kDSOSProcAttachItem = 0x0005, + kDSOSThreadAttachItem = 0x0006, + kDSOSProcAttach2Item = 0x0007, + kDSOSProcRunItem = 0x0008, + /* 0x0009 - 0x00ff reserved for general expansion */ + /* 0x0100 - 0xffff available for target-specific use */ +}; + enum SerialMultiplexor { MuxRaw = 0, MuxTextTrace = 0x0102, @@ -164,11 +179,14 @@ SYMBIANUTILS_EXPORT void appendString(QByteArray *ba, const QByteArray &str, End struct SYMBIANUTILS_EXPORT Library { - Library() {} + Library(); + explicit Library(const TrkResult &r); QByteArray name; uint codeseg; uint dataseg; + //library addresses are valid for a given process (depending on memory model, they might be loaded at the same address in all processes or not) + uint pid; }; struct SYMBIANUTILS_EXPORT TrkAppVersion @@ -187,6 +205,11 @@ struct SYMBIANUTILS_EXPORT Session Session(); void reset(); QString deviceDescription(unsigned verbose) const; + QString toString() const; + // Answer to qXfer::libraries + QByteArray gdbLibraryList() const; + // Answer to qsDllInfo, can be sent chunk-wise. + QByteArray gdbQsDllInfo(int start = 0, int count = -1) const; // Trk feedback byte cpuMajor; @@ -198,6 +221,7 @@ struct SYMBIANUTILS_EXPORT Session byte extended2TypeSize; TrkAppVersion trkAppVersion; uint pid; + uint mainTid; uint tid; uint codeseg; uint dataseg; @@ -206,12 +230,7 @@ struct SYMBIANUTILS_EXPORT Session typedef QList<Library> Libraries; Libraries libraries; - typedef uint Thread; - typedef QList<Thread> Threads; - Threads threads; - // Gdb request - uint currentThread; QStringList modules; }; diff --git a/tools/runonphone/symbianutils/trkutils_p.h b/tools/runonphone/symbianutils/trkutils_p.h index 12b0109..05df83a 100644 --- a/tools/runonphone/symbianutils/trkutils_p.h +++ b/tools/runonphone/symbianutils/trkutils_p.h @@ -55,7 +55,7 @@ void appendDateTime(QByteArray *ba, QDateTime dateTime, Endianness = TargetByteO // returns a QByteArray containing optionally // the serial frame [0x01 0x90 <len>] and 0x7e encoded7d(ba) 0x7e QByteArray frameMessage(byte command, byte token, const QByteArray &data, bool serialFrame); -bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *r, QByteArray *rawData = 0); +bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *r, bool& linkEstablishmentMode, QByteArray *rawData = 0); } // namespace trk diff --git a/tools/runonphone/trksignalhandler.cpp b/tools/runonphone/trksignalhandler.cpp index 2abf91f..b6d446f 100644 --- a/tools/runonphone/trksignalhandler.cpp +++ b/tools/runonphone/trksignalhandler.cpp @@ -42,7 +42,19 @@ #include <QDebug> #include <QCoreApplication> #include <QObject> +#include <QFile> +#include <QDir> #include "trksignalhandler.h" +#include "trkutils.h" + +class CrashState +{ +public: + uint pid; + uint tid; + QString crashReason; + uint crashPC; +}; class TrkSignalHandlerPrivate { @@ -55,6 +67,12 @@ private: QTextStream err; int loglevel; int lastpercent; + QList<trk::Library> libraries; + QFile crashlogtextfile; + QFile crashstackfile; + QList<CrashState> queuedCrashes; + QString crashlogPath; + bool crashlog; }; void TrkSignalHandler::copyingStarted() @@ -108,6 +126,7 @@ void TrkSignalHandler::startingApplication() void TrkSignalHandler::applicationRunning(uint pid) { + Q_UNUSED(pid) if (d->loglevel > 0) d->out << "Running..." << endl; } @@ -155,13 +174,153 @@ void TrkSignalHandler::setLogLevel(int level) d->loglevel = level; } +void TrkSignalHandler::setCrashLogging(bool enabled) +{ + d->crashlog = enabled; +} + +void TrkSignalHandler::setCrashLogPath(QString path) +{ + d->crashlogPath = path; +} + +bool lessThanCodeBase(const trk::Library& cs1, const trk::Library& cs2) +{ + return cs1.codeseg < cs2.codeseg; +} + void TrkSignalHandler::stopped(uint pc, uint pid, uint tid, const QString& reason) { d->err << "STOPPED: pc=" << hex << pc << " pid=" << pid << " tid=" << tid << dec << " - " << reason << endl; - // if it was a breakpoint, then we could continue with "emit resume(pid, tid);" - // since we have set no breakpoints, it will be a just in time debug of a panic / exception - emit terminate(); + + if (d->crashlog) { + CrashState cs; + cs.pid = pid; + cs.tid = tid; + cs.crashPC = pc; + cs.crashReason = reason; + + d->queuedCrashes.append(cs); + + if (d->queuedCrashes.count() == 1) { + d->err << "Fetching registers and stack..." << endl; + emit getRegistersAndCallStack(pid, tid); + } + } + else + emit resume(pid, tid); +} + +void TrkSignalHandler::registersAndCallStackReadComplete(const QList<uint>& registers, const QByteArray& stack) +{ + CrashState cs = d->queuedCrashes.first(); + QDir dir(d->crashlogPath); + d->crashlogtextfile.setFileName(dir.filePath(QString("d_exc_%1.txt").arg(cs.tid))); + d->crashstackfile.setFileName(dir.filePath(QString("d_exc_%1.stk").arg(cs.tid))); + d->crashlogtextfile.open(QIODevice::WriteOnly); + QTextStream crashlog(&d->crashlogtextfile); + + crashlog << "-----------------------------------------------------------------------------" << endl; + crashlog << "EKA2 USER CRASH LOG" << endl; + crashlog << "Thread Name: " << QString("ProcessID-%1::ThreadID-%2").arg(cs.pid).arg(cs.tid) << endl; + crashlog << "Thread ID: " << cs.tid << endl; + //this is wrong, but TRK doesn't make stack limit available so we lie + crashlog << QString("User Stack %1-%2").arg(registers.at(13), 8, 16, QChar('0')).arg(registers.at(13) + stack.size(), 8, 16, QChar('0')) << endl; + //this is also wrong, but TRK doesn't give all information for exceptions + crashlog << QString("Panic: PC=%1 ").arg(cs.crashPC, 8, 16, QChar('0')) << cs.crashReason << endl; + crashlog << endl; + crashlog << "USER REGISTERS:" << endl; + crashlog << QString("CPSR=%1").arg(registers.at(16), 8, 16, QChar('0')) << endl; + for (int i=0;i<16;i+=4) { + crashlog << QString("r%1=%2 %3 %4 %5") + .arg(i, 2, 10, QChar('0')) + .arg(registers.at(i), 8, 16, QChar('0')) + .arg(registers.at(i+1), 8, 16, QChar('0')) + .arg(registers.at(i+2), 8, 16, QChar('0')) + .arg(registers.at(i+3), 8, 16, QChar('0')) << endl; + } + crashlog << endl; + + //emit info for post mortem debug + qSort(d->libraries.begin(), d->libraries.end(), lessThanCodeBase); + d->err << "Code Segments:" << endl; + crashlog << "CODE SEGMENTS:" << endl; + for(int i=0; i<d->libraries.count(); i++) { + const trk::Library& seg = d->libraries.at(i); + if(seg.pid != cs.pid) + continue; + if (d->loglevel > 1) { + d->err << QString("Code: %1 Data: %2 Name: ") + .arg(seg.codeseg, 8, 16, QChar('0')) + .arg(seg.dataseg, 8, 16, QChar('0')) + << seg.name << endl; + } + + //produce fake code segment end addresses since we don't get the real ones from TRK + uint end; + if (i+1 < d->libraries.count()) + end = d->libraries.at(i+1).codeseg - 1; + else + end = 0xFFFFFFFF; + + crashlog << QString("%1-%2 ") + .arg(seg.codeseg, 8, 16, QChar('0')) + .arg(end, 8, 16, QChar('0')) + << seg.name << endl; + } + + d->crashlogtextfile.close(); + + if (d->loglevel > 1) { + d->err << "Registers:" << endl; + for (int i=0;i<16;i++) { + d->err << QString("R%1: %2 ").arg(i, 2, 10, QChar('0')).arg(registers.at(i), 8, 16, QChar('0')); + if (i % 4 == 3) + d->err << endl; + } + d->err << QString("CPSR: %1").arg(registers.at(16), 8, 16, QChar('0')) << endl; + + d->err << "Stack:" << endl; + uint sp = registers.at(13); + for(int i=0; i<stack.size(); i+=16, sp+=16) { + d->err << QString("%1: ").arg(sp, 8, 16, QChar('0')); + d->err << trk::stringFromArray(stack.mid(i,16)); + d->err << endl; + } + } + d->crashstackfile.open(QIODevice::WriteOnly); + d->crashstackfile.write(stack); + d->crashstackfile.close(); + + if (d->loglevel > 0) + d->err << "Crash logs saved to " << d->crashlogtextfile.fileName() << " & " << d->crashstackfile.fileName() << endl; + + // resume the thread to allow Symbian OS to handle the panic normally. + // terminate when a non main thread is suspended reboots the phone (TRK bug) + emit resume(cs.pid, cs.tid); + + //fetch next crashed thread + d->queuedCrashes.removeFirst(); + if (d->queuedCrashes.count()) { + cs = d->queuedCrashes.first(); + d->err << "Fetching registers and stack..." << endl; + emit getRegistersAndCallStack(cs.pid, cs.tid); + } + +} + +void TrkSignalHandler::libraryLoaded(const trk::Library &lib) +{ + d->libraries << lib; +} + +void TrkSignalHandler::libraryUnloaded(const trk::Library &lib) +{ + for (QList<trk::Library>::iterator i = d->libraries.begin(); i != d->libraries.end(); i++) { + if((*i).name == lib.name && (*i).pid == lib.pid) + i = d->libraries.erase(i); + } } void TrkSignalHandler::timeout() diff --git a/tools/runonphone/trksignalhandler.h b/tools/runonphone/trksignalhandler.h index d31e46f..bfe2c3e 100644 --- a/tools/runonphone/trksignalhandler.h +++ b/tools/runonphone/trksignalhandler.h @@ -43,6 +43,7 @@ #define TRKSIGNALHANDLER_H #include <QObject> #include <QString> +#include "symbianutils/trkutils.h" class TrkSignalHandlerPrivate; class TrkSignalHandler : public QObject @@ -66,13 +67,20 @@ public slots: void stateChanged(int); void stopped(uint pc, uint pid, uint tid, const QString& reason); void timeout(); + void libraryLoaded(const trk::Library &lib); + void libraryUnloaded(const trk::Library &lib); + void registersAndCallStackReadComplete(const QList<uint>& registers, const QByteArray& stack); signals: void resume(uint pid, uint tid); + void stop(uint pid, uint tid); void terminate(); + void getRegistersAndCallStack(uint pid, uint tid); public: TrkSignalHandler(); ~TrkSignalHandler(); void setLogLevel(int); + void setCrashLogging(bool); + void setCrashLogPath(QString); private: TrkSignalHandlerPrivate *d; }; |