diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2011-01-11 10:48:38 (GMT) |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2011-01-11 14:22:53 (GMT) |
commit | a601a45f7fbff6df2b39990d0e1dbd00542b9819 (patch) | |
tree | 4ccef6d0bc78b9ed03209f99e873e5ba37209351 /src | |
parent | b58eb0419f9f724af5d9baf8bbce4e0f1e2f3f8b (diff) | |
download | Qt-a601a45f7fbff6df2b39990d0e1dbd00542b9819.zip Qt-a601a45f7fbff6df2b39990d0e1dbd00542b9819.tar.gz Qt-a601a45f7fbff6df2b39990d0e1dbd00542b9819.tar.bz2 |
Allow use of command line parameters with RApaLsSession::StartApp.
When a Symbian application is launched using RApaLsSession::StartApp,
command line parameters can be given with CApaCommandLine::SetTailEndL
and will now be correctly interpreted by Qt applications as command
line parameters.
There are a couple of limitations:
1) The parameters given with CApaCommandLine::SetTailEndL will not
be available in main method's argv array; they can be
accessed via QCoreApplication::arguments function.
2) CApaCommandLine::SetTailEndL does support any arbitrary binary data
as parameter, but only 8-bit string data gets parsed properly into
QCoreApplication::arguments. For other kind of tail data, you need
to subclass QS60MainAppUi and implement ProcessCommandParametersL
callback.
Task-number: QTBUG-15987
Reviewed-by: axis
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 64 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication_p.h | 10 | ||||
-rw-r--r-- | src/corelib/kernel/qcorecmdlineargs_p.h | 13 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 29 |
4 files changed, 93 insertions, 23 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index b445a50..381be34 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -71,6 +71,7 @@ # include <e32ldr.h> # include "qeventdispatcher_symbian_p.h" # include "private/qcore_symbian_p.h" +# include <apacmdln.h> #elif defined(Q_OS_UNIX) # if !defined(QT_NO_GLIB) # include "qeventdispatcher_glib_p.h" @@ -115,7 +116,58 @@ private: #ifdef Q_OS_SYMBIAN typedef TDriveNumber (*SystemDriveFunc)(RFs&); -static SystemDriveFunc PtrGetSystemDrive=0; +static SystemDriveFunc PtrGetSystemDrive = 0; +static CApaCommandLine* apaCommandLine = 0; +static char *apaTail = 0; +static QVector<char *> *apaArgv = 0; + +static void qt_cleanup_apa_cmd_line() +{ + delete apaCommandLine; + apaCommandLine = 0; + delete apaArgv; + apaArgv = 0; + delete apaTail; + apaTail = 0; +} + +static inline void qt_init_symbian_apa_arguments(int &argc, char **&argv) +{ + // If app is launched via CApaCommandLine::StartApp(), normal arguments only contain + // application name. + if (argc == 1) { + CApaCommandLine* commandLine = QCoreApplicationPrivate::symbianCommandLine(); + if(commandLine) { + TPtrC8 apaCmdLine = commandLine->TailEnd(); + int tailLen = apaCmdLine.Length(); + if (tailLen) { + apaTail = reinterpret_cast<char *>(qMalloc(tailLen + 1)); + qMemCopy(apaTail, reinterpret_cast<const char *>(apaCmdLine.Ptr()), tailLen); + apaTail[tailLen] = '\0'; + apaArgv = new QVector<char *>(8); + // Reuse windows command line parsing + *apaArgv = qWinCmdLine<char>(apaTail, tailLen, argc); + apaArgv->insert(0, argv[0]); + argc++; + argv = apaArgv->data(); + } + } + } +} + +CApaCommandLine* QCoreApplicationPrivate::symbianCommandLine() +{ + // Getting of Apa command line needs to be static as it can only be called successfully + // once per process. + if (!apaCommandLine) { + TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(apaCommandLine); + if (err == KErrNone) { + qAddPostRoutine(qt_cleanup_apa_cmd_line); + } + } + return apaCommandLine; +} + #endif #if defined(Q_WS_WIN) || defined(Q_WS_MAC) @@ -274,6 +326,10 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv) } QCoreApplicationPrivate::is_app_closing = false; +#ifdef Q_OS_SYMBIAN + qt_init_symbian_apa_arguments(argc, argv); +#endif + #ifdef Q_OS_UNIX qt_application_thread_id = QThread::currentThreadId(); #endif @@ -2056,6 +2112,12 @@ char **QCoreApplication::argv() As a result of this, the string given by arguments().at(0) might not be the program name on Windows, depending on how the application was started. + For Symbian applications started with \c RApaLsSession::StartApp one can specify + arguments using \c CApaCommandLine::SetTailEndL function. Such arguments are only + available via this method; they will not be passed to \c main function. Also note + that only 8-bit string data set with \c CApaCommandLine::SetTailEndL is supported + by this function. + \sa applicationFilePath() */ diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index d06fb51..703c825 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -65,8 +65,11 @@ QT_BEGIN_NAMESPACE typedef QList<QTranslator*> QTranslatorList; -#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE) +#if defined(Q_OS_SYMBIAN) +# if !defined(QT_NO_SYSTEMLOCALE) class QEnvironmentChangeNotifier; +# endif +class CApaCommandLine; #endif class QAbstractEventDispatcher; @@ -116,9 +119,12 @@ public: bool aboutToQuitEmitted; QString cachedApplicationDirPath; QString cachedApplicationFilePath; -#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE) +#if defined(Q_OS_SYMBIAN) +# if !defined(QT_NO_SYSTEMLOCALE) QScopedPointer<QEnvironmentChangeNotifier> environmentChangeNotifier; void symbianInit(); +# endif + static CApaCommandLine* symbianCommandLine(); #endif static bool isTranslatorInstalled(QTranslator *translator); diff --git a/src/corelib/kernel/qcorecmdlineargs_p.h b/src/corelib/kernel/qcorecmdlineargs_p.h index fd1d202..cdde782 100644 --- a/src/corelib/kernel/qcorecmdlineargs_p.h +++ b/src/corelib/kernel/qcorecmdlineargs_p.h @@ -58,11 +58,13 @@ QT_BEGIN_NAMESPACE -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN) QT_BEGIN_INCLUDE_NAMESPACE #include "QtCore/qvector.h" -#include "qt_windows.h" +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) +# include "qt_windows.h" +#endif QT_END_INCLUDE_NAMESPACE // template implementation of the parsing algorithm @@ -130,6 +132,7 @@ static QVector<Char*> qWinCmdLine(Char *cmdParam, int length, int &argc) return argv; } +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) static inline QStringList qWinCmdArgs(QString cmdLine) // not const-ref: this might be modified { QStringList args; @@ -150,8 +153,8 @@ static inline QStringList qCmdLineArgs(int argc, char *argv[]) QString cmdLine = QString::fromWCharArray(GetCommandLine()); return qWinCmdArgs(cmdLine); } - -#else // !Q_OS_WIN +#endif +#else // !Q_OS_WIN || !Q_OS_SYMBIAN static inline QStringList qCmdLineArgs(int argc, char *argv[]) { @@ -161,7 +164,7 @@ static inline QStringList qCmdLineArgs(int argc, char *argv[]) return args; } -#endif // Q_OS_WIN +#endif // Q_OS_WIN || Q_OS_SYMBIAN QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 4793437..789f198 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1431,21 +1431,20 @@ void qt_init(QApplicationPrivate * /* priv */, int) // The S60 framework has not been initialized. We need to do it. TApaApplicationFactory factory(S60->s60ApplicationFactory ? S60->s60ApplicationFactory : newS60Application); - CApaCommandLine* commandLine = 0; - TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(commandLine); - // After this construction, CEikonEnv will be available from CEikonEnv::Static(). - // (much like our qApp). - QtEikonEnv* coe = new QtEikonEnv; - //not using QT_TRAP_THROWING, because coe owns the cleanupstack so it can't be pushed there. - if(err == KErrNone) - TRAP(err, coe->ConstructAppFromCommandLineL(factory,*commandLine)); - delete commandLine; - if(err != KErrNone) { - qWarning() << "qt_init: Eikon application construct failed (" - << err - << "), maybe missing resource file on S60 3.1?"; - delete coe; - qt_symbian_throwIfError(err); + CApaCommandLine* commandLine = q_check_ptr(QCoreApplicationPrivate::symbianCommandLine()); + if (commandLine) { + // After this construction, CEikonEnv will be available from CEikonEnv::Static(). + // (much like our qApp). + QtEikonEnv* coe = new QtEikonEnv; + //not using QT_TRAP_THROWING, because coe owns the cleanupstack so it can't be pushed there. + TRAPD(err, coe->ConstructAppFromCommandLineL(factory, *commandLine)); + if(err != KErrNone) { + qWarning() << "qt_init: Eikon application construct failed (" + << err + << "), maybe missing resource file on S60 3.1?"; + delete coe; + qt_symbian_throwIfError(err); + } } S60->s60InstalledTrapHandler = User::SetTrapHandler(origTrapHandler); |