📄 qcoreapplication.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtCore module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qcoreapplication.h"#include "qcoreapplication_p.h"#include "qabstracteventdispatcher.h"#include "qcoreevent.h"#include "qeventloop.h"#include <qdatastream.h>#include <qdatetime.h>#include <qdebug.h>#include <qdir.h>#include <qfile.h>#include <qfileinfo.h>#include <qhash.h>#include <private/qprocess_p.h>#include <qtextcodec.h>#include <qthread.h>#include <qthreadstorage.h>#include <private/qthread_p.h>#include <qlibraryinfo.h>#ifdef Q_OS_UNIX# include "qeventdispatcher_unix_p.h"#endif#ifdef Q_OS_WIN# include "qeventdispatcher_win_p.h"#endif#include <stdlib.h>#if defined(Q_WS_WIN) || defined(Q_WS_MAC)extern QString qAppFileName();#endif#if !defined(Q_OS_WIN)QString QCoreApplicationPrivate::appName() const{ static QString applName; if (applName.isEmpty() && argv[0]) { char *p = strrchr(argv[0], '/'); applName = QString::fromLocal8Bit(p ? p + 1 : argv[0]); } return applName;}#endifbool QCoreApplicationPrivate::checkInstance(const char *function){ bool b = (QCoreApplication::self != 0); if (!b) qWarning("QApplication::%s() failed: please instantiate the QApplication object first.", function); return b;}// Support for introspectionQSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set = { 0, 0, 0, 0 };void qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set){ qt_signal_spy_callback_set = callback_set;}extern "C" void Q_CORE_EXPORT qt_startup_hook(){}typedef QList<QtCleanUpFunction> QVFuncList;Q_GLOBAL_STATIC(QVFuncList, postRList)void qAddPostRoutine(QtCleanUpFunction p){ QVFuncList *list = postRList(); if (!list) return; list->prepend(p);}void qRemovePostRoutine(QtCleanUpFunction p){ QVFuncList *list = postRList(); if (!list) return; list->removeAll(p);}void Q_CORE_EXPORT qt_call_post_routines(){ QVFuncList *list = postRList(); if (!list) return; while (!list->isEmpty()) (list->takeFirst())();}// app starting up if falsebool QCoreApplicationPrivate::is_app_running = false; // app closing down if truebool QCoreApplicationPrivate::is_app_closing = false;Q_CORE_EXPORT uint qGlobalPostedEventsCount(){ QThread *currentThread = QThread::currentThread(); if (!currentThread) return 0; return QThreadData::get(currentThread)->postEventList.size();}QCoreApplication *QCoreApplication::self = 0;QAbstractEventDispatcher *QCoreApplicationPrivate::eventDispatcher = 0;#ifdef Q_OS_UNIXQt::HANDLE qt_application_thread_id = 0;#endif#ifndef QT_NO_THREADQ_GLOBAL_STATIC(QAdoptedThread, actual_mainThread);static QThread *the_mainThread = 0;static QThread *mainThread() { return the_mainThread ? the_mainThread : actual_mainThread();}#elsestatic QThread* mainThread() { return QThread::currentThread(); }#endifstruct QCoreApplicationData { QCoreApplicationData() {#ifndef QT_NO_LIBRARY app_libpaths = 0;#endif } ~QCoreApplicationData() {#ifndef QT_NO_LIBRARY delete app_libpaths;#endif } QString orgName, orgDomain, application;#ifndef QT_NO_LIBRARY QStringList *app_libpaths;#endif};Q_GLOBAL_STATIC(QCoreApplicationData, coreappdata)QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv) : QObjectPrivate(), argc(aargc), argv(aargv), application_type(0), eventFilter(0), in_exec(false){ static const char *const empty = ""; if (argc == 0 || argv == 0) { argc = 0; argv = (char **)∅ // ouch! careful with QCoreApplication::argv()! } QCoreApplicationPrivate::is_app_closing = false;#ifdef Q_OS_UNIX qt_application_thread_id = QThread::currentThreadId();#endif QThread *thr = mainThread(); QThreadPrivate::setCurrentThread(thr); QObjectPrivate::thread = QThreadData::get(thr)->id;}QCoreApplicationPrivate::~QCoreApplicationPrivate(){ QThreadData *data = QThreadData::get(mainThread());#ifndef QT_NO_THREAD QThreadStorageData::finish(data->tls);#endif QThreadPrivate::setCurrentThread(0); // need to clear the state of the mainData, just in case a new QCoreApplication comes along. QMutexLocker locker(&data->postEventList.mutex); for (int i = 0; i < data->postEventList.size(); ++i) { const QPostEvent &pe = data->postEventList.at(i); if (pe.event) { --pe.receiver->d_func()->postedEvents;#ifdef QT3_SUPPORT if (pe.event->type() == QEvent::ChildInserted) --pe.receiver->d_func()->postedChildInsertedEvents;#endif pe.event->posted = false; delete pe.event; } } data->postEventList.clear(); data->postEventList.recursion = 0; data->quitNow = false;}void QCoreApplicationPrivate::createEventDispatcher(){ Q_Q(QCoreApplication);#if defined(Q_OS_UNIX) eventDispatcher = new QEventDispatcherUNIX(q);#elif defined(Q_OS_WIN) eventDispatcher = new QEventDispatcherWin32(q);#else# error "QEventDispatcher not yet ported to this platform"#endif}void QCoreApplicationPrivate::moveToMainThread(QObject *o){ if (!o || o->thread() == mainThread()) return; Q_ASSERT(o->parent() == 0); if (o->thread() != 0) QCoreApplication::sendPostedEvents(o, 0); o->d_func()->thread = QThreadData::get(mainThread())->id;}QThread *QCoreApplicationPrivate::mainThread(){ return ::mainThread(); }#ifdef QT3_SUPPORTvoid QCoreApplicationPrivate::removePostedChildInsertedEvents(QObject *receiver, QObject *child){ QThread *currentThread = QThread::currentThread(); if (currentThread) { QThreadData *data = QThreadData::get(currentThread); QMutexLocker locker(&data->postEventList.mutex); // the QObject destructor calls QObject::removeChild, which calls // QCoreApplication::sendEvent() directly. this can happen while the event // loop is in the middle of posting events, and when we get here, we may // not have any more posted events for this object. // if this is a child remove event and the child insert // hasn't been dispatched yet, kill that insert for (int i = 0; i < data->postEventList.size(); ++i) { const QPostEvent &pe = data->postEventList.at(i); if (pe.event && pe.receiver == receiver) { if (pe.event->type() == QEvent::ChildInserted && ((QChildEvent*)pe.event)->child() == child) { --receiver->d_func()->postedEvents; --receiver->d_func()->postedChildInsertedEvents; Q_ASSERT(receiver->d_func()->postedEvents >= 0); Q_ASSERT(receiver->d_func()->postedChildInsertedEvents >= 0); pe.event->posted = false; delete pe.event; const_cast<QPostEvent &>(pe).event = 0; const_cast<QPostEvent &>(pe).receiver = 0; } } } }}#endifvoid QCoreApplicationPrivate::checkReceiverThread(QObject *receiver){ QThread *currentThread = QThread::currentThread(); QThread *thr = receiver->thread(); Q_ASSERT_X(currentThread == thr || !thr, "QCoreApplication::sendEvent", QString::fromLatin1("Cannot send events to objects owned by a different thread. " "Current thread %1. Receiver '%2' (of type '%3') was created in thread %4") .arg(QString::number((ulong) currentThread, 16)) .arg(receiver->objectName()) .arg(QLatin1String(receiver->metaObject()->className())) .arg(QString::number((ulong) thr, 16)) .toLocal8Bit().data()); Q_UNUSED(currentThread); Q_UNUSED(thr);}void QCoreApplicationPrivate::appendApplicationPathToLibraryPaths(){#ifndef QT_NO_LIBRARY QStringList *app_libpaths = coreappdata()->app_libpaths; Q_ASSERT(app_libpaths); QString app_location( QCoreApplication::applicationFilePath() ); app_location.truncate(app_location.lastIndexOf(QLatin1Char('/'))); app_location = QDir(app_location).canonicalPath(); if (app_location != QLibraryInfo::location(QLibraryInfo::PluginsPath) && QFile::exists(app_location)) app_libpaths->append(app_location);#endif}QString qAppName(){ if (!QCoreApplicationPrivate::checkInstance("qAppName")) return QString(); return QCoreApplication::instance()->d_func()->appName();}/*! \class QCoreApplication \brief The QCoreApplication class provides an event loop for console Qt applications. \ingroup application \mainclass This class is used by non-GUI applications to provide their event loop. For non-GUI application that uses Qt, there should be exactly one QCoreApplication object. For GUI applications, see QApplication. QCoreApplication contains the main event loop, where all events from the operating system (e.g., timer and network events) and other sources are processed and dispatched. It also handles the application's initialization and finalization, as well as system-wide and application-wide settings. The command line arguments which QCoreApplication's constructor should be called with are accessible using argc() and argv(). The event loop is started with a call to exec(). Long running operations can call processEvents() to keep the application responsive. Some Qt classes (e.g., QString) can be used without a QCoreApplication object. However, in general, we recommend that you create a QCoreApplication or a QApplication object in your \c main() function as early as possible. An application has an applicationDirPath() and an applicationFilePath(). Translation files can be added or removed using installTranslator() and removeTranslator(). Application strings can be translated using translate(). The QObject::tr() and QObject::trUtf8() functions are implemented in terms of translate(). The class provides a quit() slot and an aboutToQuit() signal. Several static convenience functions are also provided. The QCoreApplication object is available from instance(). Events can be sent or posted using sendEvent(), postEvent(), and sendPostedEvents(). Pending events can be removed with removePostedEvents() or flushed with flush(). Library paths (see QLibrary) can be retrieved with libraryPaths() and manipulated by setLibraryPaths(), addLibraryPath(), and removeLibraryPath(). \sa QApplication, QAbstractEventDispatcher, QEventLoop*//*! \fn static QCoreApplication *QCoreApplication::instance() Returns a pointer to the application's QCoreApplication (or QApplication) instance.*//*!\internal */QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p) : QObject(p, 0){ init(); // note: it is the subclasses' job to call // QCoreApplicationPrivate::eventDispatcher->startingUp();}/*! Flushes the platform specific event queues. If you are doing graphical changes inside a loop that does not return to the event loop on asynchronous window systems like X11 or double buffered window systems like Mac OS X, and you want to visualize these changes immediately (e.g. Splash Screens), call this function. \sa sendPostedEvents()*/void QCoreApplication::flush(){ if (self && self->d_func()->eventDispatcher) self->d_func()->eventDispatcher->flush();}/*! Constructs a Qt kernel application. Kernel applications are applications without a graphical user interface. These type of
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -