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