1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qcoreapplication.h"
43 #include "qcoreapplication_p.h"
44 
45 #include "qabstracteventdispatcher.h"
46 #include "qcoreevent.h"
47 #include "qeventloop.h"
48 #include "qcorecmdlineargs_p.h"
49 #include <qdatastream.h>
50 #include <qdebug.h>
51 #include <qdir.h>
52 #include <qfile.h>
53 #include <qfileinfo.h>
54 #include <qhash.h>
55 #include <private/qprocess_p.h>
56 #include <qtextcodec.h>
57 #include <qthread.h>
58 #include <qthreadpool.h>
59 #include <qthreadstorage.h>
60 #include <private/qthread_p.h>
61 #include <qelapsedtimer.h>
62 #include <qlibraryinfo.h>
63 #include <qvarlengtharray.h>
64 #include <private/qfactoryloader_p.h>
65 #include <private/qfunctions_p.h>
66 #include <private/qlocale_p.h>
67 #include <private/qmutexpool_p.h>
68 
69 #ifdef Q_OS_SYMBIAN
70 #  include <exception>
71 #  include <f32file.h>
72 #  include <e32ldr.h>
73 #  include "qeventdispatcher_symbian_p.h"
74 #  include "private/qcore_symbian_p.h"
75 #  include "private/qfilesystemengine_p.h"
76 #  include <apacmdln.h>
77 #elif defined(Q_OS_UNIX)
78 #  if defined(Q_OS_BLACKBERRY)
79 #    include "qeventdispatcher_blackberry_p.h"
80 #    include <process.h>
81 #    include <unistd.h>
82 #  else
83 #    if !defined(QT_NO_GLIB)
84 #      include "qeventdispatcher_glib_p.h"
85 #    endif
86 #    include "qeventdispatcher_unix_p.h"
87 #  endif
88 #endif
89 
90 #ifdef Q_OS_WIN
91 #  include "qeventdispatcher_win_p.h"
92 #endif
93 
94 #ifdef Q_OS_MAC
95 #  include "qcore_mac_p.h"
96 #endif
97 
98 #include <stdlib.h>
99 
100 #ifdef Q_OS_UNIX
101 #  include <locale.h>
102 #endif
103 
104 #ifdef Q_OS_VXWORKS
105 #  include <taskLib.h>
106 #endif
107 
108 #ifdef Q_OS_QNX
109 #  include <sys/neutrino.h>
110 #  include <pthread.h>
111 #  include <sched.h>
112 #endif
113 
114 QT_BEGIN_NAMESPACE
115 
116 class QMutexUnlocker
117 {
118 public:
QMutexUnlocker(QMutex * m)119     inline explicit QMutexUnlocker(QMutex *m)
120         : mtx(m)
121     { }
~QMutexUnlocker()122     inline ~QMutexUnlocker() { unlock(); }
unlock()123     inline void unlock() { if (mtx) mtx->unlock(); mtx = 0; }
124 
125 private:
126     Q_DISABLE_COPY(QMutexUnlocker)
127 
128     QMutex *mtx;
129 };
130 
131 #ifdef Q_OS_SYMBIAN
132 static CApaCommandLine* apaCommandLine = 0;
133 static char *apaTail = 0;
134 static QVector<char *> *apaArgv = 0;
135 
qt_cleanup_apa_cmd_line()136 static void qt_cleanup_apa_cmd_line()
137 {
138     delete apaCommandLine;
139     apaCommandLine = 0;
140     delete apaArgv;
141     apaArgv = 0;
142     delete apaTail;
143     apaTail = 0;
144 }
145 
qt_init_symbian_apa_arguments(int & argc,char ** & argv)146 static inline void qt_init_symbian_apa_arguments(int &argc, char **&argv)
147 {
148     // If app is launched via CApaCommandLine::StartApp(), normal arguments only contain
149     // application name.
150     if (argc == 1) {
151         CApaCommandLine* commandLine = QCoreApplicationPrivate::symbianCommandLine();
152         if(commandLine) {
153             TPtrC8 apaCmdLine = commandLine->TailEnd();
154             int tailLen = apaCmdLine.Length();
155             if (tailLen) {
156                 apaTail = reinterpret_cast<char *>(qMalloc(tailLen + 1));
157                 qMemCopy(apaTail, reinterpret_cast<const char *>(apaCmdLine.Ptr()), tailLen);
158                 apaTail[tailLen] = '\0';
159                 apaArgv = new QVector<char *>(8);
160                 // Reuse windows command line parsing
161                 *apaArgv = qWinCmdLine<char>(apaTail, tailLen, argc);
162                 apaArgv->insert(0, argv[0]);
163                 argc++;
164                 argv = apaArgv->data();
165             }
166         }
167     }
168 }
169 
symbianCommandLine()170 CApaCommandLine* QCoreApplicationPrivate::symbianCommandLine()
171 {
172     // Getting of Apa command line needs to be static as it can only be called successfully
173 	// once per process.
174     if (!apaCommandLine) {
175         TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(apaCommandLine);
176         if (err == KErrNone) {
177             qAddPostRoutine(qt_cleanup_apa_cmd_line);
178         }
179     }
180     return apaCommandLine;
181 }
182 
183 #endif
184 
185 #if defined(Q_WS_WIN) || defined(Q_WS_MAC)
186 extern QString qAppFileName();
187 #endif
188 
189 int QCoreApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0
190 #if defined(QT3_SUPPORT)
191 bool QCoreApplicationPrivate::useQt3Support = true;
192 #endif
193 
194 #if !defined(Q_OS_WIN)
195 #ifdef Q_OS_MAC
macMenuBarName()196 QString QCoreApplicationPrivate::macMenuBarName()
197 {
198     QString bundleName;
199     CFTypeRef string = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), CFSTR("CFBundleName"));
200     if (string)
201         bundleName = QCFString::toQString(static_cast<CFStringRef>(string));
202     return bundleName;
203 }
204 #endif
appName() const205 QString QCoreApplicationPrivate::appName() const
206 {
207     QMutexLocker locker(QMutexPool::globalInstanceGet(&applicationName));
208 
209     if (applicationName.isNull()) {
210 #ifdef Q_OS_MAC
211         applicationName = macMenuBarName();
212 #endif
213         if (applicationName.isEmpty() && argv[0]) {
214             char *p = strrchr(argv[0], '/');
215             applicationName = QString::fromLocal8Bit(p ? p + 1 : argv[0]);
216         }
217     }
218     return applicationName;
219 }
220 #endif
221 
checkInstance(const char * function)222 bool QCoreApplicationPrivate::checkInstance(const char *function)
223 {
224     bool b = (QCoreApplication::self != 0);
225     if (!b)
226         qWarning("QApplication::%s: Please instantiate the QApplication object first", function);
227     return b;
228 }
229 
230 Q_GLOBAL_STATIC(QString, qmljs_debug_arguments);
231 
processCommandLineArguments()232 void QCoreApplicationPrivate::processCommandLineArguments()
233 {
234     int j = argc ? 1 : 0;
235     for (int i = 1; i < argc; ++i) {
236         if (argv[i] && *argv[i] != '-') {
237             argv[j++] = argv[i];
238             continue;
239         }
240         QByteArray arg = argv[i];
241         if (arg.startsWith("-qmljsdebugger=")) {
242             *qmljs_debug_arguments() = QString::fromLocal8Bit(arg.right(arg.length() - 15));
243         } else if (arg == "-qmljsdebugger" && i < argc - 1) {
244             ++i;
245             *qmljs_debug_arguments() = QString::fromLocal8Bit(argv[i]);
246         } else {
247             argv[j++] = argv[i];
248         }
249     }
250 
251     if (j < argc) {
252         argv[j] = 0;
253         argc = j;
254     }
255 }
256 
257 // Support for introspection
258 
259 QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set = { 0, 0, 0, 0 };
260 
qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet & callback_set)261 void qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set)
262 {
263     qt_signal_spy_callback_set = callback_set;
264 }
265 
qt_startup_hook()266 extern "C" void Q_CORE_EXPORT qt_startup_hook()
267 {
268 }
269 
270 typedef QList<QtCleanUpFunction> QVFuncList;
Q_GLOBAL_STATIC(QVFuncList,postRList)271 Q_GLOBAL_STATIC(QVFuncList, postRList)
272 
273 void qAddPostRoutine(QtCleanUpFunction p)
274 {
275     QVFuncList *list = postRList();
276     if (!list)
277         return;
278     list->prepend(p);
279 }
280 
qRemovePostRoutine(QtCleanUpFunction p)281 void qRemovePostRoutine(QtCleanUpFunction p)
282 {
283     QVFuncList *list = postRList();
284     if (!list)
285         return;
286     list->removeAll(p);
287 }
288 
qt_call_post_routines()289 void Q_CORE_EXPORT qt_call_post_routines()
290 {
291     QVFuncList *list = 0;
292     QT_TRY {
293         list = postRList();
294     } QT_CATCH(const std::bad_alloc &) {
295         // ignore - if we can't allocate a post routine list,
296         // there's a high probability that there's no post
297         // routine to be executed :)
298     }
299     if (!list)
300         return;
301     while (!list->isEmpty())
302         (list->takeFirst())();
303 }
304 
305 
306 // app starting up if false
307 bool QCoreApplicationPrivate::is_app_running = false;
308  // app closing down if true
309 bool QCoreApplicationPrivate::is_app_closing = false;
310 // initialized in qcoreapplication and in qtextstream autotest when setlocale is called.
311 Q_CORE_EXPORT bool qt_locale_initialized = false;
312 
313 #ifdef Q_OS_SYMBIAN
314 // The global QSettings needs to be cleaned where cleanup stack is available, which is not
315 // normally the case when global static destructors are run.
316 // Declare a custom QGlobalStaticDeleter for QSettings to handle that case.
317 template<>
318 class QGlobalStaticDeleter<QSettings>
319 {
320 public:
321     QGlobalStatic<QSettings> &globalStatic;
QGlobalStaticDeleter(QGlobalStatic<QSettings> & _globalStatic)322     QGlobalStaticDeleter(QGlobalStatic<QSettings> &_globalStatic)
323         : globalStatic(_globalStatic)
324     { }
325 
~QGlobalStaticDeleter()326     inline ~QGlobalStaticDeleter()
327     {
328         CTrapCleanup *cleanup = CTrapCleanup::New();
329         delete globalStatic.pointer;
330         delete cleanup;
331         globalStatic.pointer = 0;
332         globalStatic.destroyed = true;
333     }
334 };
335 #endif
336 
337 /*
338   Create an instance of Trolltech.conf. This ensures that the settings will not
339   be thrown out of QSetting's cache for unused settings.
340   */
341 #ifndef QT_NO_SETTINGS
342 Q_GLOBAL_STATIC_WITH_ARGS(QSettings, staticTrolltechConf, (QSettings::UserScope, QLatin1String("Trolltech")))
343 
trolltechConf()344 QSettings *QCoreApplicationPrivate::trolltechConf()
345 {
346     return staticTrolltechConf();
347 }
348 #endif
349 
qGlobalPostedEventsCount()350 Q_CORE_EXPORT uint qGlobalPostedEventsCount()
351 {
352     QThreadData *currentThreadData = QThreadData::current();
353     return currentThreadData->postEventList.size() - currentThreadData->postEventList.startOffset;
354 }
355 
356 
qt_set_current_thread_to_main_thread()357 void qt_set_current_thread_to_main_thread()
358 {
359     QCoreApplicationPrivate::theMainThread = QThread::currentThread();
360 }
361 
362 
363 
364 QCoreApplication *QCoreApplication::self = 0;
365 QAbstractEventDispatcher *QCoreApplicationPrivate::eventDispatcher = 0;
366 uint QCoreApplicationPrivate::attribs;
367 
368 #ifdef Q_OS_UNIX
369 Qt::HANDLE qt_application_thread_id = 0;
370 #endif
371 
372 struct QCoreApplicationData {
QCoreApplicationDataQCoreApplicationData373     QCoreApplicationData() {
374 #ifndef QT_NO_LIBRARY
375         app_libpaths = 0;
376 #endif
377     }
~QCoreApplicationDataQCoreApplicationData378     ~QCoreApplicationData() {
379 #ifndef QT_NO_LIBRARY
380         delete app_libpaths;
381 #endif
382 #ifndef QT_NO_QOBJECT
383         // cleanup the QAdoptedThread created for the main() thread
384         if (QCoreApplicationPrivate::theMainThread) {
385             QThreadData *data = QThreadData::get2(QCoreApplicationPrivate::theMainThread);
386             data->deref(); // deletes the data and the adopted thread
387         }
388 #endif
389     }
390 
391 #ifdef Q_OS_BLACKBERRY
392     //The QCoreApplicationData struct is only populated on demand, because it is rarely needed and would
393     //affect startup time
loadManifestQCoreApplicationData394     void loadManifest() {
395         static bool manifestLoadAttempt = false;
396         if (manifestLoadAttempt)
397             return;
398 
399         manifestLoadAttempt = true;
400 
401         QFile metafile(QLatin1String("app/META-INF/MANIFEST.MF"));
402         if (!metafile.open(QIODevice::ReadOnly)) {
403             qWarning() << Q_FUNC_INFO << "Could not open application metafile for reading";
404         } else {
405             while (!metafile.atEnd() && (application.isEmpty() || applicationVersion.isEmpty() || orgName.isEmpty())) {
406                 QByteArray line = metafile.readLine();
407                 if (line.startsWith("Application-Name:"))
408                     application = QString::fromUtf8(line.mid(18).trimmed());
409                 else if (line.startsWith("Application-Version:"))
410                     applicationVersion = QString::fromUtf8(line.mid(21).trimmed());
411                 else if (line.startsWith("Package-Author:"))
412                     orgName = QString::fromUtf8(line.mid(16).trimmed());
413             }
414             metafile.close();
415         }
416     }
417 #endif
418 
419     QString orgName, orgDomain, application;
420     QString applicationVersion;
421 
422 #ifndef QT_NO_LIBRARY
423     QStringList *app_libpaths;
424 #endif
425 
426 };
427 
Q_GLOBAL_STATIC(QCoreApplicationData,coreappdata)428 Q_GLOBAL_STATIC(QCoreApplicationData, coreappdata)
429 
430 QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint flags)
431     : QObjectPrivate(), argc(aargc), argv(aargv), application_type(0), eventFilter(0),
432       in_exec(false), aboutToQuitEmitted(false)
433 {
434     app_compile_version = flags & 0xffffff;
435 #if defined(QT3_SUPPORT)
436     useQt3Support = !(flags & 0x01000000);
437 #endif
438     static const char *const empty = "";
439     if (argc == 0 || argv == 0) {
440         argc = 0;
441         argv = (char **)&empty; // ouch! careful with QCoreApplication::argv()!
442     }
443     QCoreApplicationPrivate::is_app_closing = false;
444 
445 #ifdef Q_OS_SYMBIAN
446     qt_init_symbian_apa_arguments(argc, argv);
447 #endif
448 
449 #ifdef Q_OS_UNIX
450     qt_application_thread_id = QThread::currentThreadId();
451 #endif
452 
453 #ifdef Q_OS_QNX
454     // make the kernel attempt to emulate an instruction with a misaligned access
455     // if the attempt fails, it faults with a SIGBUS
456     int tv = -1;
457     ThreadCtl(_NTO_TCTL_ALIGN_FAULT, &tv);
458 
459     // without Round Robin drawn intensive apps will hog the cpu
460     // and make the system appear frozen
461     int sched_policy;
462     sched_param param;
463     if (pthread_getschedparam(0, &sched_policy, &param) == 0 && sched_policy != SCHED_RR) {
464         sched_policy = SCHED_RR;
465         pthread_setschedparam(0, sched_policy, &param);
466     }
467 #endif
468 
469     // note: this call to QThread::currentThread() may end up setting theMainThread!
470     if (QThread::currentThread() != theMainThread)
471         qWarning("WARNING: QApplication was not created in the main() thread.");
472 }
473 
~QCoreApplicationPrivate()474 QCoreApplicationPrivate::~QCoreApplicationPrivate()
475 {
476     if (threadData) {
477 #ifndef QT_NO_THREAD
478         void *data = &threadData->tls;
479         QThreadStorageData::finish((void **)data);
480 #endif
481 
482         // need to clear the state of the mainData, just in case a new QCoreApplication comes along.
483         QMutexLocker locker(&threadData->postEventList.mutex);
484         for (int i = 0; i < threadData->postEventList.size(); ++i) {
485             const QPostEvent &pe = threadData->postEventList.at(i);
486             if (pe.event) {
487                 --pe.receiver->d_func()->postedEvents;
488                 pe.event->posted = false;
489                 delete pe.event;
490             }
491         }
492         threadData->postEventList.clear();
493         threadData->postEventList.recursion = 0;
494         threadData->quitNow = false;
495     }
496 }
497 
createEventDispatcher()498 void QCoreApplicationPrivate::createEventDispatcher()
499 {
500     Q_Q(QCoreApplication);
501 #if defined(Q_OS_SYMBIAN)
502     eventDispatcher = new QEventDispatcherSymbian(q);
503 #elif defined(Q_OS_UNIX)
504 #  if defined(Q_OS_BLACKBERRY)
505     eventDispatcher = new QEventDispatcherBlackberry(q);
506 #  else
507 #  if !defined(QT_NO_GLIB)
508     if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported())
509         eventDispatcher = new QEventDispatcherGlib(q);
510     else
511 #  endif
512         eventDispatcher = new QEventDispatcherUNIX(q);
513 #  endif
514 #elif defined(Q_OS_WIN)
515     eventDispatcher = new QEventDispatcherWin32(q);
516 #else
517 #  error "QEventDispatcher not yet ported to this platform"
518 #endif
519 }
520 
521 QThread *QCoreApplicationPrivate::theMainThread = 0;
mainThread()522 QThread *QCoreApplicationPrivate::mainThread()
523 {
524     Q_ASSERT(theMainThread != 0);
525     return theMainThread;
526 }
527 
528 #if !defined (QT_NO_DEBUG) || defined (QT_MAC_FRAMEWORK_BUILD)
checkReceiverThread(QObject * receiver)529 void QCoreApplicationPrivate::checkReceiverThread(QObject *receiver)
530 {
531     QThread *currentThread = QThread::currentThread();
532     QThread *thr = receiver->thread();
533     Q_ASSERT_X(currentThread == thr || !thr,
534                "QCoreApplication::sendEvent",
535                QString::fromLatin1("Cannot send events to objects owned by a different thread. "
536                                    "Current thread %1. Receiver '%2' (of type '%3') was created in thread %4")
537                .arg(QString::number((quintptr) currentThread, 16))
538                .arg(receiver->objectName())
539                .arg(QLatin1String(receiver->metaObject()->className()))
540                .arg(QString::number((quintptr) thr, 16))
541                .toLocal8Bit().data());
542     Q_UNUSED(currentThread);
543     Q_UNUSED(thr);
544 }
545 #elif defined(Q_OS_SYMBIAN) && defined (QT_NO_DEBUG)
546 // no implementation in release builds, but keep the symbol present
checkReceiverThread(QObject *)547 void QCoreApplicationPrivate::checkReceiverThread(QObject * /* receiver */)
548 {
549 }
550 #endif
551 
appendApplicationPathToLibraryPaths()552 void QCoreApplicationPrivate::appendApplicationPathToLibraryPaths()
553 {
554 #if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
555     QStringList *app_libpaths = coreappdata()->app_libpaths;
556     Q_ASSERT(app_libpaths);
557 # if defined(Q_OS_SYMBIAN)
558     QString app_location( QCoreApplication::applicationDirPath() );
559     // File existence check for application's private dir requires additional '\' or
560     // platform security will not allow it.
561     if (app_location !=  QLibraryInfo::location(QLibraryInfo::PluginsPath) && QFile::exists(app_location + QLatin1Char('\\')) && !app_libpaths->contains(app_location))
562 # else
563     QString app_location( QCoreApplication::applicationFilePath() );
564     app_location.truncate(app_location.lastIndexOf(QLatin1Char('/')));
565     app_location = QDir(app_location).canonicalPath();
566     if (QFile::exists(app_location) && !app_libpaths->contains(app_location))
567 # endif
568         app_libpaths->append(app_location);
569 #endif
570 }
571 
qmljsDebugArguments()572 QString QCoreApplicationPrivate::qmljsDebugArguments()
573 {
574     return *qmljs_debug_arguments();
575 }
576 
qAppName()577 QString qAppName()
578 {
579     if (!QCoreApplicationPrivate::checkInstance("qAppName"))
580         return QString();
581     return QCoreApplication::instance()->d_func()->appName();
582 }
583 
584 /*!
585     \class QCoreApplication
586     \brief The QCoreApplication class provides an event loop for console Qt
587     applications.
588 
589     This class is used by non-GUI applications to provide their event
590     loop. For non-GUI application that uses Qt, there should be exactly
591     one QCoreApplication object. For GUI applications, see
592     QApplication.
593 
594     QCoreApplication contains the main event loop, where all events
595     from the operating system (e.g., timer and network events) and
596     other sources are processed and dispatched. It also handles the
597     application's initialization and finalization, as well as
598     system-wide and application-wide settings.
599 
600     \section1 The Event Loop and Event Handling
601 
602     The event loop is started with a call to exec(). Long running
603     operations can call processEvents() to keep the application
604     responsive.
605 
606     In general, we recommend that you create a QCoreApplication or a
607     QApplication object in your \c main() function as early as
608     possible. exec() will not return until the event loop exits; e.g.,
609     when quit() is called.
610 
611     Several static convenience functions are also provided. The
612     QCoreApplication object is available from instance(). Events can
613     be sent or posted using sendEvent(), postEvent(), and
614     sendPostedEvents(). Pending events can be removed with
615     removePostedEvents() or flushed with flush().
616 
617     The class provides a quit() slot and an aboutToQuit() signal.
618 
619     \section1 Application and Library Paths
620 
621     An application has an applicationDirPath() and an
622     applicationFilePath(). Library paths (see QLibrary) can be retrieved
623     with libraryPaths() and manipulated by setLibraryPaths(), addLibraryPath(),
624     and removeLibraryPath().
625 
626     \section1 Internationalization and Translations
627 
628     Translation files can be added or removed
629     using installTranslator() and removeTranslator(). Application
630     strings can be translated using translate(). The QObject::tr()
631     and QObject::trUtf8() functions are implemented in terms of
632     translate().
633 
634     \section1 Accessing Command Line Arguments
635 
636     The command line arguments which are passed to QCoreApplication's
637     constructor should be accessed using the arguments() function.
638     Note that some arguments supplied by the user may have been
639     processed and removed by QCoreApplication.
640 
641     In cases where command line arguments need to be obtained using the
642     argv() function, you must convert them from the local string encoding
643     using QString::fromLocal8Bit().
644 
645     \section1 Locale Settings
646 
647     On Unix/Linux Qt is configured to use the system locale settings by
648     default. This can cause a conflict when using POSIX functions, for
649     instance, when converting between data types such as floats and
650     strings, since the notation may differ between locales. To get
651     around this problem, call the POSIX function \c{setlocale(LC_NUMERIC,"C")}
652     right after initializing QApplication or QCoreApplication to reset
653     the locale that is used for number formatting to "C"-locale.
654 
655     \sa QApplication, QAbstractEventDispatcher, QEventLoop,
656     {Semaphores Example}, {Wait Conditions Example}
657 */
658 
659 /*!
660     \fn static QCoreApplication *QCoreApplication::instance()
661 
662     Returns a pointer to the application's QCoreApplication (or
663     QApplication) instance.
664 
665     If no instance has been allocated, \c null is returned.
666 */
667 
668 /*!\internal
669  */
QCoreApplication(QCoreApplicationPrivate & p)670 QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)
671     : QObject(p, 0)
672 {
673     init();
674     // note: it is the subclasses' job to call
675     // QCoreApplicationPrivate::eventDispatcher->startingUp();
676 }
677 
678 /*!
679     Flushes the platform specific event queues.
680 
681     If you are doing graphical changes inside a loop that does not
682     return to the event loop on asynchronous window systems like X11
683     or double buffered window systems like Mac OS X, and you want to
684     visualize these changes immediately (e.g. Splash Screens), call
685     this function.
686 
687     \sa sendPostedEvents()
688 */
flush()689 void QCoreApplication::flush()
690 {
691     if (self && self->d_func()->eventDispatcher)
692         self->d_func()->eventDispatcher->flush();
693 }
694 
695 /*!
696     Constructs a Qt kernel application. Kernel applications are
697     applications without a graphical user interface. These type of
698     applications are used at the console or as server processes.
699 
700     The \a argc and \a argv arguments are processed by the application,
701     and made available in a more convenient form by the arguments()
702     function.
703 
704     \warning The data referred to by \a argc and \a argv must stay valid
705     for the entire lifetime of the QCoreApplication object. In addition,
706     \a argc must be greater than zero and \a argv must contain at least
707     one valid character string.
708 */
QCoreApplication(int & argc,char ** argv)709 QCoreApplication::QCoreApplication(int &argc, char **argv)
710     : QObject(*new QCoreApplicationPrivate(argc, argv, 0x040000))
711 {
712     init();
713     QCoreApplicationPrivate::eventDispatcher->startingUp();
714 #if defined(Q_OS_SYMBIAN) && !defined(QT_NO_LIBRARY)
715     // Refresh factoryloader, as text codecs are requested during lib path
716     // resolving process and won't be therefore properly loaded.
717     // Unknown if this is symbian specific issue.
718     QFactoryLoader::refreshAll();
719 #endif
720 
721 #if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE)
722     d_func()->symbianInit();
723 #endif
724 }
725 
QCoreApplication(int & argc,char ** argv,int _internal)726 QCoreApplication::QCoreApplication(int &argc, char **argv, int _internal)
727 : QObject(*new QCoreApplicationPrivate(argc, argv, _internal))
728 {
729     init();
730     QCoreApplicationPrivate::eventDispatcher->startingUp();
731 #if defined(Q_OS_SYMBIAN)
732 #ifndef QT_NO_LIBRARY
733     // Refresh factoryloader, as text codecs are requested during lib path
734     // resolving process and won't be therefore properly loaded.
735     // Unknown if this is symbian specific issue.
736     QFactoryLoader::refreshAll();
737 #endif
738 #ifndef QT_NO_SYSTEMLOCALE
739     d_func()->symbianInit();
740 #endif
741 #endif //Q_OS_SYMBIAN
742 }
743 
744 
745 // ### move to QCoreApplicationPrivate constructor?
init()746 void QCoreApplication::init()
747 {
748     Q_D(QCoreApplication);
749 
750 #ifdef Q_OS_UNIX
751     setlocale(LC_ALL, "");                // use correct char set mapping
752     qt_locale_initialized = true;
753 #endif
754 
755     Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
756     QCoreApplication::self = this;
757 
758 #ifdef Q_OS_SYMBIAN
759     //ensure temp and working directories exist
760     QFileSystemEngine::createDirectory(QFileSystemEntry(QFileSystemEngine::tempPath()), true);
761     QFileSystemEngine::createDirectory(QFileSystemEntry(QFileSystemEngine::currentPath()), true);
762 #endif
763 
764 #ifndef QT_NO_THREAD
765     QThread::initialize();
766 #endif
767 
768     // use the event dispatcher created by the app programmer (if any)
769     if (!QCoreApplicationPrivate::eventDispatcher)
770         QCoreApplicationPrivate::eventDispatcher = d->threadData->eventDispatcher;
771     // otherwise we create one
772     if (!QCoreApplicationPrivate::eventDispatcher)
773         d->createEventDispatcher();
774     Q_ASSERT(QCoreApplicationPrivate::eventDispatcher != 0);
775 
776     if (!QCoreApplicationPrivate::eventDispatcher->parent())
777         QCoreApplicationPrivate::eventDispatcher->moveToThread(d->threadData->thread);
778 
779     d->threadData->eventDispatcher = QCoreApplicationPrivate::eventDispatcher;
780 
781 #if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
782     if (!coreappdata()->app_libpaths) {
783         // make sure that library paths is initialized
784         libraryPaths();
785     } else {
786         d->appendApplicationPathToLibraryPaths();
787     }
788 #endif
789 
790 #if defined(Q_OS_UNIX) && !(defined(QT_NO_PROCESS))
791     // Make sure the process manager thread object is created in the main
792     // thread.
793     QProcessPrivate::initializeProcessManager();
794 #endif
795 
796 #ifdef QT_EVAL
797     extern void qt_core_eval_init(uint);
798     qt_core_eval_init(d->application_type);
799 #endif
800 
801 #if    defined(Q_OS_SYMBIAN)  \
802     && defined(Q_CC_NOKIAX86) \
803     && defined(QT_DEBUG)
804     /**
805      * Prevent the executable from being locked in the Symbian emulator. The
806      * code dramatically simplifies debugging on Symbian, but beyond that has
807      * no impact.
808      *
809      * Force the ZLazyUnloadTimer to fire and therefore unload code segments
810      * immediately. The code affects Symbian's file server and on the other
811      * hand needs only to be run once in each emulator run.
812      */
813     {
814         RLoader loader;
815         CleanupClosePushL(loader);
816         User::LeaveIfError(loader.Connect());
817         User::LeaveIfError(loader.CancelLazyDllUnload());
818         CleanupStack::PopAndDestroy(&loader);
819     }
820 #endif
821 
822     d->processCommandLineArguments();
823 
824     qt_startup_hook();
825 }
826 
827 #if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE)
symbianInit()828 void QCoreApplicationPrivate::symbianInit()
829 {
830     if (!environmentChangeNotifier)
831         environmentChangeNotifier.reset(new QEnvironmentChangeNotifier);
832 }
833 #endif
834 
835 
836 /*!
837     Destroys the QCoreApplication object.
838 */
~QCoreApplication()839 QCoreApplication::~QCoreApplication()
840 {
841     qt_call_post_routines();
842 
843     self = 0;
844     QCoreApplicationPrivate::is_app_closing = true;
845     QCoreApplicationPrivate::is_app_running = false;
846 
847 #if !defined(QT_NO_THREAD)
848 #if !defined(QT_NO_CONCURRENT)
849     // Synchronize and stop the global thread pool threads.
850     QThreadPool *globalThreadPool = 0;
851     QT_TRY {
852         globalThreadPool = QThreadPool::globalInstance();
853     } QT_CATCH (...) {
854         // swallow the exception, since destructors shouldn't throw
855     }
856     if (globalThreadPool)
857         globalThreadPool->waitForDone();
858 #endif
859     QThread::cleanup();
860 #endif
861 
862     d_func()->threadData->eventDispatcher = 0;
863     if (QCoreApplicationPrivate::eventDispatcher)
864         QCoreApplicationPrivate::eventDispatcher->closingDown();
865     QCoreApplicationPrivate::eventDispatcher = 0;
866 
867 #ifndef QT_NO_LIBRARY
868     delete coreappdata()->app_libpaths;
869     coreappdata()->app_libpaths = 0;
870 #endif
871 }
872 
873 
874 /*!
875     Sets the attribute \a attribute if \a on is true;
876     otherwise clears the attribute.
877 
878     One of the attributes that can be set with this method is
879     Qt::AA_ImmediateWidgetCreation. It tells Qt to create toplevel
880     windows immediately. Normally, resources for widgets are allocated
881     on demand to improve efficiency and minimize resource usage.
882     Therefore, if it is important to minimize resource consumption, do
883     not set this attribute.
884 
885     \sa testAttribute()
886 */
setAttribute(Qt::ApplicationAttribute attribute,bool on)887 void QCoreApplication::setAttribute(Qt::ApplicationAttribute attribute, bool on)
888 {
889     if (on)
890         QCoreApplicationPrivate::attribs |= 1 << attribute;
891     else
892         QCoreApplicationPrivate::attribs &= ~(1 << attribute);
893 #ifdef Q_OS_MAC
894     // Turn on the no native menubar here, since we used to
895     // do this implicitly. We DO NOT flip it off if someone sets
896     // it to false.
897     // Ideally, we'd have magic that would be something along the lines of
898     // "follow MacPluginApplication" unless explicitly set.
899     // Considering this attribute isn't only at the beginning
900     // it's unlikely it will ever be a problem, but I want
901     // to have the behavior documented here.
902     if (attribute == Qt::AA_MacPluginApplication && on
903           && !testAttribute(Qt::AA_DontUseNativeMenuBar)) {
904         setAttribute(Qt::AA_DontUseNativeMenuBar, true);
905     }
906 #endif
907 }
908 
909 /*!
910   Returns true if attribute \a attribute is set;
911   otherwise returns false.
912 
913   \sa setAttribute()
914  */
testAttribute(Qt::ApplicationAttribute attribute)915 bool QCoreApplication::testAttribute(Qt::ApplicationAttribute attribute)
916 {
917     return QCoreApplicationPrivate::testAttribute(attribute);
918 }
919 
920 
921 /*!
922   \internal
923 
924   This function is here to make it possible for Qt extensions to
925   hook into event notification without subclassing QApplication
926 */
notifyInternal(QObject * receiver,QEvent * event)927 bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
928 {
929     // Make it possible for Qt Jambi and QSA to hook into events even
930     // though QApplication is subclassed...
931     bool result = false;
932     void *cbdata[] = { receiver, event, &result };
933     if (QInternal::activateCallbacks(QInternal::EventNotifyCallback, cbdata)) {
934         return result;
935     }
936 
937     // Qt enforces the rule that events can only be sent to objects in
938     // the current thread, so receiver->d_func()->threadData is
939     // equivalent to QThreadData::current(), just without the function
940     // call overhead.
941     QObjectPrivate *d = receiver->d_func();
942     QThreadData *threadData = d->threadData;
943     ++threadData->loopLevel;
944 
945 #ifdef QT_JAMBI_BUILD
946     int deleteWatch = 0;
947     int *oldDeleteWatch = QObjectPrivate::setDeleteWatch(d, &deleteWatch);
948 
949     bool inEvent = d->inEventHandler;
950     d->inEventHandler = true;
951 #endif
952 
953     bool returnValue;
954     QT_TRY {
955         returnValue = notify(receiver, event);
956     } QT_CATCH (...) {
957         --threadData->loopLevel;
958         QT_RETHROW;
959     }
960 
961 #ifdef QT_JAMBI_BUILD
962     // Restore the previous state if the object was not deleted..
963     if (!deleteWatch) {
964         d->inEventHandler = inEvent;
965     }
966     QObjectPrivate::resetDeleteWatch(d, oldDeleteWatch, deleteWatch);
967 #endif
968     --threadData->loopLevel;
969     return returnValue;
970 }
971 
972 
973 /*!
974   Sends \a event to \a receiver: \a {receiver}->event(\a event).
975   Returns the value that is returned from the receiver's event
976   handler. Note that this function is called for all events sent to
977   any object in any thread.
978 
979   For certain types of events (e.g. mouse and key events),
980   the event will be propagated to the receiver's parent and so on up to
981   the top-level object if the receiver is not interested in the event
982   (i.e., it returns false).
983 
984   There are five different ways that events can be processed;
985   reimplementing this virtual function is just one of them. All five
986   approaches are listed below:
987   \list 1
988   \i Reimplementing paintEvent(), mousePressEvent() and so
989   on. This is the commonest, easiest and least powerful way.
990 
991   \i Reimplementing this function. This is very powerful, providing
992   complete control; but only one subclass can be active at a time.
993 
994   \i Installing an event filter on QCoreApplication::instance(). Such
995   an event filter is able to process all events for all widgets, so
996   it's just as powerful as reimplementing notify(); furthermore, it's
997   possible to have more than one application-global event filter.
998   Global event filters even see mouse events for
999   \l{QWidget::isEnabled()}{disabled widgets}. Note that application
1000   event filters are only called for objects that live in the main
1001   thread.
1002 
1003   \i Reimplementing QObject::event() (as QWidget does). If you do
1004   this you get Tab key presses, and you get to see the events before
1005   any widget-specific event filters.
1006 
1007   \i Installing an event filter on the object. Such an event filter gets all
1008   the events, including Tab and Shift+Tab key press events, as long as they
1009   do not change the focus widget.
1010   \endlist
1011 
1012   \sa QObject::event(), installEventFilter()
1013 */
1014 
notify(QObject * receiver,QEvent * event)1015 bool QCoreApplication::notify(QObject *receiver, QEvent *event)
1016 {
1017     Q_D(QCoreApplication);
1018     // no events are delivered after ~QCoreApplication() has started
1019     if (QCoreApplicationPrivate::is_app_closing)
1020         return true;
1021 
1022     if (receiver == 0) {                        // serious error
1023         qWarning("QCoreApplication::notify: Unexpected null receiver");
1024         return true;
1025     }
1026 
1027 #ifndef QT_NO_DEBUG
1028     d->checkReceiverThread(receiver);
1029 #endif
1030 
1031     return receiver->isWidgetType() ? false : d->notify_helper(receiver, event);
1032 }
1033 
sendThroughApplicationEventFilters(QObject * receiver,QEvent * event)1034 bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event)
1035 {
1036     if (receiver->d_func()->threadData == this->threadData) {
1037         // application event filters are only called for objects in the GUI thread
1038         for (int i = 0; i < eventFilters.size(); ++i) {
1039             register QObject *obj = eventFilters.at(i);
1040             if (!obj)
1041                 continue;
1042             if (obj->d_func()->threadData != threadData) {
1043                 qWarning("QCoreApplication: Application event filter cannot be in a different thread.");
1044                 continue;
1045             }
1046             if (obj->eventFilter(receiver, event))
1047                 return true;
1048         }
1049     }
1050     return false;
1051 }
1052 
sendThroughObjectEventFilters(QObject * receiver,QEvent * event)1053 bool QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *receiver, QEvent *event)
1054 {
1055     Q_Q(QCoreApplication);
1056     if (receiver != q) {
1057         for (int i = 0; i < receiver->d_func()->eventFilters.size(); ++i) {
1058             register QObject *obj = receiver->d_func()->eventFilters.at(i);
1059             if (!obj)
1060                 continue;
1061             if (obj->d_func()->threadData != receiver->d_func()->threadData) {
1062                 qWarning("QCoreApplication: Object event filter cannot be in a different thread.");
1063                 continue;
1064             }
1065             if (obj->eventFilter(receiver, event))
1066                 return true;
1067         }
1068     }
1069     return false;
1070 }
1071 
1072 /*!\internal
1073 
1074   Helper function called by notify()
1075  */
notify_helper(QObject * receiver,QEvent * event)1076 bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
1077 {
1078     // send to all application event filters
1079     if (sendThroughApplicationEventFilters(receiver, event))
1080         return true;
1081     // send to all receiver event filters
1082     if (sendThroughObjectEventFilters(receiver, event))
1083         return true;
1084     // deliver the event
1085     return receiver->event(event);
1086 }
1087 
1088 /*!
1089   Returns true if an application object has not been created yet;
1090   otherwise returns false.
1091 
1092   \sa closingDown()
1093 */
1094 
startingUp()1095 bool QCoreApplication::startingUp()
1096 {
1097     return !QCoreApplicationPrivate::is_app_running;
1098 }
1099 
1100 /*!
1101   Returns true if the application objects are being destroyed;
1102   otherwise returns false.
1103 
1104   \sa startingUp()
1105 */
1106 
closingDown()1107 bool QCoreApplication::closingDown()
1108 {
1109     return QCoreApplicationPrivate::is_app_closing;
1110 }
1111 
1112 
1113 /*!
1114     Processes all pending events for the calling thread according to
1115     the specified \a flags until there are no more events to process.
1116 
1117     You can call this function occasionally when your program is busy
1118     performing a long operation (e.g. copying a file).
1119 
1120     In event you are running a local loop which calls this function
1121     continuously, without an event loop, the
1122     \l{QEvent::DeferredDelete}{DeferredDelete} events will
1123     not be processed. This can affect the behaviour of widgets,
1124     e.g. QToolTip, that rely on \l{QEvent::DeferredDelete}{DeferredDelete}
1125     events to function properly. An alternative would be to call
1126     \l{QCoreApplication::sendPostedEvents()}{sendPostedEvents()} from
1127     within that local loop.
1128 
1129     Calling this function processes events only for the calling thread.
1130 
1131     \threadsafe
1132 
1133     \sa exec(), QTimer, QEventLoop::processEvents(), flush(), sendPostedEvents()
1134 */
processEvents(QEventLoop::ProcessEventsFlags flags)1135 void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
1136 {
1137     QThreadData *data = QThreadData::current();
1138     if (!data->eventDispatcher)
1139         return;
1140     if (flags & QEventLoop::DeferredDeletion)
1141         QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
1142     data->eventDispatcher->processEvents(flags);
1143 }
1144 
1145 /*!
1146     \overload processEvents()
1147 
1148     Processes pending events for the calling thread for \a maxtime
1149     milliseconds or until there are no more events to process,
1150     whichever is shorter.
1151 
1152     You can call this function occasionally when you program is busy
1153     doing a long operation (e.g. copying a file).
1154 
1155     Calling this function processes events only for the calling thread.
1156 
1157     \threadsafe
1158 
1159     \sa exec(), QTimer, QEventLoop::processEvents()
1160 */
processEvents(QEventLoop::ProcessEventsFlags flags,int maxtime)1161 void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime)
1162 {
1163     QThreadData *data = QThreadData::current();
1164     if (!data->eventDispatcher)
1165         return;
1166     QElapsedTimer start;
1167     start.start();
1168     if (flags & QEventLoop::DeferredDeletion)
1169         QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
1170     while (data->eventDispatcher->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
1171         if (start.elapsed() > maxtime)
1172             break;
1173         if (flags & QEventLoop::DeferredDeletion)
1174             QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
1175     }
1176 }
1177 
1178 /*****************************************************************************
1179   Main event loop wrappers
1180  *****************************************************************************/
1181 
1182 /*!
1183     Enters the main event loop and waits until exit() is called.
1184     Returns the value that was set to exit() (which is 0 if exit() is
1185     called via quit()).
1186 
1187     It is necessary to call this function to start event handling. The
1188     main event loop receives events from the window system and
1189     dispatches these to the application widgets.
1190 
1191     To make your application perform idle processing (i.e. executing a
1192     special function whenever there are no pending events), use a
1193     QTimer with 0 timeout. More advanced idle processing schemes can
1194     be achieved using processEvents().
1195 
1196     We recommend that you connect clean-up code to the
1197     \l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in
1198     your application's \c{main()} function because on some platforms the
1199     QCoreApplication::exec() call may not return. For example, on Windows
1200     when the user logs off, the system terminates the process after Qt
1201     closes all top-level windows. Hence, there is no guarantee that the
1202     application will have time to exit its event loop and execute code at
1203     the end of the \c{main()} function after the QCoreApplication::exec()
1204     call.
1205 
1206     \sa quit(), exit(), processEvents(), QApplication::exec()
1207 */
exec()1208 int QCoreApplication::exec()
1209 {
1210     if (!QCoreApplicationPrivate::checkInstance("exec"))
1211         return -1;
1212 
1213     QThreadData *threadData = self->d_func()->threadData;
1214     if (threadData != QThreadData::current()) {
1215         qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
1216         return -1;
1217     }
1218     if (!threadData->eventLoops.isEmpty()) {
1219         qWarning("QCoreApplication::exec: The event loop is already running");
1220         return -1;
1221     }
1222 
1223     threadData->quitNow = false;
1224     QEventLoop eventLoop;
1225     self->d_func()->in_exec = true;
1226     self->d_func()->aboutToQuitEmitted = false;
1227     int returnCode = eventLoop.exec();
1228     threadData->quitNow = false;
1229     if (self) {
1230         self->d_func()->in_exec = false;
1231         if (!self->d_func()->aboutToQuitEmitted)
1232             emit self->aboutToQuit();
1233         self->d_func()->aboutToQuitEmitted = true;
1234         sendPostedEvents(0, QEvent::DeferredDelete);
1235     }
1236 
1237     return returnCode;
1238 }
1239 
1240 
1241 /*!
1242   Tells the application to exit with a return code.
1243 
1244     After this function has been called, the application leaves the
1245     main event loop and returns from the call to exec(). The exec()
1246     function returns \a returnCode. If the event loop is not running,
1247     this function does nothing.
1248 
1249   By convention, a \a returnCode of 0 means success, and any non-zero
1250   value indicates an error.
1251 
1252   Note that unlike the C library function of the same name, this
1253   function \e does return to the caller -- it is event processing that
1254   stops.
1255 
1256   \sa quit(), exec()
1257 */
exit(int returnCode)1258 void QCoreApplication::exit(int returnCode)
1259 {
1260     if (!self)
1261         return;
1262     QThreadData *data = self->d_func()->threadData;
1263     data->quitNow = true;
1264     for (int i = 0; i < data->eventLoops.size(); ++i) {
1265         QEventLoop *eventLoop = data->eventLoops.at(i);
1266         eventLoop->exit(returnCode);
1267     }
1268 }
1269 
1270 /*****************************************************************************
1271   QCoreApplication management of posted events
1272  *****************************************************************************/
1273 
1274 /*!
1275     \fn bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
1276 
1277     Sends event \a event directly to receiver \a receiver, using the
1278     notify() function. Returns the value that was returned from the
1279     event handler.
1280 
1281     The event is \e not deleted when the event has been sent. The normal
1282     approach is to create the event on the stack, for example:
1283 
1284     \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 0
1285 
1286     \sa postEvent(), notify()
1287 */
1288 
1289 /*!
1290     Adds the event \a event, with the object \a receiver as the
1291     receiver of the event, to an event queue and returns immediately.
1292 
1293     The event must be allocated on the heap since the post event queue
1294     will take ownership of the event and delete it once it has been
1295     posted.  It is \e {not safe} to access the event after
1296     it has been posted.
1297 
1298     When control returns to the main event loop, all events that are
1299     stored in the queue will be sent using the notify() function.
1300 
1301     Events are processed in the order posted. For more control over
1302     the processing order, use the postEvent() overload below, which
1303     takes a priority argument. This function posts all event with a
1304     Qt::NormalEventPriority.
1305 
1306     \threadsafe
1307 
1308     \sa sendEvent(), notify(), sendPostedEvents()
1309 */
1310 
postEvent(QObject * receiver,QEvent * event)1311 void QCoreApplication::postEvent(QObject *receiver, QEvent *event)
1312 {
1313     postEvent(receiver, event, Qt::NormalEventPriority);
1314 }
1315 
1316 
1317 /*!
1318     \overload postEvent()
1319     \since 4.3
1320 
1321     Adds the event \a event, with the object \a receiver as the
1322     receiver of the event, to an event queue and returns immediately.
1323 
1324     The event must be allocated on the heap since the post event queue
1325     will take ownership of the event and delete it once it has been
1326     posted.  It is \e {not safe} to access the event after
1327     it has been posted.
1328 
1329     When control returns to the main event loop, all events that are
1330     stored in the queue will be sent using the notify() function.
1331 
1332     Events are sorted in descending \a priority order, i.e. events
1333     with a high \a priority are queued before events with a lower \a
1334     priority. The \a priority can be any integer value, i.e. between
1335     INT_MAX and INT_MIN, inclusive; see Qt::EventPriority for more
1336     details. Events with equal \a priority will be processed in the
1337     order posted.
1338 
1339     \threadsafe
1340 
1341     \sa sendEvent(), notify(), sendPostedEvents(), Qt::EventPriority
1342 */
postEvent(QObject * receiver,QEvent * event,int priority)1343 void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
1344 {
1345     if (receiver == 0) {
1346         qWarning("QCoreApplication::postEvent: Unexpected null receiver");
1347         delete event;
1348         return;
1349     }
1350 
1351     QThreadData * volatile * pdata = &receiver->d_func()->threadData;
1352     QThreadData *data = *pdata;
1353     if (!data) {
1354         // posting during destruction? just delete the event to prevent a leak
1355         delete event;
1356         return;
1357     }
1358 
1359     // lock the post event mutex
1360     data->postEventList.mutex.lock();
1361 
1362     // if object has moved to another thread, follow it
1363     while (data != *pdata) {
1364         data->postEventList.mutex.unlock();
1365 
1366         data = *pdata;
1367         if (!data) {
1368             // posting during destruction? just delete the event to prevent a leak
1369             delete event;
1370             return;
1371         }
1372 
1373         data->postEventList.mutex.lock();
1374     }
1375 
1376     QMutexUnlocker locker(&data->postEventList.mutex);
1377 
1378     // if this is one of the compressible events, do compression
1379     if (receiver->d_func()->postedEvents
1380         && self && self->compressEvent(event, receiver, &data->postEventList)) {
1381         return;
1382     }
1383 
1384     if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {
1385         // remember the current running eventloop for DeferredDelete
1386         // events posted in the receiver's thread
1387         event->d = reinterpret_cast<QEventPrivate *>(quintptr(data->loopLevel));
1388     }
1389 
1390     // delete the event on exceptions to protect against memory leaks till the event is
1391     // properly owned in the postEventList
1392     QScopedPointer<QEvent> eventDeleter(event);
1393     data->postEventList.addEvent(QPostEvent(receiver, event, priority));
1394     eventDeleter.take();
1395     event->posted = true;
1396     ++receiver->d_func()->postedEvents;
1397     data->canWait = false;
1398     locker.unlock();
1399 
1400     if (data->eventDispatcher)
1401         data->eventDispatcher->wakeUp();
1402 }
1403 
1404 /*!
1405   \internal
1406   Returns true if \a event was compressed away (possibly deleted) and should not be added to the list.
1407 */
compressEvent(QEvent * event,QObject * receiver,QPostEventList * postedEvents)1408 bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents)
1409 {
1410 #ifdef Q_WS_WIN
1411     Q_ASSERT(event);
1412     Q_ASSERT(receiver);
1413     Q_ASSERT(postedEvents);
1414 
1415     // compress posted timers to this object.
1416     if (event->type() == QEvent::Timer && receiver->d_func()->postedEvents > 0) {
1417         int timerId = ((QTimerEvent *) event)->timerId();
1418         for (int i=0; i<postedEvents->size(); ++i) {
1419             const QPostEvent &e = postedEvents->at(i);
1420             if (e.receiver == receiver && e.event && e.event->type() == QEvent::Timer
1421                 && ((QTimerEvent *) e.event)->timerId() == timerId) {
1422                 delete event;
1423                 return true;
1424             }
1425         }
1426     } else
1427 #endif
1428         if ((event->type() == QEvent::DeferredDelete
1429              || event->type() == QEvent::Quit)
1430             && receiver->d_func()->postedEvents > 0) {
1431             for (int i = 0; i < postedEvents->size(); ++i) {
1432                 const QPostEvent &cur = postedEvents->at(i);
1433                 if (cur.receiver != receiver
1434                     || cur.event == 0
1435                     || cur.event->type() != event->type())
1436                     continue;
1437                 // found an event for this receiver
1438                 delete event;
1439                 return true;
1440             }
1441         }
1442     return false;
1443 }
1444 
1445 /*!
1446   \fn void QCoreApplication::sendPostedEvents()
1447   \overload sendPostedEvents()
1448 
1449     Dispatches all posted events, i.e. empties the event queue.
1450 */
1451 
1452 /*!
1453   Immediately dispatches all events which have been previously queued
1454   with QCoreApplication::postEvent() and which are for the object \a receiver
1455   and have the event type \a event_type.
1456 
1457   Events from the window system are \e not dispatched by this
1458   function, but by processEvents().
1459 
1460   If \a receiver is null, the events of \a event_type are sent for all
1461   objects. If \a event_type is 0, all the events are sent for \a receiver.
1462 
1463   \note This method must be called from the same thread as its QObject parameter, \a receiver.
1464 
1465   \sa flush(), postEvent()
1466 */
1467 
sendPostedEvents(QObject * receiver,int event_type)1468 void QCoreApplication::sendPostedEvents(QObject *receiver, int event_type)
1469 {
1470     QThreadData *data = QThreadData::current();
1471 
1472     QCoreApplicationPrivate::sendPostedEvents(receiver, event_type, data);
1473 }
1474 
sendPostedEvents(QObject * receiver,int event_type,QThreadData * data)1475 void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type,
1476                                                QThreadData *data)
1477 {
1478     if (event_type == -1) {
1479         // we were called by an obsolete event dispatcher.
1480         event_type = 0;
1481     }
1482 
1483     if (receiver && receiver->d_func()->threadData != data) {
1484         qWarning("QCoreApplication::sendPostedEvents: Cannot send "
1485                  "posted events for objects in another thread");
1486         return;
1487     }
1488 
1489     ++data->postEventList.recursion;
1490 
1491 #ifdef QT3_SUPPORT
1492     if (event_type == QEvent::ChildInserted) {
1493         if (receiver) {
1494             // optimize sendPostedEvents(w, QEvent::ChildInserted) calls away
1495             receiver->d_func()->sendPendingChildInsertedEvents();
1496             --data->postEventList.recursion;
1497             return;
1498         }
1499 
1500         // ChildInserted events are sent in response to *Request
1501         event_type = QEvent::ChildInsertedRequest;
1502     }
1503 #endif
1504 
1505     QMutexLocker locker(&data->postEventList.mutex);
1506 
1507     // by default, we assume that the event dispatcher can go to sleep after
1508     // processing all events. if any new events are posted while we send
1509     // events, canWait will be set to false.
1510     data->canWait = (data->postEventList.size() == 0);
1511 
1512     if (data->postEventList.size() == 0 || (receiver && !receiver->d_func()->postedEvents)) {
1513         --data->postEventList.recursion;
1514         return;
1515     }
1516 
1517     data->canWait = true;
1518 
1519     // okay. here is the tricky loop. be careful about optimizing
1520     // this, it looks the way it does for good reasons.
1521     int startOffset = data->postEventList.startOffset;
1522     int &i = (!event_type && !receiver) ? data->postEventList.startOffset : startOffset;
1523     data->postEventList.insertionOffset = data->postEventList.size();
1524 
1525     while (i < data->postEventList.size()) {
1526         // avoid live-lock
1527         if (i >= data->postEventList.insertionOffset)
1528             break;
1529 
1530         const QPostEvent &pe = data->postEventList.at(i);
1531         ++i;
1532 
1533         if (!pe.event)
1534             continue;
1535         if ((receiver && receiver != pe.receiver) || (event_type && event_type != pe.event->type())) {
1536             data->canWait = false;
1537             continue;
1538         }
1539 
1540         if (pe.event->type() == QEvent::DeferredDelete) {
1541             // DeferredDelete events are only sent when we are explicitly asked to
1542             // (s.a. QEvent::DeferredDelete), and then only if the event loop that
1543             // posted the event has returned.
1544             const bool allowDeferredDelete =
1545                 (quintptr(pe.event->d) > unsigned(data->loopLevel)
1546                  || (!quintptr(pe.event->d) && data->loopLevel > 0)
1547                  || (event_type == QEvent::DeferredDelete
1548                      && quintptr(pe.event->d) == unsigned(data->loopLevel)));
1549             if (!allowDeferredDelete) {
1550                 // cannot send deferred delete
1551                 if (!event_type && !receiver) {
1552                     // don't lose the event
1553                     data->postEventList.addEvent(pe);
1554                     const_cast<QPostEvent &>(pe).event = 0;
1555                 }
1556                 continue;
1557             }
1558         }
1559 
1560         // first, we diddle the event so that we can deliver
1561         // it, and that no one will try to touch it later.
1562         pe.event->posted = false;
1563         QEvent * e = pe.event;
1564         QObject * r = pe.receiver;
1565 
1566         --r->d_func()->postedEvents;
1567         Q_ASSERT(r->d_func()->postedEvents >= 0);
1568 
1569         // next, update the data structure so that we're ready
1570         // for the next event.
1571         const_cast<QPostEvent &>(pe).event = 0;
1572 
1573         locker.unlock();
1574         // after all that work, it's time to deliver the event.
1575 #ifdef QT_NO_EXCEPTIONS
1576         QCoreApplication::sendEvent(r, e);
1577 #else
1578         try {
1579             QCoreApplication::sendEvent(r, e);
1580         } catch (...) {
1581             delete e;
1582             locker.relock();
1583 
1584             // since we were interrupted, we need another pass to make sure we clean everything up
1585             data->canWait = false;
1586 
1587             // uglehack: copied from below
1588             --data->postEventList.recursion;
1589             if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
1590                 data->eventDispatcher->wakeUp();
1591             throw;              // rethrow
1592         }
1593 #endif
1594 
1595         delete e;
1596         locker.relock();
1597 
1598         // careful when adding anything below this point - the
1599         // sendEvent() call might invalidate any invariants this
1600         // function depends on.
1601     }
1602 
1603     --data->postEventList.recursion;
1604     if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
1605         data->eventDispatcher->wakeUp();
1606 
1607     // clear the global list, i.e. remove everything that was
1608     // delivered.
1609     if (!event_type && !receiver && data->postEventList.startOffset >= 0) {
1610         const QPostEventList::iterator it = data->postEventList.begin();
1611         data->postEventList.erase(it, it + data->postEventList.startOffset);
1612         data->postEventList.insertionOffset -= data->postEventList.startOffset;
1613         Q_ASSERT(data->postEventList.insertionOffset >= 0);
1614         data->postEventList.startOffset = 0;
1615     }
1616 }
1617 
1618 /*!
1619   Removes all events posted using postEvent() for \a receiver.
1620 
1621   The events are \e not dispatched, instead they are removed from the
1622   queue. You should never need to call this function. If you do call it,
1623   be aware that killing events may cause \a receiver to break one or
1624   more invariants.
1625 
1626   \threadsafe
1627 */
1628 
removePostedEvents(QObject * receiver)1629 void QCoreApplication::removePostedEvents(QObject *receiver)
1630 {
1631     removePostedEvents(receiver, 0);
1632 }
1633 
1634 /*!
1635     \overload removePostedEvents()
1636     \since 4.3
1637 
1638     Removes all events of the given \a eventType that were posted
1639     using postEvent() for \a receiver.
1640 
1641     The events are \e not dispatched, instead they are removed from
1642     the queue. You should never need to call this function. If you do
1643     call it, be aware that killing events may cause \a receiver to
1644     break one or more invariants.
1645 
1646     If \a receiver is null, the events of \a eventType are removed for
1647     all objects. If \a eventType is 0, all the events are removed for
1648     \a receiver.
1649 
1650     \threadsafe
1651 */
1652 
removePostedEvents(QObject * receiver,int eventType)1653 void QCoreApplication::removePostedEvents(QObject *receiver, int eventType)
1654 {
1655 #ifdef QT3_SUPPORT
1656     if (eventType == QEvent::ChildInserted)
1657         eventType = QEvent::ChildInsertedRequest;
1658 #endif
1659 
1660     QThreadData *data = receiver ? receiver->d_func()->threadData : QThreadData::current();
1661     QMutexLocker locker(&data->postEventList.mutex);
1662 
1663     // the QObject destructor calls this function directly.  this can
1664     // happen while the event loop is in the middle of posting events,
1665     // and when we get here, we may not have any more posted events
1666     // for this object.
1667     if (receiver && !receiver->d_func()->postedEvents)
1668         return;
1669 
1670     //we will collect all the posted events for the QObject
1671     //and we'll delete after the mutex was unlocked
1672     QVarLengthArray<QEvent*> events;
1673     int n = data->postEventList.size();
1674     int j = 0;
1675 
1676     for (int i = 0; i < n; ++i) {
1677         const QPostEvent &pe = data->postEventList.at(i);
1678 
1679         if ((!receiver || pe.receiver == receiver)
1680             && (pe.event && (eventType == 0 || pe.event->type() == eventType))) {
1681             --pe.receiver->d_func()->postedEvents;
1682 #ifdef QT3_SUPPORT
1683             if (pe.event->type() == QEvent::ChildInsertedRequest)
1684                 pe.receiver->d_func()->pendingChildInsertedEvents.clear();
1685 #endif
1686             pe.event->posted = false;
1687             events.append(pe.event);
1688             const_cast<QPostEvent &>(pe).event = 0;
1689         } else if (!data->postEventList.recursion) {
1690             if (i != j)
1691                 data->postEventList.swap(i, j);
1692             ++j;
1693         }
1694     }
1695 
1696 #ifdef QT_DEBUG
1697     if (receiver && eventType == 0) {
1698         Q_ASSERT(!receiver->d_func()->postedEvents);
1699     }
1700 #endif
1701 
1702     if (!data->postEventList.recursion) {
1703         // truncate list
1704         data->postEventList.erase(data->postEventList.begin() + j, data->postEventList.end());
1705     }
1706 
1707     locker.unlock();
1708     for (int i = 0; i < events.count(); ++i) {
1709         delete events[i];
1710     }
1711 }
1712 
1713 /*!
1714   Removes \a event from the queue of posted events, and emits a
1715   warning message if appropriate.
1716 
1717   \warning This function can be \e really slow. Avoid using it, if
1718   possible.
1719 
1720   \threadsafe
1721 */
1722 
removePostedEvent(QEvent * event)1723 void QCoreApplicationPrivate::removePostedEvent(QEvent * event)
1724 {
1725     if (!event || !event->posted)
1726         return;
1727 
1728     QThreadData *data = QThreadData::current();
1729 
1730     QMutexLocker locker(&data->postEventList.mutex);
1731 
1732     if (data->postEventList.size() == 0) {
1733 #if defined(QT_DEBUG)
1734         qDebug("QCoreApplication::removePostedEvent: Internal error: %p %d is posted",
1735                 (void*)event, event->type());
1736         return;
1737 #endif
1738     }
1739 
1740     for (int i = 0; i < data->postEventList.size(); ++i) {
1741         const QPostEvent & pe = data->postEventList.at(i);
1742         if (pe.event == event) {
1743 #ifndef QT_NO_DEBUG
1744             qWarning("QCoreApplication::removePostedEvent: Event of type %d deleted while posted to %s %s",
1745                      event->type(),
1746                      pe.receiver->metaObject()->className(),
1747                      pe.receiver->objectName().toLocal8Bit().data());
1748 #endif
1749             --pe.receiver->d_func()->postedEvents;
1750             pe.event->posted = false;
1751             delete pe.event;
1752             const_cast<QPostEvent &>(pe).event = 0;
1753             return;
1754         }
1755     }
1756 }
1757 
1758 /*!\reimp
1759 
1760 */
event(QEvent * e)1761 bool QCoreApplication::event(QEvent *e)
1762 {
1763     if (e->type() == QEvent::Quit) {
1764         quit();
1765         return true;
1766     }
1767     return QObject::event(e);
1768 }
1769 
1770 /*! \enum QCoreApplication::Encoding
1771 
1772     This enum type defines the 8-bit encoding of character string
1773     arguments to translate():
1774 
1775     \value CodecForTr  The encoding specified by
1776                        QTextCodec::codecForTr() (Latin-1 if none has
1777                        been set).
1778     \value UnicodeUTF8  UTF-8.
1779     \value DefaultCodec  (Obsolete) Use CodecForTr instead.
1780 
1781     \sa QObject::tr(), QObject::trUtf8(), QString::fromUtf8()
1782 */
1783 
1784 /*!
1785     Tells the application to exit with return code 0 (success).
1786     Equivalent to calling QCoreApplication::exit(0).
1787 
1788     It's common to connect the QApplication::lastWindowClosed() signal
1789     to quit(), and you also often connect e.g. QAbstractButton::clicked() or
1790     signals in QAction, QMenu, or QMenuBar to it.
1791 
1792     Example:
1793 
1794     \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 1
1795 
1796     \sa exit(), aboutToQuit(), QApplication::lastWindowClosed()
1797 */
1798 
quit()1799 void QCoreApplication::quit()
1800 {
1801     exit(0);
1802 }
1803 
1804 /*!
1805   \fn void QCoreApplication::aboutToQuit()
1806 
1807   This signal is emitted when the application is about to quit the
1808   main event loop, e.g. when the event loop level drops to zero.
1809   This may happen either after a call to quit() from inside the
1810   application or when the users shuts down the entire desktop session.
1811 
1812   The signal is particularly useful if your application has to do some
1813   last-second cleanup. Note that no user interaction is possible in
1814   this state.
1815 
1816   \sa quit()
1817 */
1818 
1819 #ifndef QT_NO_TRANSLATION
1820 /*!
1821     Adds the translation file \a translationFile to the list of
1822     translation files to be used for translations.
1823 
1824     Multiple translation files can be installed. Translations are
1825     searched for in the reverse order in which they were installed,
1826     so the most recently installed translation file is searched first
1827     and the first translation file installed is searched last.
1828     The search stops as soon as a translation containing a matching
1829     string is found.
1830 
1831     Installing or removing a QTranslator, or changing an installed QTranslator
1832     generates a \l{QEvent::LanguageChange}{LanguageChange} event for the
1833     QCoreApplication instance. A QApplication instance will propagate the event
1834     to all toplevel windows, where a reimplementation of changeEvent can
1835     re-translate the user interface by passing user-visible strings via the
1836     tr() function to the respective property setters. User-interface classes
1837     generated by \l{Qt Designer} provide a \c retranslateUi() function that can be
1838     called.
1839 
1840     \sa removeTranslator() translate() QTranslator::load() {Dynamic Translation}
1841 */
1842 
installTranslator(QTranslator * translationFile)1843 void QCoreApplication::installTranslator(QTranslator *translationFile)
1844 {
1845     if (!translationFile)
1846         return;
1847 
1848     if (!QCoreApplicationPrivate::checkInstance("installTranslator"))
1849         return;
1850     QCoreApplicationPrivate *d = self->d_func();
1851     d->translators.prepend(translationFile);
1852 
1853 #ifndef QT_NO_TRANSLATION_BUILDER
1854     if (translationFile->isEmpty())
1855         return;
1856 #endif
1857 
1858     QEvent ev(QEvent::LanguageChange);
1859     QCoreApplication::sendEvent(self, &ev);
1860 }
1861 
1862 /*!
1863     Removes the translation file \a translationFile from the list of
1864     translation files used by this application. (It does not delete the
1865     translation file from the file system.)
1866 
1867     \sa installTranslator() translate(), QObject::tr()
1868 */
1869 
removeTranslator(QTranslator * translationFile)1870 void QCoreApplication::removeTranslator(QTranslator *translationFile)
1871 {
1872     if (!translationFile)
1873         return;
1874     if (!QCoreApplicationPrivate::checkInstance("removeTranslator"))
1875         return;
1876     QCoreApplicationPrivate *d = self->d_func();
1877     if (d->translators.removeAll(translationFile) && !self->closingDown()) {
1878         QEvent ev(QEvent::LanguageChange);
1879         QCoreApplication::sendEvent(self, &ev);
1880     }
1881 }
1882 
1883 /*!
1884     \overload translate()
1885 */
translate(const char * context,const char * sourceText,const char * disambiguation,Encoding encoding)1886 QString QCoreApplication::translate(const char *context, const char *sourceText,
1887                                     const char *disambiguation, Encoding encoding)
1888 {
1889     return translate(context, sourceText, disambiguation, encoding, -1);
1890 }
1891 
replacePercentN(QString * result,int n)1892 static void replacePercentN(QString *result, int n)
1893 {
1894     if (n >= 0) {
1895         int percentPos = 0;
1896         int len = 0;
1897         while ((percentPos = result->indexOf(QLatin1Char('%'), percentPos + len)) != -1) {
1898             len = 1;
1899             QString fmt;
1900             if (result->at(percentPos + len) == QLatin1Char('L')) {
1901                 ++len;
1902                 fmt = QLatin1String("%L1");
1903             } else {
1904                 fmt = QLatin1String("%1");
1905             }
1906             if (result->at(percentPos + len) == QLatin1Char('n')) {
1907                 fmt = fmt.arg(n);
1908                 ++len;
1909                 result->replace(percentPos, len, fmt);
1910                 len = fmt.length();
1911             }
1912         }
1913     }
1914 }
1915 
1916 /*!
1917     \reentrant
1918     \since 4.5
1919 
1920     Returns the translation text for \a sourceText, by querying the
1921     installed translation files. The translation files are searched
1922     from the most recently installed file back to the first
1923     installed file.
1924 
1925     QObject::tr() and QObject::trUtf8() provide this functionality
1926     more conveniently.
1927 
1928     \a context is typically a class name (e.g., "MyDialog") and \a
1929     sourceText is either English text or a short identifying text.
1930 
1931     \a disambiguation is an identifying string, for when the same \a
1932     sourceText is used in different roles within the same context. By
1933     default, it is null.
1934 
1935     See the \l QTranslator and \l QObject::tr() documentation for
1936     more information about contexts, disambiguations and comments.
1937 
1938     \a encoding indicates the 8-bit encoding of character strings.
1939 
1940     \a n is used in conjunction with \c %n to support plural forms.
1941     See QObject::tr() for details.
1942 
1943     If none of the translation files contain a translation for \a
1944     sourceText in \a context, this function returns a QString
1945     equivalent of \a sourceText. The encoding of \a sourceText is
1946     specified by \e encoding; it defaults to CodecForTr.
1947 
1948     This function is not virtual. You can use alternative translation
1949     techniques by subclassing \l QTranslator.
1950 
1951     \warning This method is reentrant only if all translators are
1952     installed \e before calling this method. Installing or removing
1953     translators while performing translations is not supported. Doing
1954     so will most likely result in crashes or other undesirable
1955     behavior.
1956 
1957     \sa QObject::tr() installTranslator() QTextCodec::codecForTr()
1958 */
1959 
1960 
translate(const char * context,const char * sourceText,const char * disambiguation,Encoding encoding,int n)1961 QString QCoreApplication::translate(const char *context, const char *sourceText,
1962                                     const char *disambiguation, Encoding encoding, int n)
1963 {
1964     QString result;
1965 
1966     if (!sourceText)
1967         return result;
1968 
1969     if (self && !self->d_func()->translators.isEmpty()) {
1970         QList<QTranslator*>::ConstIterator it;
1971         QTranslator *translationFile;
1972         for (it = self->d_func()->translators.constBegin(); it != self->d_func()->translators.constEnd(); ++it) {
1973             translationFile = *it;
1974             result = translationFile->translate(context, sourceText, disambiguation, n);
1975             if (!result.isEmpty())
1976                 break;
1977         }
1978     }
1979 
1980     if (result.isEmpty()) {
1981 #ifdef QT_NO_TEXTCODEC
1982         Q_UNUSED(encoding)
1983 #else
1984         if (encoding == UnicodeUTF8)
1985             result = QString::fromUtf8(sourceText);
1986         else if (QTextCodec::codecForTr() != 0)
1987             result = QTextCodec::codecForTr()->toUnicode(sourceText);
1988         else
1989 #endif
1990             result = QString::fromLatin1(sourceText);
1991     }
1992 
1993     replacePercentN(&result, n);
1994     return result;
1995 }
1996 
1997 // Declared in qglobal.h
qtTrId(const char * id,int n)1998 QString qtTrId(const char *id, int n)
1999 {
2000     return QCoreApplication::translate(0, id, 0, QCoreApplication::UnicodeUTF8, n);
2001 }
2002 
isTranslatorInstalled(QTranslator * translator)2003 bool QCoreApplicationPrivate::isTranslatorInstalled(QTranslator *translator)
2004 {
2005     return QCoreApplication::self
2006            && QCoreApplication::self->d_func()->translators.contains(translator);
2007 }
2008 
2009 #endif //QT_NO_TRANSLATE
2010 
2011 /*!
2012     Returns the directory that contains the application executable.
2013 
2014     For example, if you have installed Qt in the \c{C:\Trolltech\Qt}
2015     directory, and you run the \c{regexp} example, this function will
2016     return "C:/Trolltech/Qt/examples/tools/regexp".
2017 
2018     On Mac OS X this will point to the directory actually containing the
2019     executable, which may be inside of an application bundle (if the
2020     application is bundled).
2021 
2022     \warning On Linux, this function will try to get the path from the
2023     \c {/proc} file system. If that fails, it assumes that \c
2024     {argv[0]} contains the absolute file name of the executable. The
2025     function also assumes that the current directory has not been
2026     changed by the application.
2027 
2028     In Symbian this function will return the application private directory,
2029     not the path to executable itself, as those are always in \c {/sys/bin}.
2030     If the application is in a read only drive, i.e. ROM, then the private path
2031     on the system drive will be returned.
2032 
2033     \sa applicationFilePath()
2034 */
applicationDirPath()2035 QString QCoreApplication::applicationDirPath()
2036 {
2037     if (!self) {
2038         qWarning("QCoreApplication::applicationDirPath: Please instantiate the QApplication object first");
2039         return QString();
2040     }
2041 
2042     QCoreApplicationPrivate *d = self->d_func();
2043     if (d->cachedApplicationDirPath.isNull())
2044 #if defined(Q_OS_SYMBIAN)
2045     {
2046         QString appPath;
2047         RFs& fs = qt_s60GetRFs();
2048         TChar driveChar;
2049         QChar qDriveChar;
2050         driveChar = (RProcess().FileName())[0];
2051 
2052         //Check if the process is installed in a read only drive (typically ROM),
2053         //and use the system drive (typically C:) if so.
2054         TInt drive;
2055         TDriveInfo driveInfo;
2056         TInt err = fs.CharToDrive(driveChar, drive);
2057         if (err == KErrNone) {
2058             err = fs.Drive(driveInfo, drive);
2059         }
2060         if (err != KErrNone || (driveInfo.iDriveAtt & KDriveAttRom) || (driveInfo.iMediaAtt
2061             & KMediaAttWriteProtected)) {
2062             drive = fs.GetSystemDrive();
2063             fs.DriveToChar(drive, driveChar);
2064         }
2065 
2066         qDriveChar = QChar(QLatin1Char(driveChar)).toUpper();
2067 
2068         TFileName privatePath;
2069         fs.PrivatePath(privatePath);
2070         appPath = qt_TDesC2QString(privatePath);
2071         appPath.prepend(QLatin1Char(':')).prepend(qDriveChar);
2072 
2073         d->cachedApplicationDirPath = QFileInfo(appPath).path();
2074     }
2075 #else
2076         d->cachedApplicationDirPath = QFileInfo(applicationFilePath()).path();
2077 #endif
2078     return d->cachedApplicationDirPath;
2079 }
2080 
2081 /*!
2082     Returns the file path of the application executable.
2083 
2084     For example, if you have installed Qt in the \c{/usr/local/qt}
2085     directory, and you run the \c{regexp} example, this function will
2086     return "/usr/local/qt/examples/tools/regexp/regexp".
2087 
2088     \warning On Linux, this function will try to get the path from the
2089     \c {/proc} file system. If that fails, it assumes that \c
2090     {argv[0]} contains the absolute file name of the executable. The
2091     function also assumes that the current directory has not been
2092     changed by the application.
2093 
2094     \sa applicationDirPath()
2095 */
applicationFilePath()2096 QString QCoreApplication::applicationFilePath()
2097 {
2098     if (!self) {
2099         qWarning("QCoreApplication::applicationFilePath: Please instantiate the QApplication object first");
2100         return QString();
2101     }
2102 
2103     QCoreApplicationPrivate *d = self->d_func();
2104     if (!d->cachedApplicationFilePath.isNull())
2105         return d->cachedApplicationFilePath;
2106 
2107 #if defined(Q_WS_WIN)
2108     d->cachedApplicationFilePath = QFileInfo(qAppFileName()).filePath();
2109     return d->cachedApplicationFilePath;
2110 #elif defined(Q_OS_BLACKBERRY)
2111     if (!arguments().isEmpty()) { // args is never empty, but the navigator can change behaviour some day
2112         QFileInfo fileInfo(arguments().at(0));
2113         const bool zygotized = fileInfo.exists();
2114         if (zygotized) {
2115             // Handle the zygotized case:
2116             d->cachedApplicationFilePath = QDir::cleanPath(fileInfo.absoluteFilePath());
2117             return d->cachedApplicationFilePath;
2118         }
2119     }
2120 
2121     // Handle the non-zygotized case:
2122     const size_t maximum_path = static_cast<size_t>(pathconf("/",_PC_PATH_MAX));
2123     char buff[maximum_path+1];
2124     if (_cmdname(buff)) {
2125         d->cachedApplicationFilePath = QDir::cleanPath(QString::fromLocal8Bit(buff));
2126         return d->cachedApplicationFilePath;
2127     } else {
2128         qWarning("QCoreApplication::applicationFilePath: _cmdname() failed");
2129         // _cmdname() won't fail, but just in case, fallback to the old method
2130         QDir dir(QLatin1String("./app/native/"));
2131         QStringList executables = dir.entryList(QDir::Executable | QDir::Files);
2132         if (!executables.empty()) {
2133             //We assume that there is only one executable in the folder
2134             d->cachedApplicationFilePath = dir.absoluteFilePath(executables.first());
2135             return d->cachedApplicationFilePath;
2136         } else {
2137             return QString();
2138         }
2139     }
2140 #elif defined(Q_WS_MAC)
2141     QString qAppFileName_str = qAppFileName();
2142     if(!qAppFileName_str.isEmpty()) {
2143         QFileInfo fi(qAppFileName_str);
2144         d->cachedApplicationFilePath = fi.exists() ? fi.canonicalFilePath() : QString();
2145         return d->cachedApplicationFilePath;
2146     }
2147 #endif
2148 #if defined(Q_OS_SYMBIAN)
2149     QString appPath;
2150     RProcess proc;
2151     TInt err = proc.Open(proc.Id());
2152     if (err == KErrNone) {
2153         TFileName procName = proc.FileName();
2154         appPath.append(QString(reinterpret_cast<const QChar*>(procName.Ptr()), procName.Length()));
2155         proc.Close();
2156     }
2157 
2158     d->cachedApplicationFilePath = appPath;
2159     return d->cachedApplicationFilePath;
2160 
2161 #elif defined( Q_OS_UNIX )
2162 #  ifdef Q_OS_LINUX
2163     // Try looking for a /proc/<pid>/exe symlink first which points to
2164     // the absolute path of the executable
2165     QFileInfo pfi(QString::fromLatin1("/proc/%1/exe").arg(getpid()));
2166     if (pfi.exists() && pfi.isSymLink()) {
2167         d->cachedApplicationFilePath = pfi.canonicalFilePath();
2168         return d->cachedApplicationFilePath;
2169     }
2170 #  endif
2171 
2172     QString argv0 = QFile::decodeName(QByteArray(argv()[0]));
2173     QString absPath;
2174 
2175     if (!argv0.isEmpty() && argv0.at(0) == QLatin1Char('/')) {
2176         /*
2177           If argv0 starts with a slash, it is already an absolute
2178           file path.
2179         */
2180         absPath = argv0;
2181     } else if (argv0.contains(QLatin1Char('/'))) {
2182         /*
2183           If argv0 contains one or more slashes, it is a file path
2184           relative to the current directory.
2185         */
2186         absPath = QDir::current().absoluteFilePath(argv0);
2187     } else {
2188         /*
2189           Otherwise, the file path has to be determined using the
2190           PATH environment variable.
2191         */
2192         QByteArray pEnv = qgetenv("PATH");
2193         QDir currentDir = QDir::current();
2194         QStringList paths = QString::fromLocal8Bit(pEnv.constData()).split(QLatin1Char(':'));
2195         for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
2196             if ((*p).isEmpty())
2197                 continue;
2198             QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
2199             QFileInfo candidate_fi(candidate);
2200             if (candidate_fi.exists() && !candidate_fi.isDir()) {
2201                 absPath = candidate;
2202                 break;
2203             }
2204         }
2205     }
2206 
2207     absPath = QDir::cleanPath(absPath);
2208 
2209     QFileInfo fi(absPath);
2210     d->cachedApplicationFilePath = fi.exists() ? fi.canonicalFilePath() : QString();
2211     return d->cachedApplicationFilePath;
2212 #endif
2213 }
2214 
2215 /*!
2216     \since 4.4
2217 
2218     Returns the current process ID for the application.
2219 */
applicationPid()2220 qint64 QCoreApplication::applicationPid()
2221 {
2222 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
2223     return GetCurrentProcessId();
2224 #elif defined(Q_OS_VXWORKS)
2225     return (pid_t) taskIdCurrent;
2226 #else
2227     return getpid();
2228 #endif
2229 }
2230 
2231 /*!
2232     \obsolete
2233 
2234     Use arguments().size() instead.
2235 */
argc()2236 int QCoreApplication::argc()
2237 {
2238     if (!self) {
2239         qWarning("QCoreApplication::argc: Please instantiate the QApplication object first");
2240         return 0;
2241     }
2242     return self->d_func()->argc;
2243 }
2244 
2245 
2246 /*!
2247     \obsolete
2248 
2249     Use arguments() instead.
2250 */
argv()2251 char **QCoreApplication::argv()
2252 {
2253     if (!self) {
2254         qWarning("QCoreApplication::argv: Please instantiate the QApplication object first");
2255         return 0;
2256     }
2257     return self->d_func()->argv;
2258 }
2259 
2260 /*!
2261     \since 4.1
2262 
2263     Returns the list of command-line arguments.
2264 
2265     Usually arguments().at(0) is the program name, arguments().at(1)
2266     is the first argument, and arguments().last() is the last
2267     argument. See the note below about Windows.
2268 
2269     Calling this function is slow - you should store the result in a variable
2270     when parsing the command line.
2271 
2272     \warning On Unix, this list is built from the argc and argv parameters passed
2273     to the constructor in the main() function. The string-data in argv is
2274     interpreted using QString::fromLocal8Bit(); hence it is not possible to
2275     pass, for example, Japanese command line arguments on a system that runs in a
2276     Latin1 locale. Most modern Unix systems do not have this limitation, as they are
2277     Unicode-based.
2278 
2279     On NT-based Windows, this limitation does not apply either.
2280     On Windows, the arguments() are not built from the contents of argv/argc, as
2281     the content does not support Unicode. Instead, the arguments() are constructed
2282     from the return value of
2283     \l{http://msdn2.microsoft.com/en-us/library/ms683156(VS.85).aspx}{GetCommandLine()}.
2284     As a result of this, the string given by arguments().at(0) might not be
2285     the program name on Windows, depending on how the application was started.
2286 
2287     For Symbian applications started with \c RApaLsSession::StartApp one can specify
2288     arguments using \c CApaCommandLine::SetTailEndL function. Such arguments are only
2289     available via this method; they will not be passed to \c main function. Also note
2290     that only 8-bit string data set with \c CApaCommandLine::SetTailEndL is supported
2291     by this function.
2292 
2293     \sa applicationFilePath()
2294 */
2295 
arguments()2296 QStringList QCoreApplication::arguments()
2297 {
2298     QStringList list;
2299 
2300     if (!self) {
2301         qWarning("QCoreApplication::arguments: Please instantiate the QApplication object first");
2302         return list;
2303     }
2304 #ifdef Q_OS_WIN
2305     QString cmdline = QString::fromWCharArray(GetCommandLine());
2306 
2307 #if defined(Q_OS_WINCE)
2308     wchar_t tempFilename[MAX_PATH+1];
2309     if (GetModuleFileName(0, tempFilename, MAX_PATH)) {
2310         tempFilename[MAX_PATH] = 0;
2311         cmdline.prepend(QLatin1Char('\"') + QString::fromWCharArray(tempFilename) + QLatin1String("\" "));
2312     }
2313 #endif // Q_OS_WINCE
2314 
2315     list = qWinCmdArgs(cmdline);
2316     if (self->d_func()->application_type) { // GUI app? Skip known - see qapplication.cpp
2317         QStringList stripped;
2318         for (int a = 0; a < list.count(); ++a) {
2319             QString arg = list.at(a);
2320             QByteArray l1arg = arg.toLatin1();
2321             if (l1arg == "-qdevel" ||
2322                 l1arg == "-qdebug" ||
2323                 l1arg == "-reverse" ||
2324                 l1arg == "-stylesheet" ||
2325                 l1arg == "-widgetcount")
2326                 ;
2327             else if (l1arg.startsWith("-style=") ||
2328                      l1arg.startsWith("-qmljsdebugger="))
2329                 ;
2330             else if (l1arg == "-style" ||
2331                      l1arg == "-qmljsdebugger" ||
2332                      l1arg == "-session" ||
2333                      l1arg == "-graphicssystem" ||
2334                      l1arg == "-testability")
2335                 ++a;
2336             else
2337                 stripped += arg;
2338         }
2339         list = stripped;
2340     }
2341 #else
2342     const int ac = self->d_func()->argc;
2343     char ** const av = self->d_func()->argv;
2344     for (int a = 0; a < ac; ++a) {
2345         list << QString::fromLocal8Bit(av[a]);
2346     }
2347 #endif
2348 
2349     return list;
2350 }
2351 
2352 /*!
2353     \property QCoreApplication::organizationName
2354     \brief the name of the organization that wrote this application
2355 
2356     The value is used by the QSettings class when it is constructed
2357     using the empty constructor. This saves having to repeat this
2358     information each time a QSettings object is created.
2359 
2360     On Mac, QSettings uses organizationDomain() as the organization
2361     if it's not an empty string; otherwise it uses
2362     organizationName(). On all other platforms, QSettings uses
2363     organizationName() as the organization.
2364 
2365     On BlackBerry this property is read-only. It is obtained from the
2366     BAR application descriptor file.
2367 
2368     \sa organizationDomain applicationName
2369 */
2370 
setOrganizationName(const QString & orgName)2371 void QCoreApplication::setOrganizationName(const QString &orgName)
2372 {
2373     coreappdata()->orgName = orgName;
2374 }
2375 
organizationName()2376 QString QCoreApplication::organizationName()
2377 {
2378 #ifdef Q_OS_BLACKBERRY
2379     coreappdata()->loadManifest();
2380 #endif
2381     return coreappdata()->orgName;
2382 }
2383 
2384 /*!
2385     \property QCoreApplication::organizationDomain
2386     \brief the Internet domain of the organization that wrote this application
2387 
2388     The value is used by the QSettings class when it is constructed
2389     using the empty constructor. This saves having to repeat this
2390     information each time a QSettings object is created.
2391 
2392     On Mac, QSettings uses organizationDomain() as the organization
2393     if it's not an empty string; otherwise it uses organizationName().
2394     On all other platforms, QSettings uses organizationName() as the
2395     organization.
2396 
2397     \sa organizationName applicationName applicationVersion
2398 */
setOrganizationDomain(const QString & orgDomain)2399 void QCoreApplication::setOrganizationDomain(const QString &orgDomain)
2400 {
2401     coreappdata()->orgDomain = orgDomain;
2402 }
2403 
organizationDomain()2404 QString QCoreApplication::organizationDomain()
2405 {
2406     return coreappdata()->orgDomain;
2407 }
2408 
2409 /*!
2410     \property QCoreApplication::applicationName
2411     \brief the name of this application
2412 
2413     The value is used by the QSettings class when it is constructed
2414     using the empty constructor. This saves having to repeat this
2415     information each time a QSettings object is created.
2416 
2417     On BlackBerry this property is read-only. It is obtained from the
2418     BAR application descriptor file.
2419 
2420     \sa organizationName organizationDomain applicationVersion
2421 */
setApplicationName(const QString & application)2422 void QCoreApplication::setApplicationName(const QString &application)
2423 {
2424     coreappdata()->application = application;
2425 }
2426 
applicationName()2427 QString QCoreApplication::applicationName()
2428 {
2429 #ifdef Q_OS_BLACKBERRY
2430     coreappdata()->loadManifest();
2431 #endif
2432 
2433     QString appname = coreappdata() ? coreappdata()->application : QString();
2434     if (appname.isEmpty() && QCoreApplication::self)
2435         appname = QCoreApplication::self->d_func()->appName();
2436 
2437     return appname;
2438 }
2439 
2440 /*!
2441     \property QCoreApplication::applicationVersion
2442     \since 4.4
2443     \brief the version of this application
2444 
2445     On BlackBerry this property is read-only. It is obtained from the
2446     BAR application descriptor file.
2447 
2448     \sa applicationName organizationName organizationDomain
2449 */
setApplicationVersion(const QString & version)2450 void QCoreApplication::setApplicationVersion(const QString &version)
2451 {
2452     coreappdata()->applicationVersion = version;
2453 }
2454 
applicationVersion()2455 QString QCoreApplication::applicationVersion()
2456 {
2457 #ifdef Q_OS_BLACKBERRY
2458     coreappdata()->loadManifest();
2459 #endif
2460     return coreappdata()->applicationVersion;
2461 }
2462 
2463 #ifndef QT_NO_LIBRARY
2464 
2465 #if defined(Q_OS_SYMBIAN)
qt_symbian_installLibraryPaths(QString installPathPlugins,QStringList & libPaths)2466 void qt_symbian_installLibraryPaths(QString installPathPlugins, QStringList& libPaths)
2467 {
2468     // Add existing path on all drives for relative PluginsPath in Symbian
2469     QString tempPath = installPathPlugins;
2470     if (tempPath.at(tempPath.length() - 1) != QDir::separator()) {
2471         tempPath += QDir::separator();
2472     }
2473     RFs& fs = qt_s60GetRFs();
2474     TPtrC tempPathPtr(reinterpret_cast<const TText*> (tempPath.constData()));
2475     // Symbian searches should start from Y:. Fix start drive otherwise TFindFile starts from the session drive
2476     _LIT(KStartDir, "Y:");
2477     TFileName dirPath(KStartDir);
2478     dirPath.Append(tempPathPtr);
2479     TFindFile finder(fs);
2480     TInt err = finder.FindByDir(tempPathPtr, dirPath);
2481     while (err == KErrNone) {
2482         QString foundDir(reinterpret_cast<const QChar *>(finder.File().Ptr()),
2483                          finder.File().Length());
2484         foundDir = QDir(foundDir).canonicalPath();
2485         if (!libPaths.contains(foundDir))
2486             libPaths.append(foundDir);
2487         err = finder.Find();
2488     }
2489 }
2490 #endif
2491 
2492 Q_GLOBAL_STATIC_WITH_ARGS(QMutex, libraryPathMutex, (QMutex::Recursive))
2493 
2494 /*!
2495     Returns a list of paths that the application will search when
2496     dynamically loading libraries.
2497 
2498     Qt provides default library paths, but they can also be set using
2499     a \l{Using qt.conf}{qt.conf} file. Paths specified in this file
2500     will override default values.
2501 
2502     This list will include the installation directory for plugins if
2503     it exists (the default installation directory for plugins is \c
2504     INSTALL/plugins, where \c INSTALL is the directory where Qt was
2505     installed).  The directory of the application executable (NOT the
2506     working directory) is always added, as well as the colon separated
2507     entries of the QT_PLUGIN_PATH environment variable.
2508 
2509     If you want to iterate over the list, you can use the \l foreach
2510     pseudo-keyword:
2511 
2512     \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 2
2513 
2514     \sa setLibraryPaths(), addLibraryPath(), removeLibraryPath(), QLibrary,
2515         {How to Create Qt Plugins}
2516 */
libraryPaths()2517 QStringList QCoreApplication::libraryPaths()
2518 {
2519     QMutexLocker locker(libraryPathMutex());
2520     if (!coreappdata()->app_libpaths) {
2521         QStringList *app_libpaths = coreappdata()->app_libpaths = new QStringList;
2522         QString installPathPlugins =  QLibraryInfo::location(QLibraryInfo::PluginsPath);
2523 #if defined(Q_OS_SYMBIAN)
2524         if (installPathPlugins.at(1) != QChar(QLatin1Char(':'))) {
2525             qt_symbian_installLibraryPaths(installPathPlugins, *app_libpaths);
2526         }
2527 #else
2528         if (QFile::exists(installPathPlugins)) {
2529             // Make sure we convert from backslashes to slashes.
2530             installPathPlugins = QDir(installPathPlugins).canonicalPath();
2531             if (!app_libpaths->contains(installPathPlugins))
2532                 app_libpaths->append(installPathPlugins);
2533         }
2534 #endif
2535 
2536         // If QCoreApplication is not yet instantiated,
2537         // make sure we add the application path when we construct the QCoreApplication
2538         if (self) self->d_func()->appendApplicationPathToLibraryPaths();
2539 
2540         const QByteArray libPathEnv = qgetenv("QT_PLUGIN_PATH");
2541         if (!libPathEnv.isEmpty()) {
2542 #if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
2543             QLatin1Char pathSep(';');
2544 #else
2545             QLatin1Char pathSep(':');
2546 #endif
2547             QStringList paths = QString::fromLatin1(libPathEnv).split(pathSep, QString::SkipEmptyParts);
2548             for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) {
2549                 QString canonicalPath = QDir(*it).canonicalPath();
2550                 if (!canonicalPath.isEmpty()
2551                     && !app_libpaths->contains(canonicalPath)) {
2552                     app_libpaths->append(canonicalPath);
2553                 }
2554             }
2555         }
2556     }
2557     return *(coreappdata()->app_libpaths);
2558 }
2559 
2560 
2561 
2562 /*!
2563 
2564     Sets the list of directories to search when loading libraries to
2565     \a paths. All existing paths will be deleted and the path list
2566     will consist of the paths given in \a paths.
2567 
2568     In Symbian this function is only useful for setting paths for
2569     finding Qt extension plugin stubs, since the OS can only
2570     load libraries from the \c{/sys/bin} directory.
2571 
2572     \sa libraryPaths(), addLibraryPath(), removeLibraryPath(), QLibrary
2573  */
setLibraryPaths(const QStringList & paths)2574 void QCoreApplication::setLibraryPaths(const QStringList &paths)
2575 {
2576     QMutexLocker locker(libraryPathMutex());
2577     if (!coreappdata()->app_libpaths)
2578         coreappdata()->app_libpaths = new QStringList;
2579     *(coreappdata()->app_libpaths) = paths;
2580     locker.unlock();
2581     QFactoryLoader::refreshAll();
2582 }
2583 
2584 /*!
2585   Prepends \a path to the beginning of the library path list, ensuring that
2586   it is searched for libraries first. If \a path is empty or already in the
2587   path list, the path list is not changed.
2588 
2589   The default path list consists of a single entry, the installation
2590   directory for plugins.  The default installation directory for plugins
2591   is \c INSTALL/plugins, where \c INSTALL is the directory where Qt was
2592   installed.
2593 
2594   In Symbian this function is only useful for adding paths for
2595   finding Qt extension plugin stubs, since the OS can only
2596   load libraries from the \c{/sys/bin} directory.
2597 
2598   \sa removeLibraryPath(), libraryPaths(), setLibraryPaths()
2599  */
addLibraryPath(const QString & path)2600 void QCoreApplication::addLibraryPath(const QString &path)
2601 {
2602     if (path.isEmpty())
2603         return;
2604 
2605     QMutexLocker locker(libraryPathMutex());
2606 
2607     // make sure that library paths is initialized
2608     libraryPaths();
2609 
2610     QString canonicalPath = QDir(path).canonicalPath();
2611     if (!canonicalPath.isEmpty()
2612         && !coreappdata()->app_libpaths->contains(canonicalPath)) {
2613         coreappdata()->app_libpaths->prepend(canonicalPath);
2614         locker.unlock();
2615         QFactoryLoader::refreshAll();
2616     }
2617 }
2618 
2619 /*!
2620     Removes \a path from the library path list. If \a path is empty or not
2621     in the path list, the list is not changed.
2622 
2623     \sa addLibraryPath(), libraryPaths(), setLibraryPaths()
2624 */
removeLibraryPath(const QString & path)2625 void QCoreApplication::removeLibraryPath(const QString &path)
2626 {
2627     if (path.isEmpty())
2628         return;
2629 
2630     QMutexLocker locker(libraryPathMutex());
2631 
2632     // make sure that library paths is initialized
2633     libraryPaths();
2634 
2635     QString canonicalPath = QDir(path).canonicalPath();
2636     coreappdata()->app_libpaths->removeAll(canonicalPath);
2637     QFactoryLoader::refreshAll();
2638 }
2639 
2640 #if defined(Q_OS_SYMBIAN)
rebuildInstallLibraryPaths()2641 void QCoreApplicationPrivate::rebuildInstallLibraryPaths()
2642 {
2643     // check there is not a single fixed install path
2644     QString nativeInstallPathPlugins =  QLibraryInfo::location(QLibraryInfo::PluginsPath);
2645     if (nativeInstallPathPlugins.at(1) == QChar(QLatin1Char(':')))
2646         return;
2647     QString installPathPlugins = QDir::cleanPath(nativeInstallPathPlugins);
2648     // look for the install path at the drive roots
2649     installPathPlugins.prepend(QChar(QLatin1Char(':')));
2650 
2651     QMutexLocker locker(libraryPathMutex());
2652     QStringList &app_libpaths = *coreappdata()->app_libpaths;
2653     // Build a new library path, copying non-installPath components, and replacing existing install path with new
2654     QStringList newPaths;
2655     bool installPathFound = false;
2656     foreach (QString path, app_libpaths) {
2657         if (path.mid(1).compare(installPathPlugins, Qt::CaseInsensitive) == 0) {
2658             // skip existing install paths, insert new install path when we find the first
2659             if (!installPathFound)
2660                 qt_symbian_installLibraryPaths(nativeInstallPathPlugins, newPaths);
2661             installPathFound = true;
2662         } else {
2663             newPaths.append(path);
2664         }
2665     }
2666     app_libpaths = newPaths;
2667 }
2668 #endif
2669 
2670 #endif //QT_NO_LIBRARY
2671 
2672 /*!
2673     \typedef QCoreApplication::EventFilter
2674 
2675     A function with the following signature that can be used as an
2676     event filter:
2677 
2678     \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 3
2679 
2680     \sa setEventFilter()
2681 */
2682 
2683 /*!
2684     \fn EventFilter QCoreApplication::setEventFilter(EventFilter filter)
2685 
2686     Replaces the event filter function for the QCoreApplication with
2687     \a filter and returns the pointer to the replaced event filter
2688     function. Only the current event filter function is called. If you
2689     want to use both filter functions, save the replaced EventFilter
2690     in a place where yours can call it.
2691 
2692     The event filter function set here is called for all messages
2693     received by all threads meant for all Qt objects. It is \e not
2694     called for messages that are not meant for Qt objects.
2695 
2696     The event filter function should return true if the message should
2697     be filtered, (i.e. stopped). It should return false to allow
2698     processing the message to continue.
2699 
2700     By default, no event filter function is set (i.e., this function
2701     returns a null EventFilter the first time it is called).
2702 
2703     \note The filter function set here receives native messages,
2704     i.e. MSG or XEvent structs, that are going to Qt objects. It is
2705     called by QCoreApplication::filterEvent(). If the filter function
2706     returns false to indicate the message should be processed further,
2707     the native message can then be translated into a QEvent and
2708     handled by the standard Qt \l{QEvent} {event} filering, e.g.
2709     QObject::installEventFilter().
2710 
2711     \note The filter function set here is different form the filter
2712     function set via QAbstractEventDispatcher::setEventFilter(), which
2713     gets all messages received by its thread, even messages meant for
2714     objects that are not handled by Qt.
2715 
2716     \sa QObject::installEventFilter(), QAbstractEventDispatcher::setEventFilter()
2717 */
2718 QCoreApplication::EventFilter
setEventFilter(QCoreApplication::EventFilter filter)2719 QCoreApplication::setEventFilter(QCoreApplication::EventFilter filter)
2720 {
2721     Q_D(QCoreApplication);
2722     EventFilter old = d->eventFilter;
2723     d->eventFilter = filter;
2724     return old;
2725 }
2726 
2727 /*!
2728     Sends \a message through the event filter that was set by
2729     setEventFilter(). If no event filter has been set, this function
2730     returns false; otherwise, this function returns the result of the
2731     event filter function in the \a result parameter.
2732 
2733     \sa setEventFilter()
2734 */
filterEvent(void * message,long * result)2735 bool QCoreApplication::filterEvent(void *message, long *result)
2736 {
2737     Q_D(QCoreApplication);
2738     if (result)
2739         *result = 0;
2740     if (d->eventFilter)
2741         return d->eventFilter(message, result);
2742 #ifdef Q_OS_WIN
2743     return winEventFilter(reinterpret_cast<MSG *>(message), result);
2744 #else
2745     return false;
2746 #endif
2747 }
2748 
2749 /*!
2750     This function returns true if there are pending events; otherwise
2751     returns false. Pending events can be either from the window
2752     system or posted events using postEvent().
2753 
2754     \sa QAbstractEventDispatcher::hasPendingEvents()
2755 */
hasPendingEvents()2756 bool QCoreApplication::hasPendingEvents()
2757 {
2758     QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
2759     if (eventDispatcher)
2760         return eventDispatcher->hasPendingEvents();
2761     return false;
2762 }
2763 
2764 #ifdef QT3_SUPPORT
2765 /*! \fn void QCoreApplication::lock()
2766 
2767     In Qt 3, this function locked the Qt library mutex, allowing
2768     non-GUI threads to perform basic printing operations using
2769     QPainter.
2770 
2771     In Qt 4, this is no longer supported, since painting is only
2772     supported from within a paint event handler. This function does
2773     nothing.
2774 
2775     \sa QWidget::paintEvent()
2776 */
2777 
2778 /*! \fn void QCoreApplication::unlock(bool wakeUpGui)
2779 
2780     In Qt 3, this function unlocked the Qt library mutex. The mutex
2781     allowed non-GUI threads to perform basic printing operations
2782     using QPainter.
2783 
2784     In Qt 4, this is no longer supported, since painting is only
2785     supported from within a paint event handler. This function does
2786     nothing.
2787 */
2788 
2789 /*! \fn bool QCoreApplication::locked()
2790 
2791     This function does nothing. It is there to keep old code working.
2792     It always returns false.
2793 
2794     See lock() for details.
2795 */
2796 
2797 /*! \fn bool QCoreApplication::tryLock()
2798 
2799     This function does nothing. It is there to keep old code working.
2800     It always returns false.
2801 
2802     See lock() for details.
2803 */
2804 
2805 /*! \fn void QCoreApplication::processOneEvent()
2806     \obsolete
2807 
2808     Waits for an event to occur, processes it, then returns.
2809 
2810     This function is useful for adapting Qt to situations where the
2811     event processing must be grafted onto existing program loops.
2812 
2813     Using this function in new applications may be an indication of design
2814     problems.
2815 
2816     \sa processEvents(), exec(), QTimer
2817 */
2818 
2819 /*! \obsolete
2820 
2821     This function enters the main event loop (recursively). Do not call
2822     it unless you really know what you are doing.
2823 */
enter_loop()2824 int QCoreApplication::enter_loop()
2825 {
2826     if (!QCoreApplicationPrivate::checkInstance("enter_loop"))
2827         return -1;
2828     if (QThreadData::current() != self->d_func()->threadData) {
2829         qWarning("QCoreApplication::enter_loop: Must be called from the main thread");
2830         return -1;
2831     }
2832     QEventLoop eventLoop;
2833     int returnCode = eventLoop.exec();
2834     return returnCode;
2835 }
2836 
2837 /*! \obsolete
2838 
2839     This function exits from a recursive call to the main event loop.
2840     Do not call it unless you are an expert.
2841 */
exit_loop()2842 void QCoreApplication::exit_loop()
2843 {
2844     if (!QCoreApplicationPrivate::checkInstance("exit_loop"))
2845         return;
2846     QThreadData *data = QThreadData::current();
2847     if (data != self->d_func()->threadData) {
2848         qWarning("QCoreApplication::exit_loop: Must be called from the main thread");
2849         return;
2850     }
2851     if (!data->eventLoops.isEmpty())
2852         data->eventLoops.top()->exit();
2853 }
2854 
2855 /*! \obsolete
2856 
2857     Returns the current loop level.
2858 */
loopLevel()2859 int QCoreApplication::loopLevel()
2860 {
2861     if (!QCoreApplicationPrivate::checkInstance("loopLevel"))
2862         return -1;
2863     return self->d_func()->threadData->eventLoops.size();
2864 }
2865 #endif
2866 
2867 /*
2868     \fn void QCoreApplication::watchUnixSignal(int signal, bool watch)
2869     \internal
2870 */
2871 
2872 /*!
2873     \fn void QCoreApplication::unixSignal(int number)
2874     \internal
2875 
2876     This signal is emitted whenever a Unix signal is received by the
2877     application. The Unix signal received is specified by its \a number.
2878 */
2879 
2880 /*!
2881     \fn void qAddPostRoutine(QtCleanUpFunction ptr)
2882     \relates QCoreApplication
2883 
2884     Adds a global routine that will be called from the QApplication
2885     destructor. This function is normally used to add cleanup routines
2886     for program-wide functionality.
2887 
2888     The function specified by \a ptr should take no arguments and should
2889     return nothing. For example:
2890 
2891     \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 4
2892 
2893     Note that for an application- or module-wide cleanup,
2894     qAddPostRoutine() is often not suitable. For example, if the
2895     program is split into dynamically loaded modules, the relevant
2896     module may be unloaded long before the QApplication destructor is
2897     called.
2898 
2899     For modules and libraries, using a reference-counted
2900     initialization manager or Qt's parent-child deletion mechanism may
2901     be better. Here is an example of a private class that uses the
2902     parent-child mechanism to call a cleanup function at the right
2903     time:
2904 
2905     \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 5
2906 
2907     By selecting the right parent object, this can often be made to
2908     clean up the module's data at the right moment.
2909 */
2910 
2911 /*!
2912     \macro Q_DECLARE_TR_FUNCTIONS(context)
2913     \relates QCoreApplication
2914 
2915     The Q_DECLARE_TR_FUNCTIONS() macro declares and implements two
2916     translation functions, \c tr() and \c trUtf8(), with these
2917     signatures:
2918 
2919     \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 6
2920 
2921     This macro is useful if you want to use QObject::tr() or
2922     QObject::trUtf8() in classes that don't inherit from QObject.
2923 
2924     Q_DECLARE_TR_FUNCTIONS() must appear at the very top of the
2925     class definition (before the first \c{public:} or \c{protected:}).
2926     For example:
2927 
2928     \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 7
2929 
2930     The \a context parameter is normally the class name, but it can
2931     be any string.
2932 
2933     \sa Q_OBJECT, QObject::tr(), QObject::trUtf8()
2934 */
2935 
2936 QT_END_NAMESPACE
2937