00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "qcoreapplication.h"
00025 #include "qcoreapplication_p.h"
00026
00027 #include "qabstracteventdispatcher.h"
00028 #include "qcoreevent.h"
00029 #include "qeventloop.h"
00030 #include <qdatastream.h>
00031 #include <qdatetime.h>
00032 #include <qdebug.h>
00033 #include <qdir.h>
00034 #include <qfile.h>
00035 #include <qfileinfo.h>
00036 #include <qhash.h>
00037 #include <private/qprocess_p.h>
00038 #include <qtextcodec.h>
00039 #include <qthread.h>
00040 #include <qthreadstorage.h>
00041 #include <private/qthread_p.h>
00042 #include <qlibraryinfo.h>
00043
00044 #ifdef Q_OS_UNIX
00045
00046 # if !defined(QT_NO_GLIB)
00047 # include "qeventdispatcher_glib_p.h"
00048 # endif
00049 # include "qeventdispatcher_unix_p.h"
00050 #endif
00051 #ifdef Q_OS_WIN
00052 # include "qeventdispatcher_win_p.h"
00053 #endif
00054
00055 #include <stdlib.h>
00056 #ifdef Q_OS_UNIX
00057 #include <locale.h>
00058 #endif
00059
00060 #if defined(Q_WS_WIN) || defined(Q_WS_MAC)
00061 extern QString qAppFileName();
00062 #endif
00063
00064 #if !defined(Q_OS_WIN)
00065 QString QCoreApplicationPrivate::appName() const
00066 {
00067 static QString applName;
00068 if (applName.isEmpty() && argv[0]) {
00069 char *p = strrchr(argv[0], '/');
00070 applName = QString::fromLocal8Bit(p ? p + 1 : argv[0]);
00071 }
00072 return applName;
00073 }
00074 #endif
00075
00076 bool QCoreApplicationPrivate::checkInstance(const char *function)
00077 {
00078 bool b = (QCoreApplication::self != 0);
00079 if (!b)
00080 qWarning("QApplication::%s: Please instantiate the QApplication object first", function);
00081 return b;
00082 }
00083
00084
00085
00086 QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set = { 0, 0, 0, 0 };
00087
00088 void qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set)
00089 {
00090 qt_signal_spy_callback_set = callback_set;
00091 }
00092
00093 extern "C" void Q_CORE_EXPORT qt_startup_hook()
00094 {
00095 }
00096
00097 typedef QList<QtCleanUpFunction> QVFuncList;
00098 Q_GLOBAL_STATIC(QVFuncList, postRList)
00099
00100 void qAddPostRoutine(QtCleanUpFunction p)
00101 {
00102 QVFuncList *list = postRList();
00103 if (!list)
00104 return;
00105 list->prepend(p);
00106 }
00107
00108 void qRemovePostRoutine(QtCleanUpFunction p)
00109 {
00110 QVFuncList *list = postRList();
00111 if (!list)
00112 return;
00113 list->removeAll(p);
00114 }
00115
00116 void Q_CORE_EXPORT qt_call_post_routines()
00117 {
00118 QVFuncList *list = postRList();
00119 if (!list)
00120 return;
00121 while (!list->isEmpty())
00122 (list->takeFirst())();
00123 }
00124
00125
00126
00127 bool QCoreApplicationPrivate::is_app_running = false;
00128
00129 bool QCoreApplicationPrivate::is_app_closing = false;
00130
00131
00132 Q_CORE_EXPORT uint qGlobalPostedEventsCount()
00133 {
00134 return QThreadData::current()->postEventList.size();
00135 }
00136
00137
00138 void qt_set_current_thread_to_main_thread()
00139 {
00140 QCoreApplicationPrivate::theMainThread = QThread::currentThread();
00141 }
00142
00143
00144
00145 QCoreApplication *QCoreApplication::self = 0;
00146 QAbstractEventDispatcher *QCoreApplicationPrivate::eventDispatcher = 0;
00147 uint QCoreApplicationPrivate::attribs;
00148
00149 #ifdef Q_OS_UNIX
00150 Qt::HANDLE qt_application_thread_id = 0;
00151 #endif
00152
00153 struct QCoreApplicationData {
00154 QCoreApplicationData() {
00155 #ifndef QT_NO_LIBRARY
00156 app_libpaths = 0;
00157 #endif
00158 }
00159 ~QCoreApplicationData() {
00160 #ifndef QT_NO_LIBRARY
00161 delete app_libpaths;
00162 #endif
00163 }
00164 QString orgName, orgDomain, application;
00165
00166 #ifndef QT_NO_LIBRARY
00167 QStringList *app_libpaths;
00168 #endif
00169
00170 };
00171
00172 Q_GLOBAL_STATIC(QCoreApplicationData, coreappdata)
00173
00174 QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv)
00175 : QObjectPrivate(), argc(aargc), argv(aargv), application_type(0), eventFilter(0),
00176 in_exec(false)
00177 {
00178 static const char *const empty = "";
00179 if (argc == 0 || argv == 0) {
00180 argc = 0;
00181 argv = (char **)∅
00182 }
00183 QCoreApplicationPrivate::is_app_closing = false;
00184
00185 #ifdef Q_OS_UNIX
00186 qt_application_thread_id = QThread::currentThreadId();
00187 #endif
00188
00189
00190 if (QThread::currentThread() != theMainThread)
00191 qWarning("WARNING: QApplication was not created in the main() thread.");
00192 }
00193
00194 QCoreApplicationPrivate::~QCoreApplicationPrivate()
00195 {
00196 #ifndef QT_NO_THREAD
00197 QThreadStorageData::finish(threadData->tls);
00198 threadData->tls = 0;
00199 #endif
00200
00201
00202 QMutexLocker locker(&threadData->postEventList.mutex);
00203 for (int i = 0; i < threadData->postEventList.size(); ++i) {
00204 const QPostEvent &pe = threadData->postEventList.at(i);
00205 if (pe.event) {
00206 --pe.receiver->d_func()->postedEvents;
00207 #ifdef QT3_SUPPORT
00208 if (pe.event->type() == QEvent::ChildInserted)
00209 --pe.receiver->d_func()->postedChildInsertedEvents;
00210 #endif
00211 pe.event->posted = false;
00212 delete pe.event;
00213 }
00214 }
00215 threadData->postEventList.clear();
00216 threadData->postEventList.recursion = 0;
00217 threadData->quitNow = false;
00218 }
00219
00220 void QCoreApplicationPrivate::createEventDispatcher()
00221 {
00222 Q_Q(QCoreApplication);
00223 #if defined(Q_OS_UNIX)
00224 # if !defined(QT_NO_GLIB)
00225 if (qgetenv("QT_NO_GLIB").isEmpty())
00226 eventDispatcher = new QEventDispatcherGlib(q);
00227 else
00228 # endif
00229 eventDispatcher = new QEventDispatcherUNIX(q);
00230 #elif defined(Q_OS_WIN)
00231 eventDispatcher = new QEventDispatcherWin32(q);
00232 #else
00233 # error "QEventDispatcher not yet ported to this platform"
00234 #endif
00235 }
00236
00237 QThread *QCoreApplicationPrivate::theMainThread = 0;
00238 QThread *QCoreApplicationPrivate::mainThread()
00239 {
00240 Q_ASSERT(theMainThread != 0);
00241 return theMainThread;
00242 }
00243
00244 #ifdef QT3_SUPPORT
00245 void QCoreApplicationPrivate::removePostedChildInsertedEvents(QObject *receiver, QObject *child)
00246 {
00247 QThreadData *data = receiver->d_func()->threadData;
00248 QMutexLocker locker(&data->postEventList.mutex);
00249
00250
00251
00252
00253
00254
00255
00256
00257 for (int i = 0; i < data->postEventList.size(); ++i) {
00258 const QPostEvent &pe = data->postEventList.at(i);
00259 if (pe.event && pe.receiver == receiver) {
00260 if (pe.event->type() == QEvent::ChildInserted
00261 && ((QChildEvent*)pe.event)->child() == child) {
00262 --receiver->d_func()->postedEvents;
00263 --receiver->d_func()->postedChildInsertedEvents;
00264 Q_ASSERT(receiver->d_func()->postedEvents >= 0);
00265 Q_ASSERT(receiver->d_func()->postedChildInsertedEvents >= 0);
00266 pe.event->posted = false;
00267 delete pe.event;
00268 const_cast<QPostEvent &>(pe).event = 0;
00269 const_cast<QPostEvent &>(pe).receiver = 0;
00270 }
00271 }
00272 }
00273 }
00274 #endif
00275
00276 void QCoreApplicationPrivate::checkReceiverThread(QObject *receiver)
00277 {
00278 QThread *currentThread = QThread::currentThread();
00279 QThread *thr = receiver->thread();
00280 Q_ASSERT_X(currentThread == thr || !thr,
00281 "QCoreApplication::sendEvent",
00282 QString::fromLatin1("Cannot send events to objects owned by a different thread. "
00283 "Current thread %1. Receiver '%2' (of type '%3') was created in thread %4")
00284 .arg(QString::number((ulong) currentThread, 16))
00285 .arg(receiver->objectName())
00286 .arg(QLatin1String(receiver->metaObject()->className()))
00287 .arg(QString::number((ulong) thr, 16))
00288 .toLocal8Bit().data());
00289 Q_UNUSED(currentThread);
00290 Q_UNUSED(thr);
00291 }
00292
00293 void QCoreApplicationPrivate::appendApplicationPathToLibraryPaths()
00294 {
00295 #ifndef QT_NO_LIBRARY
00296 QStringList *app_libpaths = coreappdata()->app_libpaths;
00297 Q_ASSERT(app_libpaths);
00298 QString app_location( QCoreApplication::applicationFilePath() );
00299 app_location.truncate(app_location.lastIndexOf(QLatin1Char('/')));
00300 app_location = QDir(app_location).canonicalPath();
00301 if (app_location != QLibraryInfo::location(QLibraryInfo::PluginsPath) && QFile::exists(app_location))
00302 app_libpaths->append(app_location);
00303 #endif
00304 }
00305
00306 QString qAppName()
00307 {
00308 if (!QCoreApplicationPrivate::checkInstance("qAppName"))
00309 return QString();
00310 return QCoreApplication::instance()->d_func()->appName();
00311 }
00312
00372 QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)
00373 : QObject(p, 0)
00374 {
00375 init();
00376
00377
00378 }
00379
00391 void QCoreApplication::flush()
00392 {
00393 if (self && self->d_func()->eventDispatcher)
00394 self->d_func()->eventDispatcher->flush();
00395 }
00396
00406 QCoreApplication::QCoreApplication(int &argc, char **argv)
00407 : QObject(*new QCoreApplicationPrivate(argc, argv))
00408 {
00409 init();
00410 QCoreApplicationPrivate::eventDispatcher->startingUp();
00411 }
00412
00413 extern void set_winapp_name();
00414
00415
00416 void QCoreApplication::init()
00417 {
00418 Q_D(QCoreApplication);
00419
00420 #ifdef Q_OS_UNIX
00421 setlocale(LC_ALL, "");
00422 setlocale(LC_NUMERIC, "C");
00423 #endif
00424
00425 #ifdef Q_WS_WIN
00426
00427 set_winapp_name();
00428 #endif
00429
00430 Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
00431 QCoreApplication::self = this;
00432
00433 #ifndef QT_NO_THREAD
00434 QThread::initialize();
00435 #endif
00436
00437
00438 if (!QCoreApplicationPrivate::eventDispatcher)
00439 QCoreApplicationPrivate::eventDispatcher = d->threadData->eventDispatcher;
00440
00441 if (!QCoreApplicationPrivate::eventDispatcher)
00442 d->createEventDispatcher();
00443 Q_ASSERT(QCoreApplicationPrivate::eventDispatcher != 0);
00444
00445 if (!QCoreApplicationPrivate::eventDispatcher->parent())
00446 QCoreApplicationPrivate::eventDispatcher->moveToThread(d->threadData->thread);
00447
00448 d->threadData->eventDispatcher = QCoreApplicationPrivate::eventDispatcher;
00449
00450 #ifndef QT_NO_LIBRARY
00451 if (!coreappdata()->app_libpaths) {
00452
00453 libraryPaths();
00454 } else {
00455 d->appendApplicationPathToLibraryPaths();
00456 }
00457 #endif
00458
00459 #if defined(Q_OS_UNIX) && !(defined(QT_NO_PROCESS))
00460
00461
00462 QProcessPrivate::initializeProcessManager();
00463 #endif
00464
00465 #ifdef QT_EVAL
00466 extern void qt_core_eval_init(uint);
00467 qt_core_eval_init(d->application_type);
00468 #endif
00469
00470 qt_startup_hook();
00471 }
00472
00476 QCoreApplication::~QCoreApplication()
00477 {
00478 qt_call_post_routines();
00479
00480 self = 0;
00481 QCoreApplicationPrivate::is_app_closing = true;
00482 QCoreApplicationPrivate::is_app_running = false;
00483
00484 #ifndef QT_NO_THREAD
00485 QThread::cleanup();
00486 #endif
00487
00488 d_func()->threadData->eventDispatcher = 0;
00489 if (QCoreApplicationPrivate::eventDispatcher)
00490 QCoreApplicationPrivate::eventDispatcher->closingDown();
00491 QCoreApplicationPrivate::eventDispatcher = 0;
00492 }
00493
00494
00501 void QCoreApplication::setAttribute(Qt::ApplicationAttribute attribute, bool on)
00502 {
00503 if (on)
00504 QCoreApplicationPrivate::attribs |= 1 << attribute;
00505 else
00506 QCoreApplicationPrivate::attribs &= ~(1 << attribute);
00507 }
00508
00515 bool QCoreApplication::testAttribute(Qt::ApplicationAttribute attribute)
00516 {
00517 return QCoreApplicationPrivate::testAttribute(attribute);
00518 }
00519
00520
00521
00559 bool QCoreApplication::notify(QObject *receiver, QEvent *event)
00560 {
00561 Q_D(QCoreApplication);
00562
00563 if (QCoreApplicationPrivate::is_app_closing)
00564 return true;
00565
00566 if (receiver == 0) {
00567 qWarning("QCoreApplication::notify: Unexpected null receiver");
00568 return true;
00569 }
00570
00571 d->checkReceiverThread(receiver);
00572
00573 #ifdef QT3_SUPPORT
00574 if (event->type() == QEvent::ChildRemoved && receiver->d_func()->postedChildInsertedEvents)
00575 d->removePostedChildInsertedEvents(receiver, static_cast<QChildEvent *>(event)->child());
00576 #endif // QT3_SUPPORT
00577
00578 return receiver->isWidgetType() ? false : d->notify_helper(receiver, event);
00579 }
00580
00585 bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
00586 {
00587 Q_Q(QCoreApplication);
00588
00589 QReadWriteLock *lock = QObjectPrivate::readWriteLock();
00590 if (lock)
00591 lock->lockForRead();
00592
00593
00594 for (int i = 0; i < eventFilters.size(); ++i) {
00595 register QObject *obj = eventFilters.at(i);
00596 if (lock)
00597 lock->unlock();
00598 if (obj && obj->eventFilter(receiver, event))
00599 return true;
00600 if (lock)
00601 lock->lockForRead();
00602 }
00603
00604
00605 if (receiver != q) {
00606 for (int i = 0; i < receiver->d_func()->eventFilters.size(); ++i) {
00607 register QObject *obj = receiver->d_func()->eventFilters.at(i);
00608 if (lock)
00609 lock->unlock();
00610 if (obj && obj->eventFilter(receiver, event))
00611 return true;
00612 if (lock)
00613 lock->lockForRead();
00614 }
00615 }
00616
00617 if (lock)
00618 lock->unlock();
00619
00620 return receiver->event(event);
00621 }
00622
00630 bool QCoreApplication::startingUp()
00631 {
00632 return !QCoreApplicationPrivate::is_app_running;
00633 }
00634
00642 bool QCoreApplication::closingDown()
00643 {
00644 return QCoreApplicationPrivate::is_app_closing;
00645 }
00646
00647
00657 void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
00658 {
00659 QThreadData *data = QThreadData::current();
00660 if (!data->eventDispatcher)
00661 return;
00662 data->eventDispatcher->processEvents(flags);
00663 }
00664
00676 void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime)
00677 {
00678 QThreadData *data = QThreadData::current();
00679 if (!data->eventDispatcher)
00680 return;
00681 QTime start;
00682 start.start();
00683 while (data->eventDispatcher->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
00684 if (start.elapsed() > maxtime)
00685 break;
00686 }
00687 }
00688
00689
00690
00691
00692
00709 int QCoreApplication::exec()
00710 {
00711 if (!QCoreApplicationPrivate::checkInstance("exec"))
00712 return -1;
00713
00714 QThreadData *threadData = self->d_func()->threadData;
00715 if (threadData != QThreadData::current()) {
00716 qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
00717 return -1;
00718 }
00719 if (!threadData->eventLoops.isEmpty()) {
00720 qWarning("QCoreApplication::exec: The event loop is already running");
00721 return -1;
00722 }
00723
00724 threadData->quitNow = false;
00725 QEventLoop eventLoop;
00726 self->d_func()->in_exec = true;
00727 int returnCode = eventLoop.exec();
00728 threadData->quitNow = false;
00729 if (self) {
00730 self->d_func()->in_exec = false;
00731 emit self->aboutToQuit();
00732 sendPostedEvents(0, QEvent::DeferredDelete);
00733 }
00734 return returnCode;
00735 }
00736
00753 void QCoreApplication::exit(int returnCode)
00754 {
00755 if (!self)
00756 return;
00757 QThreadData *data = self->d_func()->threadData;
00758 data->quitNow = true;
00759 for (int i = 0; i < data->eventLoops.size(); ++i) {
00760 QEventLoop *eventLoop = data->eventLoops.at(i);
00761 eventLoop->exit(returnCode);
00762 }
00763 }
00764
00765
00766
00767
00768
00803 void QCoreApplication::postEvent(QObject *receiver, QEvent *event)
00804 {
00805 if (receiver == 0) {
00806 qWarning("QCoreApplication::postEvent: Unexpected null receiver");
00807 delete event;
00808 return;
00809 }
00810
00811 QReadLocker locker(QObjectPrivate::readWriteLock());
00812 if (!QObjectPrivate::isValidObject(receiver)) {
00813 qWarning("QCoreApplication::postEvent: Receiver is not a valid QObject");
00814 delete event;
00815 return;
00816 }
00817
00818 QThreadData *data = receiver->d_func()->threadData;
00819 if (!data) {
00820
00821 delete event;
00822 return;
00823 }
00824
00825 {
00826 QMutexLocker locker(&data->postEventList.mutex);
00827
00828
00829 if (receiver->d_func()->postedEvents
00830 && self && self->compressEvent(event, receiver, &data->postEventList)) {
00831 delete event;
00832 return;
00833 }
00834
00835 event->posted = true;
00836 ++receiver->d_func()->postedEvents;
00837 #ifdef QT3_SUPPORT
00838 if (event->type() == QEvent::ChildInserted)
00839 ++receiver->d_func()->postedChildInsertedEvents;
00840 #endif
00841 if (event->type() == QEvent::DeferredDelete) {
00842 if (!data->eventLoops.isEmpty()) {
00843
00844 for (int i = data->eventLoops.size() - 1; i >= 0; --i) {
00845 QEventLoop *eventLoop = data->eventLoops.at(i);
00846 if (eventLoop->isRunning()) {
00847 event->d = reinterpret_cast<QEventPrivate *>(eventLoop);
00848 break;
00849 }
00850 }
00851 }
00852 }
00853 data->postEventList.append(QPostEvent(receiver, event));
00854 data->canWait = false;
00855 }
00856
00857 if (data->eventDispatcher)
00858 data->eventDispatcher->wakeUp();
00859 }
00860
00865 bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents)
00866 {
00867 #ifdef Q_WS_WIN
00868 Q_ASSERT(event);
00869 Q_ASSERT(receiver);
00870 Q_ASSERT(postedEvents);
00871
00872
00873 if (event->type() == QEvent::Timer && receiver->d_func()->postedEvents > 0) {
00874 int timerId = ((QTimerEvent *) event)->timerId();
00875 for (int i=0; i<postedEvents->size(); ++i) {
00876 const QPostEvent &e = postedEvents->at(i);
00877 if (e.receiver == receiver && e.event && e.event->type() == QEvent::Timer
00878 && ((QTimerEvent *) e.event)->timerId() == timerId)
00879 return true;
00880 }
00881 }
00882 #else
00883 Q_UNUSED(event);
00884 Q_UNUSED(receiver);
00885 Q_UNUSED(postedEvents);
00886 #endif
00887
00888 return false;
00889 }
00890
00912 void QCoreApplication::sendPostedEvents(QObject *receiver, int event_type)
00913 {
00914 bool doDeferredDeletion = (event_type == QEvent::DeferredDelete);
00915 if (event_type == -1) {
00916
00917 doDeferredDeletion = true;
00918 event_type = 0;
00919 }
00920
00921 QThreadData *data = QThreadData::current();
00922
00923 if (receiver && receiver->d_func()->threadData != data) {
00924 qWarning("QCoreApplication::sendPostedEvents: Cannot send "
00925 "posted events for objects in another thread");
00926 return;
00927 }
00928
00929 ++data->postEventList.recursion;
00930
00931 #ifdef QT3_SUPPORT
00932
00933 if (receiver && event_type == QEvent::ChildInserted
00934 && !receiver->d_func()->postedChildInsertedEvents) {
00935 --data->postEventList.recursion;
00936 return;
00937 }
00938
00939
00940 if (receiver == 0 && event_type == 0)
00941 sendPostedEvents(0, QEvent::ChildInserted);
00942 #endif
00943
00944 QMutexLocker locker(&data->postEventList.mutex);
00945
00946
00947
00948
00949 data->canWait = (data->postEventList.size() == 0);
00950
00951 if (data->postEventList.size() == 0 || (receiver && !receiver->d_func()->postedEvents)) {
00952 --data->postEventList.recursion;
00953 return;
00954 }
00955
00956 data->canWait = true;
00957
00958
00959
00960 int i = 0;
00961 const int s = data->postEventList.size();
00962 while (i < data->postEventList.size()) {
00963
00964 if (i >= s)
00965 break;
00966
00967 const QPostEvent &pe = data->postEventList.at(i);
00968 ++i;
00969
00970 if (!pe.event)
00971 continue;
00972 if ((receiver && receiver != pe.receiver) || (event_type && event_type != pe.event->type())) {
00973 data->canWait = false;
00974 continue;
00975 }
00976
00977 if (pe.event->type() == QEvent::DeferredDelete) {
00978 const QEventLoop *const savedEventLoop = reinterpret_cast<QEventLoop *>(pe.event->d);
00979 const QEventLoop *const currentEventLoop =
00980 data->eventLoops.isEmpty() ? 0 : data->eventLoops.top();
00981
00982
00983
00984
00985
00986 if (!doDeferredDeletion || (currentEventLoop && savedEventLoop && savedEventLoop != currentEventLoop)) {
00987
00988 if (!event_type && !receiver) {
00989
00990 data->postEventList.append(pe);
00991 const_cast<QPostEvent &>(pe).event = 0;
00992 }
00993 continue;
00994 }
00995 }
00996
00997
00998
00999 pe.event->posted = false;
01000 QEvent * e = pe.event;
01001 QObject * r = pe.receiver;
01002
01003 --r->d_func()->postedEvents;
01004 Q_ASSERT(r->d_func()->postedEvents >= 0);
01005 #ifdef QT3_SUPPORT
01006 if (e->type() == QEvent::ChildInserted)
01007 --r->d_func()->postedChildInsertedEvents;
01008 Q_ASSERT(r->d_func()->postedChildInsertedEvents >= 0);
01009 #endif
01010
01011
01012
01013 const_cast<QPostEvent &>(pe).event = 0;
01014
01015 locker.unlock();
01016
01017 #ifdef QT_NO_EXCEPTIONS
01018 QCoreApplication::sendEvent(r, e);
01019 #else
01020 try {
01021 QCoreApplication::sendEvent(r, e);
01022 } catch (...) {
01023 locker.relock();
01024 delete e;
01025
01026
01027 data->canWait = false;
01028
01029
01030 --data->postEventList.recursion;
01031 if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
01032 data->eventDispatcher->wakeUp();
01033 throw;
01034 }
01035 #endif
01036
01037 locker.relock();
01038
01039 delete e;
01040
01041
01042
01043 }
01044
01045 --data->postEventList.recursion;
01046 if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
01047 data->eventDispatcher->wakeUp();
01048
01049
01050
01051 if (!data->postEventList.recursion && !event_type && !receiver) {
01052 const QPostEventList::iterator it = data->postEventList.begin();
01053 data->postEventList.erase(it, it + i);
01054 }
01055 }
01056
01068
01069
01070 void QCoreApplication::removePostedEvents(QObject *receiver)
01071 {
01072 #ifdef PAUL_TESTING
01073 QThreadData *data = receiver ? receiver->d_func()->threadData : self->d_func()->threadData;
01074 #else
01075 if (!receiver)
01076 return;
01077
01078 QThreadData *data = receiver->d_func()->threadData;
01079 #endif
01080
01081 QMutexLocker locker(&data->postEventList.mutex);
01082
01083
01084
01085
01086
01087 #ifdef PAUL_TESTING
01088 if (receiver && !receiver->d_func()->postedEvents) return;
01089 #else
01090 if (!receiver->d_func()->postedEvents) return;
01091 #endif
01092 int n = data->postEventList.size();
01093 int j = 0;
01094
01095 #ifdef PAUL_TESTING
01096 if (!receiver) {
01097 for (int i = 0; i < n; ++i) {
01098 const QPostEvent &pe = data->postEventList.at(i);
01099 if (pe.event) {
01100 --pe.receiver->d_func()->postedEvents;
01101 #ifdef QT3_SUPPORT
01102 if (pe.event->type() == QEvent::ChildInserted)
01103 --pe.receiver->d_func()->postedChildInsertedEvents;
01104 #endif
01105 pe.event->posted = false;
01106 delete pe.event;
01107 const_cast<QPostEvent &>(pe).event = 0;
01108
01109 }
01110 }
01111 data->postEventList.clear();
01112 return;
01113 }
01114 #endif
01115
01116 for (int i = 0; i < n; ++i) {
01117 const QPostEvent &pe = data->postEventList.at(i);
01118 if (pe.receiver == receiver) {
01119 if (pe.event) {
01120 --receiver->d_func()->postedEvents;
01121 #ifdef QT3_SUPPORT
01122 if (pe.event->type() == QEvent::ChildInserted)
01123 --receiver->d_func()->postedChildInsertedEvents;
01124 #endif
01125 pe.event->posted = false;
01126 delete pe.event;
01127 const_cast<QPostEvent &>(pe).event = 0;
01128 }
01129 } else if (!data->postEventList.recursion) {
01130 if (i != j)
01131 data->postEventList.swap(i, j);
01132 ++j;
01133 }
01134 }
01135
01136 Q_ASSERT(!receiver->d_func()->postedEvents);
01137 #ifdef QT3_SUPPORT
01138 Q_ASSERT(!receiver->d_func()->postedChildInsertedEvents);
01139 #endif
01140 if (!data->postEventList.recursion) {
01141 while (j++ < n)
01142 data->postEventList.removeLast();
01143 }
01144 }
01145
01146
01157 void QCoreApplicationPrivate::removePostedEvent(QEvent * event)
01158 {
01159 if (!event || !event->posted)
01160 return;
01161
01162 QThreadData *data = QThreadData::current();
01163
01164 QMutexLocker locker(&data->postEventList.mutex);
01165
01166 if (data->postEventList.size() == 0) {
01167 #if defined(QT_DEBUG)
01168 qDebug("QCoreApplication::removePostedEvent: Internal error: %p %d is posted",
01169 (void*)event, event->type());
01170 return;
01171 #endif
01172 }
01173
01174 for (int i = 0; i < data->postEventList.size(); ++i) {
01175 const QPostEvent & pe = data->postEventList.at(i);
01176 if (pe.event == event) {
01177 #ifndef QT_NO_DEBUG
01178 qWarning("QCoreApplication::removePostedEvent: Event of type %d deleted while posted to %s %s",
01179 event->type(),
01180 pe.receiver->metaObject()->className(),
01181 pe.receiver->objectName().toLocal8Bit().data());
01182 #endif
01183 --pe.receiver->d_func()->postedEvents;
01184 #ifdef QT3_SUPPORT
01185 if (pe.event->type() == QEvent::ChildInserted)
01186 --pe.receiver->d_func()->postedChildInsertedEvents;
01187 #endif
01188 pe.event->posted = false;
01189 delete pe.event;
01190 const_cast<QPostEvent &>(pe).event = 0;
01191 return;
01192 }
01193 }
01194 }
01195
01199 bool QCoreApplication::event(QEvent *e)
01200 {
01201 if (e->type() == QEvent::Quit) {
01202 quit();
01203 return true;
01204 }
01205 return QObject::event(e);
01206 }
01207
01240 void QCoreApplication::quit()
01241 {
01242 exit(0);
01243 }
01244
01260 #ifndef QT_NO_TRANSLATION
01261
01273 void QCoreApplication::installTranslator(QTranslator *translationFile)
01274 {
01275 if (!translationFile)
01276 return;
01277
01278 if (!QCoreApplicationPrivate::checkInstance("installTranslator"))
01279 return;
01280 QCoreApplicationPrivate *d = self->d_func();
01281 d->translators.prepend(translationFile);
01282
01283 #ifndef QT_NO_TRANSLATION_BUILDER
01284 if (translationFile->isEmpty())
01285 return;
01286 #endif
01287
01288 QEvent ev(QEvent::LanguageChange);
01289 QCoreApplication::sendEvent(self, &ev);
01290 }
01291
01300 void QCoreApplication::removeTranslator(QTranslator *translationFile)
01301 {
01302 if (!translationFile)
01303 return;
01304 if (!QCoreApplicationPrivate::checkInstance("removeTranslator"))
01305 return;
01306 QCoreApplicationPrivate *d = self->d_func();
01307 if (d->translators.removeAll(translationFile) && !self->closingDown()) {
01308 QEvent ev(QEvent::LanguageChange);
01309 QCoreApplication::sendEvent(self, &ev);
01310 }
01311 }
01312
01316 QString QCoreApplication::translate(const char *context, const char *sourceText,
01317 const char *comment, Encoding encoding)
01318 {
01319 return translate(context, sourceText, comment, encoding, -1);
01320 }
01321
01363 QString QCoreApplication::translate(const char *context, const char *sourceText,
01364 const char *comment, Encoding encoding, int n)
01365 {
01366 QString result;
01367
01368 if (!sourceText)
01369 return result;
01370
01371 if (self && !self->d_func()->translators.isEmpty()) {
01372 QList<QTranslator*>::ConstIterator it;
01373 QTranslator *translationFile;
01374 for (it = self->d_func()->translators.constBegin(); it != self->d_func()->translators.constEnd(); ++it) {
01375 translationFile = *it;
01376 result = translationFile->translate(context, sourceText, comment, n);
01377 if (!result.isEmpty())
01378 break;
01379 }
01380 }
01381
01382 if (result.isEmpty()) {
01383 #ifdef QT_NO_TEXTCODEC
01384 Q_UNUSED(encoding)
01385 #else
01386 if (encoding == UnicodeUTF8)
01387 result = QString::fromUtf8(sourceText);
01388 else if (QTextCodec::codecForTr() != 0)
01389 result = QTextCodec::codecForTr()->toUnicode(sourceText);
01390 else
01391 #endif
01392 result = QString::fromLatin1(sourceText);
01393 }
01394
01395 if (n >= 0) {
01396 int percentPos = -1;
01397 while ((percentPos = result.indexOf(QLatin1Char('%'), percentPos + 1)) != -1) {
01398 int len = 1;
01399 QString fmt(QLatin1String("%1"));
01400 if (result.mid(percentPos + len, 1).startsWith(QLatin1Char('L'))) {
01401 ++len;
01402 fmt = QLatin1String("%L1");
01403 }
01404 if (result.mid(percentPos + len, 1).startsWith(QLatin1Char('n'))) {
01405 ++len;
01406 result.replace(percentPos, len, fmt.arg(n));
01407 }
01408 }
01409 }
01410 return result;
01411 }
01412
01413 bool QCoreApplicationPrivate::isTranslatorInstalled(QTranslator *translator)
01414 {
01415 return QCoreApplication::self
01416 && QCoreApplication::self->d_func()->translators.contains(translator);
01417 }
01418
01419 #endif //QT_NO_TRANSLATE
01420
01438 QString QCoreApplication::applicationDirPath()
01439 {
01440 if (!self) {
01441 qWarning("QCoreApplication::applicationDirPath: Please instantiate the QApplication object first");
01442 return QString();
01443 }
01444 return QFileInfo(applicationFilePath()).path();
01445 }
01446
01460 QString QCoreApplication::applicationFilePath()
01461 {
01462 if (!self) {
01463 qWarning("QCoreApplication::applicationFilePath: Please instantiate the QApplication object first");
01464 return QString();
01465 }
01466 #if defined( Q_WS_WIN )
01467 QFileInfo filePath;
01468 QT_WA({
01469 wchar_t module_name[256];
01470 GetModuleFileNameW(0, module_name, sizeof(module_name) / sizeof(wchar_t));
01471 filePath = QString::fromUtf16((ushort *)module_name);
01472 }, {
01473 char module_name[256];
01474 GetModuleFileNameA(0, module_name, sizeof(module_name));
01475 filePath = QString::fromLocal8Bit(module_name);
01476 });
01477
01478 return filePath.filePath();
01479 #elif defined(Q_WS_MAC)
01480 QFileInfo fi(qAppFileName());
01481 return fi.exists() ? fi.canonicalFilePath() : QString();
01482 #else
01483 # ifdef Q_OS_LINUX
01484
01485
01486 QFileInfo pfi(QString::fromLatin1("/proc/%1/exe").arg(getpid()));
01487 if (pfi.exists() && pfi.isSymLink())
01488 return pfi.canonicalFilePath();
01489 # endif
01490
01491 QString argv0 = QFile::decodeName(QByteArray(argv()[0]));
01492 QString absPath;
01493
01494 if (!argv0.isEmpty() && argv0.at(0) == QLatin1Char('/')) {
01495
01496
01497
01498
01499 absPath = argv0;
01500 } else if (argv0.contains(QLatin1Char('/'))) {
01501
01502
01503
01504
01505 absPath = QDir::current().absoluteFilePath(argv0);
01506 } else {
01507
01508
01509
01510
01511 QByteArray pEnv = qgetenv("PATH");
01512 QDir currentDir = QDir::current();
01513 QStringList paths = QString::fromLocal8Bit(pEnv.constData()).split(QLatin1String(":"));
01514 for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
01515 if ((*p).isEmpty())
01516 continue;
01517 QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
01518 if (QFile::exists(candidate)) {
01519 absPath = candidate;
01520 break;
01521 }
01522 }
01523 }
01524
01525 absPath = QDir::cleanPath(absPath);
01526
01527 QFileInfo fi(absPath);
01528 return fi.exists() ? fi.canonicalFilePath() : QString();
01529 #endif
01530 }
01531
01537 int QCoreApplication::argc()
01538 {
01539 if (!self) {
01540 qWarning("QCoreApplication::argc: Please instantiate the QApplication object first");
01541 return 0;
01542 }
01543 return self->d_func()->argc;
01544 }
01545
01546
01552 char **QCoreApplication::argv()
01553 {
01554 if (!self) {
01555 qWarning("QCoreApplication::argv: Please instantiate the QApplication object first");
01556 return 0;
01557 }
01558 return self->d_func()->argv;
01559 }
01560
01582 QStringList QCoreApplication::arguments()
01583 {
01584 QStringList list;
01585
01586 if (!self) {
01587 qWarning("QCoreApplication::arguments: Please instantiate the QApplication object first");
01588 return list;
01589 }
01590 #ifdef Q_OS_WIN
01591 QString cmdline = QT_WA_INLINE(QString::fromUtf16((unsigned short *)GetCommandLineW()), QString::fromLocal8Bit(GetCommandLineA()));
01592 extern QStringList qWinCmdArgs(QString cmdLine);
01593 list = qWinCmdArgs(cmdline);
01594 if (self->d_func()->application_type) {
01595 QStringList stripped;
01596 for (int a = 0; a < list.count(); ++a) {
01597 QString arg = list.at(a);
01598 QByteArray l1arg = arg.toLatin1();
01599 if (l1arg == "-qdevel" ||
01600 l1arg == "-qdebug" ||
01601 l1arg == "-reverse" ||
01602 l1arg == "-widgetcount")
01603 ;
01604 else if (l1arg.startsWith("-style="))
01605 ;
01606 else if (l1arg == "-style" ||
01607 l1arg == "-session")
01608 ++a;
01609 else
01610 stripped += arg;
01611 }
01612 list = stripped;
01613 }
01614 #else
01615 const int ac = self->d_func()->argc;
01616 char ** const av = self->d_func()->argv;
01617 for (int a = 0; a < ac; ++a) {
01618 list << QString::fromLocal8Bit(av[a]);
01619 }
01620 #endif
01621
01622 return list;
01623 }
01624
01641 void QCoreApplication::setOrganizationName(const QString &orgName)
01642 {
01643 coreappdata()->orgName = orgName;
01644 }
01645
01646 QString QCoreApplication::organizationName()
01647 {
01648 return coreappdata()->orgName;
01649 }
01650
01666 void QCoreApplication::setOrganizationDomain(const QString &orgDomain)
01667 {
01668 coreappdata()->orgDomain = orgDomain;
01669 }
01670
01671 QString QCoreApplication::organizationDomain()
01672 {
01673 return coreappdata()->orgDomain;
01674 }
01675
01686 void QCoreApplication::setApplicationName(const QString &application)
01687 {
01688 coreappdata()->application = application;
01689 }
01690
01691 QString QCoreApplication::applicationName()
01692 {
01693 return coreappdata()->application;
01694 }
01695
01696
01697
01698 #ifndef QT_NO_LIBRARY
01699
01700 Q_GLOBAL_STATIC_WITH_ARGS(QMutex, libraryPathMutex, (QMutex::Recursive))
01701
01702
01724 QStringList QCoreApplication::libraryPaths()
01725 {
01726 QMutexLocker locker(libraryPathMutex());
01727 if (!self)
01728 return QStringList();
01729 if (!coreappdata()->app_libpaths) {
01730 QStringList *app_libpaths = coreappdata()->app_libpaths = new QStringList;
01731 QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
01732 if (QFile::exists(installPathPlugins)) {
01733
01734 installPathPlugins = QDir(installPathPlugins).canonicalPath();
01735 app_libpaths->append(installPathPlugins);
01736 }
01737
01738
01739
01740 if (self) self->d_func()->appendApplicationPathToLibraryPaths();
01741
01742 const QByteArray libPathEnv = qgetenv("QT_PLUGIN_PATH");
01743 if (!libPathEnv.isEmpty()) {
01744 #ifdef Q_OS_WIN
01745 QLatin1Char pathSep(';');
01746 #else
01747 QLatin1Char pathSep(':');
01748 #endif
01749 QStringList paths = QString::fromLatin1(libPathEnv).split(pathSep, QString::SkipEmptyParts);
01750 for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) {
01751 app_libpaths->append(QDir(*it).canonicalPath());
01752 }
01753 }
01754 }
01755 return *(coreappdata()->app_libpaths);
01756 }
01757
01758
01759
01767 void QCoreApplication::setLibraryPaths(const QStringList &paths)
01768 {
01769 *(coreappdata()->app_libpaths) = paths;
01770 }
01782 void QCoreApplication::addLibraryPath(const QString &path)
01783 {
01784 if (path.isEmpty())
01785 return;
01786
01787
01788 libraryPaths();
01789
01790 QString canonicalPath = QDir(path).canonicalPath();
01791 if (!coreappdata()->app_libpaths->contains(canonicalPath))
01792 coreappdata()->app_libpaths->prepend(canonicalPath);
01793 }
01794
01801 void QCoreApplication::removeLibraryPath(const QString &path)
01802 {
01803 if (path.isEmpty())
01804 return;
01805
01806
01807 libraryPaths();
01808
01809 coreappdata()->app_libpaths->removeAll(path);
01810 }
01811
01812 #endif //QT_NO_LIBRARY
01813
01846 QCoreApplication::EventFilter
01847 QCoreApplication::setEventFilter(QCoreApplication::EventFilter filter)
01848 {
01849 Q_D(QCoreApplication);
01850 EventFilter old = d->eventFilter;
01851 d->eventFilter = filter;
01852 return old;
01853 }
01854
01863 bool QCoreApplication::filterEvent(void *message, long *result)
01864 {
01865 Q_D(QCoreApplication);
01866 if (result)
01867 *result = 0;
01868 if (d->eventFilter)
01869 return d->eventFilter(message, result);
01870 #ifdef Q_OS_WIN
01871 return winEventFilter(reinterpret_cast<MSG *>(message), result);
01872 #else
01873 return false;
01874 #endif
01875 }
01876
01884 bool QCoreApplication::hasPendingEvents()
01885 {
01886 QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
01887 if (eventDispatcher)
01888 return eventDispatcher->hasPendingEvents();
01889 return false;
01890 }
01891
01892 #ifdef QT3_SUPPORT
01893
01952 int QCoreApplication::enter_loop()
01953 {
01954 if (!QCoreApplicationPrivate::checkInstance("enter_loop"))
01955 return -1;
01956 if (QThreadData::current() != self->d_func()->threadData) {
01957 qWarning("QCoreApplication::enter_loop: Must be called from the main thread");
01958 return -1;
01959 }
01960 QEventLoop eventLoop;
01961 int returnCode = eventLoop.exec();
01962 return returnCode;
01963 }
01964
01970 void QCoreApplication::exit_loop()
01971 {
01972 if (!QCoreApplicationPrivate::checkInstance("exit_loop"))
01973 return;
01974 QThreadData *data = QThreadData::current();
01975 if (data != self->d_func()->threadData) {
01976 qWarning("QCoreApplication::exit_loop: Must be called from the main thread");
01977 return;
01978 }
01979 if (!data->eventLoops.isEmpty())
01980 data->eventLoops.top()->exit();
01981 }
01982
01987 int QCoreApplication::loopLevel()
01988 {
01989 if (!QCoreApplicationPrivate::checkInstance("loopLevel"))
01990 return -1;
01991 return self->d_func()->threadData->eventLoops.size();
01992 }
01993 #endif
01994