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