QtBase  v6.3.1
qcoreapplication.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2021 The Qt Company Ltd.
4 ** Copyright (C) 2021 Intel Corporation.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include "qcoreapplication.h"
42 #include "qcoreapplication_p.h"
43 
44 #ifndef QT_NO_QOBJECT
46 #include "qcoreevent.h"
47 #include "qeventloop.h"
48 #endif
49 #include "qmetaobject.h"
50 #include <private/qproperty_p.h>
51 #include "qcorecmdlineargs_p.h"
52 #include <qdatastream.h>
53 #include <qdebug.h>
54 #include <qdir.h>
55 #include <qfile.h>
56 #include <qfileinfo.h>
57 #include <qmutex.h>
58 #include <private/qloggingregistry_p.h>
59 #include <qscopeguard.h>
60 #include <qstandardpaths.h>
61 #ifndef QT_NO_QOBJECT
62 #include <qthread.h>
63 #include <qthreadstorage.h>
64 #if QT_CONFIG(future)
65 #include <QtCore/qpromise.h>
66 #endif
67 #include <private/qthread_p.h>
68 #if QT_CONFIG(thread)
69 #include <qthreadpool.h>
70 #endif
71 #endif
72 #include <qelapsedtimer.h>
73 #include <qlibraryinfo.h>
74 #include <qvarlengtharray.h>
75 #include <private/qfactoryloader_p.h>
76 #include <private/qfunctions_p.h>
77 #include <private/qlocale_p.h>
78 #include <private/qlocking_p.h>
79 #include <private/qhooks_p.h>
80 
81 #ifndef QT_NO_QOBJECT
82 #if defined(Q_OS_UNIX)
83 # if defined(Q_OS_DARWIN)
84 # include "qeventdispatcher_cf_p.h"
85 # else
86 # if !defined(QT_NO_GLIB)
87 # include "qeventdispatcher_glib_p.h"
88 # endif
89 # endif
90 # include "qeventdispatcher_unix_p.h"
91 #endif
92 #ifdef Q_OS_WIN
93 #include "qeventdispatcher_win_p.h"
94 #endif
95 #endif // QT_NO_QOBJECT
96 
97 #if defined(Q_OS_ANDROID)
98 #include <QtCore/qjniobject.h>
99 #endif
100 
101 #ifdef Q_OS_MAC
102 # include "qcore_mac_p.h"
103 #endif
104 
105 #include <stdlib.h>
106 
107 #ifdef Q_OS_UNIX
108 # include <locale.h>
109 # ifndef Q_OS_INTEGRITY
110 # include <langinfo.h>
111 # endif
112 # include <unistd.h>
113 # include <sys/types.h>
114 
115 # include "qcore_unix_p.h"
116 #endif
117 
118 #if __has_include(<sys/auxv.h>) // Linux and FreeBSD
119 # include <sys/auxv.h>
120 #endif
121 
122 #ifdef Q_OS_VXWORKS
123 # include <taskLib.h>
124 #endif
125 
126 #ifdef Q_OS_WASM
127 #include <emscripten/val.h>
128 #endif
129 
130 #ifdef QT_BOOTSTRAPPED
131 #include <private/qtrace_p.h>
132 #else
133 #include <qtcore_tracepoints_p.h>
134 #endif
135 
136 #include <algorithm>
137 #include <memory>
138 
140 
141 #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
142 extern QString qAppFileName();
143 #endif
144 
145 #if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
146 # error "Bump QCoreApplicatoinPrivate::app_compile_version to QT_VERSION_CHECK(7, 0, 0)"
147 #endif
148 // We don't know exactly, but it's at least 6.0.0:
150 
152 
153 #if !defined(Q_OS_WIN)
154 #ifdef Q_OS_DARWIN
155 QString QCoreApplicationPrivate::infoDictionaryStringProperty(const QString &propertyName)
156 {
157  QString bundleName;
158  QCFString cfPropertyName = propertyName.toCFString();
159  CFTypeRef string = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(),
160  cfPropertyName);
161  if (string)
162  bundleName = QString::fromCFString(static_cast<CFStringRef>(string));
163  return bundleName;
164 }
165 #endif
167 {
168  QString applicationName;
169 #ifdef Q_OS_DARWIN
170  applicationName = infoDictionaryStringProperty(QStringLiteral("CFBundleName"));
171 #endif
172  if (applicationName.isEmpty() && argv[0]) {
173  char *p = strrchr(argv[0], '/');
174  applicationName = QString::fromLocal8Bit(p ? p + 1 : argv[0]);
175  }
176 
177  return applicationName;
178 }
180 {
181  QString applicationVersion;
182 #ifdef QT_BOOTSTRAPPED
183 #elif defined(Q_OS_DARWIN)
184  applicationVersion = infoDictionaryStringProperty(QStringLiteral("CFBundleVersion"));
185 #elif defined(Q_OS_ANDROID)
187  if (context.isValid()) {
188  QJniObject pm = context.callObjectMethod(
189  "getPackageManager", "()Landroid/content/pm/PackageManager;");
190  QJniObject pn = context.callObjectMethod<jstring>("getPackageName");
191  if (pm.isValid() && pn.isValid()) {
192  QJniObject packageInfo = pm.callObjectMethod(
193  "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;",
194  pn.object(), 0);
195  if (packageInfo.isValid()) {
196  QJniObject versionName = packageInfo.getObjectField(
197  "versionName", "Ljava/lang/String;");
198  if (versionName.isValid())
199  return versionName.toString();
200  }
201  }
202  }
203 #endif
204  return applicationVersion;
205 }
206 #endif // !Q_OS_WIN
207 
209 
210 bool QCoreApplicationPrivate::checkInstance(const char *function)
211 {
212  bool b = (QCoreApplication::self != nullptr);
213  if (!b)
214  qWarning("QApplication::%s: Please instantiate the QApplication object first", function);
215  return b;
216 }
217 
218 #if QT_CONFIG(commandlineparser)
219 void QCoreApplicationPrivate::addQtOptions(QList<QCommandLineOption> *options)
220 {
221  options->append(QCommandLineOption(QStringLiteral("qmljsdebugger"),
222  QStringLiteral("Activates the QML/JS debugger with a specified port. The value must be of format port:1234[,block]. \"block\" makes the application wait for a connection."),
223  QStringLiteral("value")));
224 }
225 #endif
226 
228 {
229  int j = argc ? 1 : 0;
230  for (int i = 1; i < argc; ++i) {
231  if (!argv[i])
232  continue;
233  if (*argv[i] != '-') {
234  argv[j++] = argv[i];
235  continue;
236  }
237  const char *arg = argv[i];
238  if (arg[1] == '-') // startsWith("--")
239  ++arg;
240  if (strncmp(arg, "-qmljsdebugger=", 15) == 0) {
242  } else if (strcmp(arg, "-qmljsdebugger") == 0 && i < argc - 1) {
243  ++i;
245  } else {
246  argv[j++] = argv[i];
247  }
248  }
249 
250  if (j < argc) {
251  argv[j] = nullptr;
252  argc = j;
253  }
254 }
255 
256 // Support for introspection
257 
258 extern "C" void Q_CORE_EXPORT qt_startup_hook()
259 {
260 }
261 
265 Q_GLOBAL_STATIC(QVFuncList, postRList)
266 static QBasicMutex globalRoutinesMutex;
267 static bool preRoutinesCalled = false;
268 
276 {
277  QStartUpFuncList *list = preRList();
278  if (!list)
279  return;
280 
281  if (preRoutinesCalled) {
283  p();
284  }
285 
286  // Due to C++11 parallel dynamic initialization, this can be called
287  // from multiple threads.
288  const auto locker = qt_scoped_lock(globalRoutinesMutex);
289  list->prepend(p); // in case QCoreApplication is re-created, see qt_call_pre_routines
290 }
291 
293 {
294  QVFuncList *list = postRList();
295  if (!list)
296  return;
297  const auto locker = qt_scoped_lock(globalRoutinesMutex);
298  list->prepend(p);
299 }
300 
302 {
303  QVFuncList *list = postRList();
304  if (!list)
305  return;
306  const auto locker = qt_scoped_lock(globalRoutinesMutex);
307  list->removeAll(p);
308 }
309 
310 static void qt_call_pre_routines()
311 {
312  // After will be allowed invoke QtStartUpFunction when calling qAddPreRoutine
313  preRoutinesCalled = true;
314 
315  if (!preRList.exists())
316  return;
317 
319  {
320  const auto locker = qt_scoped_lock(globalRoutinesMutex);
321  // Unlike qt_call_post_routines, we don't empty the list, because
322  // Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects
323  // the function to be executed every time QCoreApplication is created.
324  list = *preRList;
325  }
326  for (QtCleanUpFunction f : std::as_const(list))
327  f();
328 }
329 
330 void Q_CORE_EXPORT qt_call_post_routines()
331 {
332  if (!postRList.exists())
333  return;
334 
335  forever {
337  {
338  // extract the current list and make the stored list empty
339  const auto locker = qt_scoped_lock(globalRoutinesMutex);
340  qSwap(*postRList, list);
341  }
342 
343  if (list.isEmpty())
344  break;
345  for (QtCleanUpFunction f : qAsConst(list))
346  f();
347  }
348 }
349 
350 
351 #ifndef QT_NO_QOBJECT
352 
353 // app starting up if false
355  // app closing down if true
357 
359 {
360  QThreadData *currentThreadData = QThreadData::current();
361  return currentThreadData->postEventList.size() - currentThreadData->postEventList.startOffset;
362 }
363 
365 
366 #endif // QT_NO_QOBJECT
367 
368 QCoreApplication *QCoreApplication::self = nullptr;
372 
374  QCoreApplicationData() noexcept {
375  applicationNameSet = false;
376  applicationVersionSet = false;
377  }
379 #ifndef QT_NO_QOBJECT
380  // cleanup the QAdoptedThread created for the main() thread
381  if (auto *t = QCoreApplicationPrivate::theMainThread.loadAcquire()) {
383  data->deref(); // deletes the data and the adopted thread
384  }
385 #endif
386  }
387 
389  QString application; // application name, initially from argv[0], can then be modified.
391  bool applicationNameSet; // true if setApplicationName was called
392  bool applicationVersionSet; // true if setApplicationVersion was called
393 
394 #if QT_CONFIG(library)
395  std::unique_ptr<QStringList> app_libpaths;
396  std::unique_ptr<QStringList> manual_libpaths;
397 #endif
398 
399 };
400 
402 
403 #ifndef QT_NO_QOBJECT
404 static bool quitLockEnabled = true;
405 #endif
406 
407 #if defined(Q_OS_WIN)
408 // Check whether the command line arguments passed to QCoreApplication
409 // match those passed into main(), to see if the user has modified them
410 // before passing them on to us. We do this by comparing to the global
411 // __argv/__argc (MS extension). Deep comparison is required since
412 // argv/argc is rebuilt by our WinMain entrypoint.
413 static inline bool isArgvModified(int argc, char **argv)
414 {
415  if (__argc != argc || !__argv /* wmain() */)
416  return true;
417  if (__argv == argv)
418  return false;
419  for (int a = 0; a < argc; ++a) {
420  if (argv[a] != __argv[a] && strcmp(argv[a], __argv[a]))
421  return true;
422  }
423  return false;
424 }
425 
426 static inline bool contains(int argc, char **argv, const char *needle)
427 {
428  for (int a = 0; a < argc; ++a) {
429  if (!strcmp(argv[a], needle))
430  return true;
431  }
432  return false;
433 }
434 #endif // Q_OS_WIN
435 
437  :
438 #ifndef QT_NO_QOBJECT
439  QObjectPrivate(),
440 #endif
441  argc(aargc)
442  , argv(aargv)
443 #if defined(Q_OS_WIN)
444  , origArgc(0)
445  , origArgv(nullptr)
446 #endif
447  , application_type(QCoreApplicationPrivate::Tty)
448 #ifndef QT_NO_QOBJECT
449  , in_exec(false)
450  , aboutToQuitEmitted(false)
451  , threadData_clean(false)
452 #else
453  , q_ptr(nullptr)
454 #endif
455 {
456  app_compile_version = flags & 0xffffff;
457  static const char *const empty = "";
458  if (argc == 0 || argv == nullptr) {
459  argc = 0;
460  argv = const_cast<char **>(&empty);
461  }
462 #if defined(Q_OS_WIN)
463  if (!isArgvModified(argc, argv)) {
464  origArgc = argc;
465  origArgv = new char *[argc];
466  std::copy(argv, argv + argc, QT_MAKE_CHECKED_ARRAY_ITERATOR(origArgv, argc));
467  }
468 #endif // Q_OS_WIN
469 
470 #ifndef QT_NO_QOBJECT
472 
473 # if defined(Q_OS_UNIX)
474  if (Q_UNLIKELY(!setuidAllowed && (geteuid() != getuid())))
475  qFatal("FATAL: The application binary appears to be running setuid, this is a security hole.");
476 # endif // Q_OS_UNIX
477 
478  QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread!
479  if (cur != theMainThread.loadAcquire())
480  qWarning("WARNING: QApplication was not created in the main() thread.");
481 #endif
482 }
483 
485 {
486 #ifndef QT_NO_QOBJECT
488 #endif
489 #if defined(Q_OS_WIN)
490  delete [] origArgv;
491 #endif
493 }
494 
495 #ifndef QT_NO_QOBJECT
496 
498 {
499  auto thisThreadData = threadData.loadRelaxed();
500 
501  if (thisThreadData && !threadData_clean) {
502 #if QT_CONFIG(thread)
503  void *data = &thisThreadData->tls;
504  QThreadStorageData::finish((void **)data);
505 #endif
506 
507  // need to clear the state of the mainData, just in case a new QCoreApplication comes along.
508  const auto locker = qt_scoped_lock(thisThreadData->postEventList.mutex);
509  for (const QPostEvent &pe : std::as_const(thisThreadData->postEventList)) {
510  if (pe.event) {
511  --pe.receiver->d_func()->postedEvents;
512  pe.event->m_posted = false;
513  delete pe.event;
514  }
515  }
516  thisThreadData->postEventList.clear();
517  thisThreadData->postEventList.recursion = 0;
518  thisThreadData->quitNow = false;
519  threadData_clean = true;
520  }
521 }
522 
524 {
525  Q_Q(QCoreApplication);
527  Q_ASSERT(!data->hasEventDispatcher());
528  eventDispatcher = data->createEventDispatcher();
530 }
531 
533 {
534 }
535 
538 {
539  Q_ASSERT(theMainThread.loadRelaxed() != nullptr);
540  return theMainThread.loadRelaxed();
541 }
542 
544 {
546  if (!data)
547  return true; // default setting
548  return data->requiresCoreApplication;
549 }
550 
552 {
553  QThread *currentThread = QThread::currentThread();
554  QThread *thr = receiver->thread();
555  Q_ASSERT_X(currentThread == thr || !thr,
556  "QCoreApplication::sendEvent",
557  QString::asprintf("Cannot send events to objects owned by a different thread. "
558  "Current thread 0x%p. Receiver '%ls' (of type '%s') was created in thread 0x%p",
559  currentThread, qUtf16Printable(receiver->objectName()),
560  receiver->metaObject()->className(), thr)
561  .toLocal8Bit().data());
562  Q_UNUSED(currentThread);
563  Q_UNUSED(thr);
564 }
565 
566 #endif // QT_NO_QOBJECT
567 
569 {
570 #if QT_CONFIG(library)
571  QStringList *app_libpaths = coreappdata()->app_libpaths.get();
572  if (!app_libpaths)
573  coreappdata()->app_libpaths.reset(app_libpaths = new QStringList);
575  app_location.truncate(app_location.lastIndexOf(QLatin1Char('/')));
576  app_location = QDir(app_location).canonicalPath();
577  if (QFile::exists(app_location) && !app_libpaths->contains(app_location))
578  app_libpaths->append(app_location);
579 #endif
580 }
581 
583 {
585  return QString();
586  return QCoreApplication::instance()->d_func()->appName();
587 }
588 
590 {
591 #if defined(Q_OS_UNIX) && !defined(QT_BOOTSTRAPPED)
592  static bool qt_locale_initialized = false;
593  if (qt_locale_initialized)
594  return;
595  qt_locale_initialized = true;
596 
597 #ifdef Q_OS_INTEGRITY
598  setlocale(LC_CTYPE, "UTF-8");
599 #else
600  // Android's Bionic didn't get nl_langinfo until NDK 15 (Android 8.0),
601  // which is too new for Qt, so we just assume it's always UTF-8.
602  auto nl_langinfo = [](int) { return "UTF-8"; };
603 
604  const char *locale = setlocale(LC_ALL, "");
605  const char *codec = nl_langinfo(CODESET);
606  if (Q_UNLIKELY(strcmp(codec, "UTF-8") != 0 && strcmp(codec, "utf8") != 0)) {
607  QByteArray oldLocale = locale;
608  QByteArray newLocale = setlocale(LC_CTYPE, nullptr);
609  if (qsizetype dot = newLocale.indexOf('.'); dot != -1)
610  newLocale.truncate(dot); // remove encoding, if any
611  if (qsizetype at = newLocale.indexOf('@'); at != -1)
612  newLocale.truncate(at); // remove variant, as the old de_DE@euro
613  newLocale += ".UTF-8";
614  newLocale = setlocale(LC_CTYPE, newLocale);
615 
616  // if locale doesn't exist, try some fallbacks
617 # ifdef Q_OS_DARWIN
618  if (newLocale.isEmpty())
619  newLocale = setlocale(LC_CTYPE, "UTF-8");
620 # endif
621  if (newLocale.isEmpty())
622  newLocale = setlocale(LC_CTYPE, "C.UTF-8");
623  if (newLocale.isEmpty())
624  newLocale = setlocale(LC_CTYPE, "C.utf8");
625 
626  qWarning("Detected system locale encoding (%s, locale \"%s\") is not UTF-8.\n"
627  "Qt shall use a UTF-8 locale (\"%s\") instead. If this causes problems,\n"
628  "reconfigure your locale. See the locale(1) manual for more information.",
629  codec, oldLocale.constData(), newLocale.constData());
630  }
631 #endif
632 #endif
633 }
634 
635 
724 #ifdef QT_NO_QOBJECT
725  : d_ptr(&p)
726 #else
727  : QObject(p, nullptr)
728 #endif
729 {
730  d_func()->q_ptr = this;
731  // note: it is the subclasses' job to call
732  // QCoreApplicationPrivate::eventDispatcher->startingUp();
733 }
734 
750 #ifndef Q_QDOC
751  , int _internal
752 #endif
753  )
754 #ifdef QT_NO_QOBJECT
755  : d_ptr(new QCoreApplicationPrivate(argc, argv, _internal))
756 #else
757  : QObject(*new QCoreApplicationPrivate(argc, argv, _internal))
758 #endif
759 {
760  d_func()->q_ptr = this;
761  d_func()->init();
762 #ifndef QT_NO_QOBJECT
764 #endif
765 }
766 
775 {
776  Q_TRACE_SCOPE(QCoreApplicationPrivate_init);
777 
778 #if defined(Q_OS_MACOS)
779  QMacAutoReleasePool pool;
780 #endif
781 
782  Q_Q(QCoreApplication);
783 
784  initLocale();
785 
786  Q_ASSERT_X(!QCoreApplication::self, "QCoreApplication", "there should be only one application object");
787  QCoreApplication::self = q;
788 
789 #if QT_CONFIG(thread)
790 #ifdef Q_OS_WASM
791  emscripten::val hardwareConcurrency = emscripten::val::global("navigator")["hardwareConcurrency"];
792  if (hardwareConcurrency.isUndefined())
793  QThreadPrivate::idealThreadCount = 2;
794  else
795  QThreadPrivate::idealThreadCount = hardwareConcurrency.as<int>();
796 #endif
797 #endif
798 
799  // Store app name/version (so they're still available after QCoreApplication is destroyed)
800  if (!coreappdata()->applicationNameSet)
801  coreappdata()->application = appName();
802 
803  if (!coreappdata()->applicationVersionSet)
804  coreappdata()->applicationVersion = appVersion();
805 
806 #if defined(Q_OS_ANDROID)
807  // We've deferred initializing the logging registry due to not being
808  // able to guarantee that logging happened on the same thread as the
809  // Qt main thread, but now that the Qt main thread is set up, we can
810  // enable categorized logging.
812 #endif
813 
814 #if QT_CONFIG(library)
815  // Reset the lib paths, so that they will be recomputed, taking the availability of argv[0]
816  // into account. If necessary, recompute right away and replay the manual changes on top of the
817  // new lib paths.
818  QStringList *appPaths = coreappdata()->app_libpaths.release();
819  QStringList *manualPaths = coreappdata()->manual_libpaths.release();
820  if (appPaths) {
821  if (manualPaths) {
822  // Replay the delta. As paths can only be prepended to the front or removed from
823  // anywhere in the list, we can just linearly scan the lists and find the items that
824  // have been removed. Once the original list is exhausted we know all the remaining
825  // items have been added.
826  QStringList newPaths(q->libraryPaths());
827  for (qsizetype i = manualPaths->length(), j = appPaths->length(); i > 0 || j > 0; qt_noop()) {
828  if (--j < 0) {
829  newPaths.prepend((*manualPaths)[--i]);
830  } else if (--i < 0) {
831  newPaths.removeAll((*appPaths)[j]);
832  } else if ((*manualPaths)[i] != (*appPaths)[j]) {
833  newPaths.removeAll((*appPaths)[j]);
834  ++i; // try again with next item.
835  }
836  }
837  delete manualPaths;
838  coreappdata()->manual_libpaths.reset(new QStringList(newPaths));
839  }
840  delete appPaths;
841  }
842 #endif
843 
844 #ifndef QT_NO_QOBJECT
845  // use the event dispatcher created by the app programmer (if any)
847  auto thisThreadData = threadData.loadRelaxed();
848  eventDispatcher = thisThreadData->eventDispatcher.loadRelaxed();
849 
850  // otherwise we create one
851  if (!eventDispatcher)
854 
855  if (!eventDispatcher->parent()) {
856  eventDispatcher->moveToThread(thisThreadData->thread.loadAcquire());
858  }
859 
860  thisThreadData->eventDispatcher = eventDispatcher;
862 #endif
863 
865 
866  qt_call_pre_routines();
867  qt_startup_hook();
868 #ifndef QT_BOOTSTRAPPED
871  reinterpret_cast<QHooks::StartupCallback>(qtHookData[QHooks::Startup])();
872 #endif
873 
874 #ifndef QT_NO_QOBJECT
875  is_app_running = true; // No longer starting up.
876 #endif
877 }
878 
883 {
884  preRoutinesCalled = false;
885 
887 
888  self = nullptr;
889 #ifndef QT_NO_QOBJECT
892 #endif
893 
894 #if QT_CONFIG(thread)
895  // Synchronize and stop the global thread pool threads.
896  QThreadPool *globalThreadPool = nullptr;
897  QT_TRY {
898  globalThreadPool = QThreadPool::globalInstance();
899  } QT_CATCH (...) {
900  // swallow the exception, since destructors shouldn't throw
901  }
902  if (globalThreadPool) {
903  globalThreadPool->waitForDone();
904  delete globalThreadPool;
905  }
906 #endif
907 
908 #ifndef QT_NO_QOBJECT
909  d_func()->threadData.loadRelaxed()->eventDispatcher = nullptr;
913 #endif
914 
915 #if QT_CONFIG(library)
916  coreappdata()->app_libpaths.reset();
917  coreappdata()->manual_libpaths.reset();
918 #endif
919 }
920 
942 {
944 }
945 
955 {
957 }
958 
959 
971 {
972  if (on)
974  else
976 #if defined(QT_NO_QOBJECT)
977  if (Q_UNLIKELY(qApp)) {
978 #else
980 #endif
981  switch (attribute) {
984  case Qt::AA_UseOpenGLES:
987 #ifdef QT_BOOTSTRAPPED
988  qWarning("Attribute %d must be set before QCoreApplication is created.",
989  attribute);
990 #else
991  qWarning("Attribute Qt::%s must be set before QCoreApplication is created.",
992  QMetaEnum::fromType<Qt::ApplicationAttribute>().valueToKey(attribute));
993 #endif
994  break;
995  default:
996  break;
997  }
998  }
999 }
1000 
1008 {
1010 }
1011 
1012 #ifndef QT_NO_QOBJECT
1013 
1026 {
1027  return quitLockEnabled;
1028 }
1029 
1030 static bool doNotify(QObject *, QEvent *);
1031 
1033 {
1035 }
1036 
1044 bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event)
1045 {
1047  if (!self && selfRequired)
1048  return false;
1049 
1050  // Make it possible for Qt Script to hook into events even
1051  // though QApplication is subclassed...
1052  bool result = false;
1053  void *cbdata[] = { receiver, event, &result };
1055  return result;
1056  }
1057 
1058  // Qt enforces the rule that events can only be sent to objects in
1059  // the current thread, so receiver->d_func()->threadData is
1060  // equivalent to QThreadData::current(), just without the function
1061  // call overhead.
1062  QObjectPrivate *d = receiver->d_func();
1063  QThreadData *threadData = d->threadData;
1064  QScopedScopeLevelCounter scopeLevelCounter(threadData);
1065  if (!selfRequired)
1066  return doNotify(receiver, event);
1067  return self->notify(receiver, event);
1068 }
1069 
1077 bool QCoreApplication::forwardEvent(QObject *receiver, QEvent *event, QEvent *originatingEvent)
1078 {
1079  if (event && originatingEvent)
1080  event->m_spont = originatingEvent->m_spont;
1081 
1082  return notifyInternal2(receiver, event);
1083 }
1084 
1139 {
1140  Q_ASSERT(receiver);
1141  Q_ASSERT(event);
1142 
1143  // no events are delivered after ~QCoreApplication() has started
1145  return true;
1146  return doNotify(receiver, event);
1147 }
1148 
1149 static bool doNotify(QObject *receiver, QEvent *event)
1150 {
1151  Q_ASSERT(event);
1152 
1153  // ### Qt 7: turn into an assert
1154  if (receiver == nullptr) { // serious error
1155  qWarning("QCoreApplication::notify: Unexpected null receiver");
1156  return true;
1157  }
1158 
1159 #ifndef QT_NO_DEBUG
1161 #endif
1162 
1163  return receiver->isWidgetType() ? false : QCoreApplicationPrivate::notify_helper(receiver, event);
1164 }
1165 
1167 {
1168  // We can't access the application event filters outside of the main thread (race conditions)
1169  Q_ASSERT(receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread());
1170 
1171  if (extraData) {
1172  // application event filters are only called for objects in the GUI thread
1173  for (qsizetype i = 0; i < extraData->eventFilters.size(); ++i) {
1174  QObject *obj = extraData->eventFilters.at(i);
1175  if (!obj)
1176  continue;
1177  if (obj->d_func()->threadData.loadRelaxed() != threadData.loadRelaxed()) {
1178  qWarning("QCoreApplication: Application event filter cannot be in a different thread.");
1179  continue;
1180  }
1181  if (obj->eventFilter(receiver, event))
1182  return true;
1183  }
1184  }
1185  return false;
1186 }
1187 
1189 {
1190  if (receiver != QCoreApplication::instance() && receiver->d_func()->extraData) {
1191  for (qsizetype i = 0; i < receiver->d_func()->extraData->eventFilters.size(); ++i) {
1192  QObject *obj = receiver->d_func()->extraData->eventFilters.at(i);
1193  if (!obj)
1194  continue;
1195  if (obj->d_func()->threadData.loadRelaxed() != receiver->d_func()->threadData.loadRelaxed()) {
1196  qWarning("QCoreApplication: Object event filter cannot be in a different thread.");
1197  continue;
1198  }
1199  if (obj->eventFilter(receiver, event))
1200  return true;
1201  }
1202  }
1203  return false;
1204 }
1205 
1212 {
1213  // Note: when adjusting the tracepoints in here
1214  // consider adjusting QApplicationPrivate::notify_helper too.
1215  Q_TRACE(QCoreApplication_notify_entry, receiver, event, event->type());
1216  bool consumed = false;
1217  bool filtered = false;
1218  Q_TRACE_EXIT(QCoreApplication_notify_exit, consumed, filtered);
1219 
1220  // send to all application event filters (only does anything in the main thread)
1221  if (QCoreApplication::self
1222  && receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread()
1223  && QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
1224  filtered = true;
1225  return filtered;
1226  }
1227  // send to all receiver event filters
1228  if (sendThroughObjectEventFilters(receiver, event)) {
1229  filtered = true;
1230  return filtered;
1231  }
1232 
1233  // deliver the event
1234  consumed = receiver->event(event);
1235  return consumed;
1236 }
1237 
1246 {
1248 }
1249 
1258 {
1260 }
1261 
1262 
1291 void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
1292 {
1294  if (!data->hasEventDispatcher())
1295  return;
1296  data->eventDispatcher.loadRelaxed()->processEvents(flags);
1297 }
1298 
1323 void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int ms)
1324 {
1325  // ### TODO: consider splitting this method into a public and a private
1326  // one, so that a user-invoked processEvents can be detected
1327  // and handled properly.
1329  if (!data->hasEventDispatcher())
1330  return;
1332  start.start();
1333  while (data->eventDispatcher.loadRelaxed()->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
1334  if (start.elapsed() > ms)
1335  break;
1336  }
1337 }
1338 
1339 /*****************************************************************************
1340  Main event loop wrappers
1341  *****************************************************************************/
1342 
1370 {
1372  return -1;
1373 
1374  QThreadData *threadData = self->d_func()->threadData;
1375  if (threadData != QThreadData::current()) {
1376  qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
1377  return -1;
1378  }
1379  if (!threadData->eventLoops.isEmpty()) {
1380  qWarning("QCoreApplication::exec: The event loop is already running");
1381  return -1;
1382  }
1383 
1384  threadData->quitNow = false;
1385  QEventLoop eventLoop;
1386  self->d_func()->in_exec = true;
1387  self->d_func()->aboutToQuitEmitted = false;
1388  int returnCode = eventLoop.exec(QEventLoop::ApplicationExec);
1389  threadData->quitNow = false;
1390 
1391  if (self)
1392  self->d_func()->execCleanup();
1393 
1394  return returnCode;
1395 }
1396 
1397 
1398 // Cleanup after eventLoop is done executing in QCoreApplication::exec().
1399 // This is for use cases in which QCoreApplication is instantiated by a
1400 // library and not by an application executable, for example, Active X
1401 // servers.
1402 
1404 {
1405  threadData.loadRelaxed()->quitNow = false;
1406  in_exec = false;
1407  if (!aboutToQuitEmitted)
1408  emit q_func()->aboutToQuit(QCoreApplication::QPrivateSignal());
1409  aboutToQuitEmitted = true;
1411 }
1412 
1413 
1444 void QCoreApplication::exit(int returnCode)
1445 {
1446  if (!self)
1447  return;
1448  QThreadData *data = self->d_func()->threadData.loadRelaxed();
1449  data->quitNow = true;
1450  for (qsizetype i = 0; i < data->eventLoops.size(); ++i) {
1451  QEventLoop *eventLoop = data->eventLoops.at(i);
1452  eventLoop->exit(returnCode);
1453  }
1454 }
1455 
1456 /*****************************************************************************
1457  QCoreApplication management of posted events
1458  *****************************************************************************/
1459 
1460 #ifndef QT_NO_QOBJECT
1476 {
1477  Q_ASSERT_X(receiver, "QCoreApplication::sendEvent", "Unexpected null receiver");
1478  Q_ASSERT_X(event, "QCoreApplication::sendEvent", "Unexpected null event");
1479 
1480  Q_TRACE(QCoreApplication_sendEvent, receiver, event, event->type());
1481 
1482  event->m_spont = false;
1483  return notifyInternal2(receiver, event);
1484 }
1485 
1489 bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
1490 {
1491  Q_ASSERT_X(receiver, "QCoreApplication::sendSpontaneousEvent", "Unexpected null receiver");
1492  Q_ASSERT_X(event, "QCoreApplication::sendSpontaneousEvent", "Unexpected null event");
1493 
1494  Q_TRACE(QCoreApplication_sendSpontaneousEvent, receiver, event, event->type());
1495 
1496  event->m_spont = true;
1497  return notifyInternal2(receiver, event);
1498 }
1499 
1500 #endif // QT_NO_QOBJECT
1501 
1503 {
1504  QPostEventListLocker locker;
1505 
1506  if (!object) {
1507  locker.threadData = QThreadData::current();
1509  return locker;
1510  }
1511 
1512  auto &threadData = QObjectPrivate::get(object)->threadData;
1513 
1514  // if object has moved to another thread, follow it
1515  for (;;) {
1516  // synchronizes with the storeRelease in QObject::moveToThread
1517  locker.threadData = threadData.loadAcquire();
1518  if (!locker.threadData) {
1519  // destruction in progress
1520  return locker;
1521  }
1522 
1523  auto temporaryLocker = qt_unique_lock(locker.threadData->postEventList.mutex);
1524  if (locker.threadData == threadData.loadAcquire()) {
1525  locker.locker = std::move(temporaryLocker);
1526  break;
1527  }
1528  }
1529 
1530  Q_ASSERT(locker.threadData);
1531  return locker;
1532 }
1533 
1559 void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
1560 {
1561  Q_ASSERT_X(event, "QCoreApplication::postEvent", "Unexpected null event");
1562 
1563  Q_TRACE_SCOPE(QCoreApplication_postEvent, receiver, event, event->type());
1564 
1565  // ### Qt 7: turn into an assert
1566  if (receiver == nullptr) {
1567  qWarning("QCoreApplication::postEvent: Unexpected null receiver");
1568  delete event;
1569  return;
1570  }
1571 
1572  auto locker = QCoreApplicationPrivate::lockThreadPostEventList(receiver);
1573  if (!locker.threadData) {
1574  // posting during destruction? just delete the event to prevent a leak
1575  delete event;
1576  return;
1577  }
1578 
1579  QThreadData *data = locker.threadData;
1580 
1581  // if this is one of the compressible events, do compression
1582  if (receiver->d_func()->postedEvents
1583  && self && self->compressEvent(event, receiver, &data->postEventList)) {
1584  Q_TRACE(QCoreApplication_postEvent_event_compressed, receiver, event);
1585  return;
1586  }
1587 
1588  if (event->type() == QEvent::DeferredDelete)
1589  receiver->d_ptr->deleteLaterCalled = true;
1590 
1591  if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {
1592  // remember the current running eventloop for DeferredDelete
1593  // events posted in the receiver's thread.
1594 
1595  // Events sent by non-Qt event handlers (such as glib) may not
1596  // have the scopeLevel set correctly. The scope level makes sure that
1597  // code like this:
1598  // foo->deleteLater();
1599  // qApp->processEvents(); // without passing QEvent::DeferredDelete
1600  // will not cause "foo" to be deleted before returning to the event loop.
1601 
1602  // If the scope level is 0 while loopLevel != 0, we are called from a
1603  // non-conformant code path, and our best guess is that the scope level
1604  // should be 1. (Loop level 0 is special: it means that no event loops
1605  // are running.)
1606  int loopLevel = data->loopLevel;
1607  int scopeLevel = data->scopeLevel;
1608  if (scopeLevel == 0 && loopLevel != 0)
1609  scopeLevel = 1;
1610  static_cast<QDeferredDeleteEvent *>(event)->level = loopLevel + scopeLevel;
1611  }
1612 
1613  // delete the event on exceptions to protect against memory leaks till the event is
1614  // properly owned in the postEventList
1615  std::unique_ptr<QEvent> eventDeleter(event);
1616  Q_TRACE(QCoreApplication_postEvent_event_posted, receiver, event, event->type());
1617  data->postEventList.addEvent(QPostEvent(receiver, event, priority));
1618  Q_UNUSED(eventDeleter.release());
1619  event->m_posted = true;
1620  ++receiver->d_func()->postedEvents;
1621  data->canWait = false;
1622  locker.unlock();
1623 
1624  QAbstractEventDispatcher* dispatcher = data->eventDispatcher.loadAcquire();
1625  if (dispatcher)
1626  dispatcher->wakeUp();
1627 }
1628 
1634 {
1635  Q_ASSERT(event);
1636  Q_ASSERT(receiver);
1637  Q_ASSERT(postedEvents);
1638 
1639 #ifdef Q_OS_WIN
1640  // compress posted timers to this object.
1641  if (event->type() == QEvent::Timer && receiver->d_func()->postedEvents > 0) {
1642  int timerId = ((QTimerEvent *) event)->timerId();
1643  for (const QPostEvent &e : std::as_const(*postedEvents)) {
1644  if (e.receiver == receiver && e.event && e.event->type() == QEvent::Timer
1645  && ((QTimerEvent *) e.event)->timerId() == timerId) {
1646  delete event;
1647  return true;
1648  }
1649  }
1650  return false;
1651  }
1652 #endif
1653 
1654  if (event->type() == QEvent::DeferredDelete) {
1655  if (receiver->d_ptr->deleteLaterCalled) {
1656  // there was a previous DeferredDelete event, so we can drop the new one
1657  delete event;
1658  return true;
1659  }
1660  // deleteLaterCalled is set to true in postedEvents when queueing the very first
1661  // deferred deletion event.
1662  return false;
1663  }
1664 
1665  if (event->type() == QEvent::Quit && receiver->d_func()->postedEvents > 0) {
1666  for (const QPostEvent &cur : std::as_const(*postedEvents)) {
1667  if (cur.receiver != receiver
1668  || cur.event == nullptr
1669  || cur.event->type() != event->type())
1670  continue;
1671  // found an event for this receiver
1672  delete event;
1673  return true;
1674  }
1675  }
1676 
1677  return false;
1678 }
1679 
1697 void QCoreApplication::sendPostedEvents(QObject *receiver, int event_type)
1698 {
1699  // ### TODO: consider splitting this method into a public and a private
1700  // one, so that a user-invoked sendPostedEvents can be detected
1701  // and handled properly.
1703 
1704  QCoreApplicationPrivate::sendPostedEvents(receiver, event_type, data);
1705 }
1706 
1708  QThreadData *data)
1709 {
1710  if (event_type == -1) {
1711  // we were called by an obsolete event dispatcher.
1712  event_type = 0;
1713  }
1714 
1715  if (receiver && receiver->d_func()->threadData.loadRelaxed() != data) {
1716  qWarning("QCoreApplication::sendPostedEvents: Cannot send "
1717  "posted events for objects in another thread");
1718  return;
1719  }
1720 
1721  ++data->postEventList.recursion;
1722 
1723  auto locker = qt_unique_lock(data->postEventList.mutex);
1724 
1725  // by default, we assume that the event dispatcher can go to sleep after
1726  // processing all events. if any new events are posted while we send
1727  // events, canWait will be set to false.
1728  data->canWait = (data->postEventList.size() == 0);
1729 
1730  if (data->postEventList.size() == 0 || (receiver && !receiver->d_func()->postedEvents)) {
1731  --data->postEventList.recursion;
1732  return;
1733  }
1734 
1735  data->canWait = true;
1736 
1737  // okay. here is the tricky loop. be careful about optimizing
1738  // this, it looks the way it does for good reasons.
1739  qsizetype startOffset = data->postEventList.startOffset;
1740  qsizetype &i = (!event_type && !receiver) ? data->postEventList.startOffset : startOffset;
1741  data->postEventList.insertionOffset = data->postEventList.size();
1742 
1743  // Exception-safe cleaning up without the need for a try/catch block
1744  struct CleanUp {
1745  QObject *receiver;
1746  int event_type;
1747  QThreadData *data;
1748  bool exceptionCaught;
1749 
1750  inline CleanUp(QObject *receiver, int event_type, QThreadData *data) :
1751  receiver(receiver), event_type(event_type), data(data), exceptionCaught(true)
1752  {}
1753  inline ~CleanUp()
1754  {
1755  if (exceptionCaught) {
1756  // since we were interrupted, we need another pass to make sure we clean everything up
1757  data->canWait = false;
1758  }
1759 
1760  --data->postEventList.recursion;
1761  if (!data->postEventList.recursion && !data->canWait && data->hasEventDispatcher())
1762  data->eventDispatcher.loadRelaxed()->wakeUp();
1763 
1764  // clear the global list, i.e. remove everything that was
1765  // delivered.
1766  if (!event_type && !receiver && data->postEventList.startOffset >= 0) {
1767  const QPostEventList::iterator it = data->postEventList.begin();
1768  data->postEventList.erase(it, it + data->postEventList.startOffset);
1769  data->postEventList.insertionOffset -= data->postEventList.startOffset;
1770  Q_ASSERT(data->postEventList.insertionOffset >= 0);
1771  data->postEventList.startOffset = 0;
1772  }
1773  }
1774  };
1775  CleanUp cleanup(receiver, event_type, data);
1776 
1777  while (i < data->postEventList.size()) {
1778  // avoid live-lock
1779  if (i >= data->postEventList.insertionOffset)
1780  break;
1781 
1782  const QPostEvent &pe = data->postEventList.at(i);
1783  ++i;
1784 
1785  if (!pe.event)
1786  continue;
1787  if ((receiver && receiver != pe.receiver) || (event_type && event_type != pe.event->type())) {
1788  data->canWait = false;
1789  continue;
1790  }
1791 
1792  if (pe.event->type() == QEvent::DeferredDelete) {
1793  // DeferredDelete events are sent either
1794  // 1) when the event loop that posted the event has returned; or
1795  // 2) if explicitly requested (with QEvent::DeferredDelete) for
1796  // events posted by the current event loop; or
1797  // 3) if the event was posted before the outermost event loop.
1798 
1799  int eventLevel = static_cast<QDeferredDeleteEvent *>(pe.event)->loopLevel();
1800  int loopLevel = data->loopLevel + data->scopeLevel;
1801  const bool allowDeferredDelete =
1802  (eventLevel > loopLevel
1803  || (!eventLevel && loopLevel > 0)
1804  || (event_type == QEvent::DeferredDelete
1805  && eventLevel == loopLevel));
1806  if (!allowDeferredDelete) {
1807  // cannot send deferred delete
1808  if (!event_type && !receiver) {
1809  // we must copy it first; we want to re-post the event
1810  // with the event pointer intact, but we can't delay
1811  // nulling the event ptr until after re-posting, as
1812  // addEvent may invalidate pe.
1813  QPostEvent pe_copy = pe;
1814 
1815  // null out the event so if sendPostedEvents recurses, it
1816  // will ignore this one, as it's been re-posted.
1817  const_cast<QPostEvent &>(pe).event = nullptr;
1818 
1819  // re-post the copied event so it isn't lost
1820  data->postEventList.addEvent(pe_copy);
1821  }
1822  continue;
1823  }
1824  }
1825 
1826  // first, we diddle the event so that we can deliver
1827  // it, and that no one will try to touch it later.
1828  pe.event->m_posted = false;
1829  QEvent *e = pe.event;
1830  QObject * r = pe.receiver;
1831 
1832  --r->d_func()->postedEvents;
1833  Q_ASSERT(r->d_func()->postedEvents >= 0);
1834 
1835  // next, update the data structure so that we're ready
1836  // for the next event.
1837  const_cast<QPostEvent &>(pe).event = nullptr;
1838 
1839  locker.unlock();
1840  const auto relocker = qScopeGuard([&locker] { locker.lock(); });
1841 
1842  QScopedPointer<QEvent> event_deleter(e); // will delete the event (with the mutex unlocked)
1843 
1844  // after all that work, it's time to deliver the event.
1846 
1847  // careful when adding anything below this point - the
1848  // sendEvent() call might invalidate any invariants this
1849  // function depends on.
1850  }
1851 
1852  cleanup.exceptionCaught = false;
1853 }
1854 
1874 void QCoreApplication::removePostedEvents(QObject *receiver, int eventType)
1875 {
1876  auto locker = QCoreApplicationPrivate::lockThreadPostEventList(receiver);
1877  QThreadData *data = locker.threadData;
1878 
1879  // the QObject destructor calls this function directly. this can
1880  // happen while the event loop is in the middle of posting events,
1881  // and when we get here, we may not have any more posted events
1882  // for this object.
1883  if (receiver && !receiver->d_func()->postedEvents)
1884  return;
1885 
1886  //we will collect all the posted events for the QObject
1887  //and we'll delete after the mutex was unlocked
1888  QVarLengthArray<QEvent*> events;
1889  qsizetype n = data->postEventList.size();
1890  qsizetype j = 0;
1891 
1892  for (qsizetype i = 0; i < n; ++i) {
1893  const QPostEvent &pe = data->postEventList.at(i);
1894 
1895  if ((!receiver || pe.receiver == receiver)
1896  && (pe.event && (eventType == 0 || pe.event->type() == eventType))) {
1897  --pe.receiver->d_func()->postedEvents;
1898  pe.event->m_posted = false;
1899  events.append(pe.event);
1900  const_cast<QPostEvent &>(pe).event = nullptr;
1901  } else if (!data->postEventList.recursion) {
1902  if (i != j)
1903  qSwap(data->postEventList[i], data->postEventList[j]);
1904  ++j;
1905  }
1906  }
1907 
1908 #ifdef QT_DEBUG
1909  if (receiver && eventType == 0) {
1910  Q_ASSERT(!receiver->d_func()->postedEvents);
1911  }
1912 #endif
1913 
1914  if (!data->postEventList.recursion) {
1915  // truncate list
1916  data->postEventList.erase(data->postEventList.begin() + j, data->postEventList.end());
1917  }
1918 
1919  locker.unlock();
1920  qDeleteAll(events);
1921 }
1922 
1934 {
1935  if (!event || !event->m_posted)
1936  return;
1937 
1939 
1940  const auto locker = qt_scoped_lock(data->postEventList.mutex);
1941 
1942  if (data->postEventList.size() == 0) {
1943 #if defined(QT_DEBUG)
1944  qDebug("QCoreApplication::removePostedEvent: Internal error: %p %d is posted",
1945  (void*)event, event->type());
1946  return;
1947 #endif
1948  }
1949 
1950  for (const QPostEvent &pe : std::as_const(data->postEventList)) {
1951  if (pe.event == event) {
1952 #ifndef QT_NO_DEBUG
1953  qWarning("QCoreApplication::removePostedEvent: Event of type %d deleted while posted to %s %s",
1954  event->type(),
1955  pe.receiver->metaObject()->className(),
1956  pe.receiver->objectName().toLocal8Bit().data());
1957 #endif
1958  --pe.receiver->d_func()->postedEvents;
1959  pe.event->m_posted = false;
1960  delete pe.event;
1961  const_cast<QPostEvent &>(pe).event = nullptr;
1962  return;
1963  }
1964  }
1965 }
1966 
1971 {
1972  if (e->type() == QEvent::Quit) {
1973  exit(0);
1974  return true;
1975  }
1976  return QObject::event(e);
1977 }
1978 
1980 {
1981  quitLockRef.ref();
1982 }
1983 
1985 {
1986  quitLockRef.deref();
1987 
1988  if (quitLockEnabled && canQuitAutomatically())
1989  quitAutomatically();
1990 }
1991 
1993 {
1994  if (!in_exec)
1995  return false;
1996 
1997  if (quitLockEnabled && quitLockRef.loadRelaxed())
1998  return false;
1999 
2000  return true;
2001 }
2002 
2004 {
2005  Q_Q(QCoreApplication);
2006 
2007  // Explicit requests by the user to quit() is plumbed via the platform
2008  // if possible, and delivers the quit event synchronously. For automatic
2009  // quits we implicitly support cancelling the quit by showing another
2010  // window, which currently relies on removing any posted quit events
2011  // from the event queue. As a result, we can't use the normal quit()
2012  // code path, and need to post manually.
2014 }
2015 
2051 {
2052  if (!self)
2053  return;
2054 
2055  if (!self->d_func()->in_exec)
2056  return;
2057 
2058  self->d_func()->quit();
2059 }
2060 
2062 {
2063  Q_Q(QCoreApplication);
2064 
2065  if (QThread::currentThread() == mainThread()) {
2066  QEvent quitEvent(QEvent::Quit);
2067  QCoreApplication::sendEvent(q, &quitEvent);
2068  } else {
2070  }
2071 }
2072 
2088 #endif // QT_NO_QOBJECT
2089 
2090 #ifndef QT_NO_TRANSLATION
2119 {
2120  if (!translationFile)
2121  return false;
2122 
2123  if (!QCoreApplicationPrivate::checkInstance("installTranslator"))
2124  return false;
2125  QCoreApplicationPrivate *d = self->d_func();
2126  {
2127  QWriteLocker locker(&d->translateMutex);
2128  d->translators.prepend(translationFile);
2129  }
2130 
2131 #ifndef QT_NO_TRANSLATION_BUILDER
2132  if (translationFile->isEmpty())
2133  return false;
2134 #endif
2135 
2136 #ifndef QT_NO_QOBJECT
2138  QCoreApplication::sendEvent(self, &ev);
2139 #endif
2140 
2141  return true;
2142 }
2143 
2155 {
2156  if (!translationFile)
2157  return false;
2158  if (!QCoreApplicationPrivate::checkInstance("removeTranslator"))
2159  return false;
2160  QCoreApplicationPrivate *d = self->d_func();
2161  QWriteLocker locker(&d->translateMutex);
2162  if (d->translators.removeAll(translationFile)) {
2163 #ifndef QT_NO_QOBJECT
2164  locker.unlock();
2165  if (!self->closingDown()) {
2167  QCoreApplication::sendEvent(self, &ev);
2168  }
2169 #endif
2170  return true;
2171  }
2172  return false;
2173 }
2174 
2175 static void replacePercentN(QString *result, int n)
2176 {
2177  if (n >= 0) {
2178  qsizetype percentPos = 0;
2179  qsizetype len = 0;
2180  while ((percentPos = result->indexOf(QLatin1Char('%'), percentPos + len)) != -1) {
2181  len = 1;
2182  if (percentPos + len == result->length())
2183  break;
2184  QString fmt;
2185  if (result->at(percentPos + len) == QLatin1Char('L')) {
2186  ++len;
2187  if (percentPos + len == result->length())
2188  break;
2189  fmt = QLatin1String("%L1");
2190  } else {
2191  fmt = QLatin1String("%1");
2192  }
2193  if (result->at(percentPos + len) == QLatin1Char('n')) {
2194  fmt = fmt.arg(n);
2195  ++len;
2196  result->replace(percentPos, len, fmt);
2197  len = fmt.length();
2198  }
2199  }
2200  }
2201 }
2202 
2235 QString QCoreApplication::translate(const char *context, const char *sourceText,
2236  const char *disambiguation, int n)
2237 {
2238  QString result;
2239 
2240  if (!sourceText)
2241  return result;
2242 
2243  if (self) {
2244  QCoreApplicationPrivate *d = self->d_func();
2245  QReadLocker locker(&d->translateMutex);
2246  if (!d->translators.isEmpty()) {
2248  QTranslator *translationFile;
2249  for (it = d->translators.constBegin(); it != d->translators.constEnd(); ++it) {
2250  translationFile = *it;
2251  result = translationFile->translate(context, sourceText, disambiguation, n);
2252  if (!result.isNull())
2253  break;
2254  }
2255  }
2256  }
2257 
2258  if (result.isNull())
2259  result = QString::fromUtf8(sourceText);
2260 
2261  replacePercentN(&result, n);
2262  return result;
2263 }
2264 
2265 // Declared in qglobal.h
2266 QString qtTrId(const char *id, int n)
2267 {
2268  return QCoreApplication::translate(nullptr, id, nullptr, n);
2269 }
2270 
2272 {
2273  if (!QCoreApplication::self)
2274  return false;
2275  QCoreApplicationPrivate *d = QCoreApplication::self->d_func();
2276  QReadLocker locker(&d->translateMutex);
2277  return d->translators.contains(translator);
2278 }
2279 
2280 #else
2281 
2282 QString QCoreApplication::translate(const char *context, const char *sourceText,
2283  const char *disambiguation, int n)
2284 {
2285  Q_UNUSED(context);
2286  Q_UNUSED(disambiguation);
2287  QString ret = QString::fromUtf8(sourceText);
2288  if (n >= 0)
2289  ret.replace(QLatin1String("%n"), QString::number(n));
2290  return ret;
2291 }
2292 
2293 #endif //QT_NO_TRANSLATION
2294 
2295 // Makes it possible to point QCoreApplication to a custom location to ensure
2296 // the directory is added to the patch, and qt.conf and deployed plugins are
2297 // found from there. This is for use cases in which QGuiApplication is
2298 // instantiated by a library and not by an application executable, for example,
2299 // Active X servers.
2300 
2302 {
2305  else
2307 }
2308 
2329 {
2330  if (!self) {
2331  qWarning("QCoreApplication::applicationDirPath: Please instantiate the QApplication object first");
2332  return QString();
2333  }
2334 
2335  QCoreApplicationPrivate *d = self->d_func();
2336  if (d->cachedApplicationDirPath.isNull())
2337  d->cachedApplicationDirPath = QFileInfo(applicationFilePath()).path();
2338  return d->cachedApplicationDirPath;
2339 }
2340 
2341 #if !defined(Q_OS_WIN) && !defined(Q_OS_DARWIN) // qcoreapplication_win.cpp or qcoreapplication_mac.cpp
2342 static QString qAppFileName()
2343 {
2344 # if defined(Q_OS_ANDROID)
2345  // the actual process on Android is the Java VM, so this doesn't help us
2346  return QString();
2347 # elif defined(Q_OS_LINUX)
2348  // this includes the Embedded Android builds
2349  return QFile::decodeName(qt_readlink("/proc/self/exe"));
2350 # elif defined(AT_EXECPATH)
2351  // seen on FreeBSD, but I suppose the other BSDs could adopt this API
2352  char execfn[PATH_MAX];
2353  if (elf_aux_info(AT_EXECPATH, execfn, sizeof(execfn)) != 0)
2354  execfn[0] = '\0';
2355 
2356  qsizetype len = qstrlen(execfn);
2358 # else
2359  // other OS or something
2360  return QString();
2361 #endif
2362 }
2363 #endif
2364 
2381 {
2382  if (!self) {
2383  qWarning("QCoreApplication::applicationFilePath: Please instantiate the QApplication object first");
2384  return QString();
2385  }
2386 
2387  QCoreApplicationPrivate *d = self->d_func();
2388 
2389  if (d->argc) {
2390  static QByteArray procName = QByteArray(d->argv[0]);
2391  if (procName != d->argv[0]) {
2392  // clear the cache if the procname changes, so we reprocess it.
2394  procName = QByteArray(d->argv[0]);
2395  }
2396  }
2397 
2400 
2401  QString absPath = qAppFileName();
2402  if (absPath.isEmpty() && !arguments().isEmpty()) {
2403  QString argv0 = QFile::decodeName(arguments().at(0).toLocal8Bit());
2404 
2405  if (!argv0.isEmpty() && argv0.at(0) == QLatin1Char('/')) {
2406  /*
2407  If argv0 starts with a slash, it is already an absolute
2408  file path.
2409  */
2410  absPath = argv0;
2411  } else if (argv0.contains(QLatin1Char('/'))) {
2412  /*
2413  If argv0 contains one or more slashes, it is a file path
2414  relative to the current directory.
2415  */
2416  absPath = QDir::current().absoluteFilePath(argv0);
2417  } else {
2418  /*
2419  Otherwise, the file path has to be determined using the
2420  PATH environment variable.
2421  */
2422  absPath = QStandardPaths::findExecutable(argv0);
2423  }
2424  }
2425 
2426  absPath = QFileInfo(absPath).canonicalFilePath();
2427  if (!absPath.isEmpty()) {
2430  }
2431  return QString();
2432 }
2433 
2440 {
2441 #if defined(Q_OS_WIN)
2442  return GetCurrentProcessId();
2443 #elif defined(Q_OS_VXWORKS)
2444  return (pid_t) taskIdCurrent;
2445 #else
2446  return getpid();
2447 #endif
2448 }
2449 
2482 {
2483  QStringList list;
2484 
2485  if (!self) {
2486  qWarning("QCoreApplication::arguments: Please instantiate the QApplication object first");
2487  return list;
2488  }
2489 
2490  const QCoreApplicationPrivate *d = self->d_func();
2491 
2492  const int argc = d->argc;
2493  char ** const argv = d->argv;
2494  list.reserve(argc);
2495 
2496 #if defined(Q_OS_WIN)
2497  const bool argsModifiedByUser = d->origArgv == nullptr;
2498  if (!argsModifiedByUser) {
2499  // On Windows, it is possible to pass Unicode arguments on
2500  // the command line, but we don't implement any of the wide
2501  // entry-points (wmain/wWinMain), so get the arguments from
2502  // the Windows API instead of using argv. Note that we only
2503  // do this when argv were not modified by the user in main().
2504  QString cmdline = QString::fromWCharArray(GetCommandLine());
2505  QStringList commandLineArguments = qWinCmdArgs(cmdline);
2506 
2507  // Even if the user didn't modify argv before passing them
2508  // on to QCoreApplication, derived QApplications might have.
2509  // If that's the case argc will differ from origArgc.
2510  if (argc != d->origArgc) {
2511  // Note: On MingGW the arguments from GetCommandLine are
2512  // not wildcard expanded (if wildcard expansion is enabled),
2513  // as opposed to the arguments in argv. This means we can't
2514  // compare commandLineArguments to argv/origArgc, but
2515  // must remove elements by value, based on whether they
2516  // were filtered out from argc.
2517  for (int i = 0; i < d->origArgc; ++i) {
2518  if (!contains(argc, argv, d->origArgv[i]))
2519  commandLineArguments.removeAll(QString::fromLocal8Bit(d->origArgv[i]));
2520  }
2521  }
2522 
2523  return commandLineArguments;
2524  } // Fall back to rebuilding from argv/argc when a modified argv was passed.
2525 #endif // defined(Q_OS_WIN)
2526 
2527  for (int a = 0; a < argc; ++a)
2528  list << QString::fromLocal8Bit(argv[a]);
2529 
2530  return list;
2531 }
2532 
2558 {
2559  if (coreappdata()->orgName == orgName)
2560  return;
2561  coreappdata()->orgName = orgName;
2562 #ifndef QT_NO_QOBJECT
2563  if (QCoreApplication::self)
2564  emit QCoreApplication::self->organizationNameChanged();
2565 #endif
2566 }
2567 
2569 {
2570  return coreappdata()->orgName;
2571 }
2572 
2595 {
2596  if (coreappdata()->orgDomain == orgDomain)
2597  return;
2598  coreappdata()->orgDomain = orgDomain;
2599 #ifndef QT_NO_QOBJECT
2600  if (QCoreApplication::self)
2601  emit QCoreApplication::self->organizationDomainChanged();
2602 #endif
2603 }
2604 
2606 {
2607  return coreappdata()->orgDomain;
2608 }
2609 
2629 {
2630  coreappdata()->applicationNameSet = !application.isEmpty();
2631  QString newAppName = application;
2632  if (newAppName.isEmpty() && QCoreApplication::self)
2633  newAppName = QCoreApplication::self->d_func()->appName();
2634  if (coreappdata()->application == newAppName)
2635  return;
2636  coreappdata()->application = newAppName;
2637 #ifndef QT_NO_QOBJECT
2638  if (QCoreApplication::self)
2639  emit QCoreApplication::self->applicationNameChanged();
2640 #endif
2641 }
2642 
2644 {
2645  return coreappdata() ? coreappdata()->application : QString();
2646 }
2647 
2682 {
2683  coreappdata()->applicationVersionSet = !version.isEmpty();
2684  QString newVersion = version;
2685  if (newVersion.isEmpty() && QCoreApplication::self)
2686  newVersion = QCoreApplication::self->d_func()->appVersion();
2687  if (coreappdata()->applicationVersion == newVersion)
2688  return;
2689  coreappdata()->applicationVersion = newVersion;
2690 #ifndef QT_NO_QOBJECT
2691  if (QCoreApplication::self)
2692  emit QCoreApplication::self->applicationVersionChanged();
2693 #endif
2694 }
2695 
2697 {
2698  return coreappdata() ? coreappdata()->applicationVersion : QString();
2699 }
2700 
2701 #if QT_CONFIG(library)
2702 
2703 Q_GLOBAL_STATIC(QRecursiveMutex, libraryPathMutex)
2704 
2705 
2739 QStringList QCoreApplication::libraryPaths()
2740 {
2741  QMutexLocker locker(libraryPathMutex());
2742  return libraryPathsLocked();
2743 }
2744 
2748 QStringList QCoreApplication::libraryPathsLocked()
2749 {
2750  if (coreappdata()->manual_libpaths)
2751  return *(coreappdata()->manual_libpaths);
2752 
2753  if (!coreappdata()->app_libpaths) {
2754  QStringList *app_libpaths = new QStringList;
2755  coreappdata()->app_libpaths.reset(app_libpaths);
2756 
2757  auto setPathsFromEnv = [&](QString libPathEnv) {
2758  if (!libPathEnv.isEmpty()) {
2760  for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) {
2761  QString canonicalPath = QDir(*it).canonicalPath();
2762  if (!canonicalPath.isEmpty()
2763  && !app_libpaths->contains(canonicalPath)) {
2764  app_libpaths->append(canonicalPath);
2765  }
2766  }
2767  }
2768  };
2769  setPathsFromEnv(qEnvironmentVariable("QT_PLUGIN_PATH"));
2770 #ifdef Q_OS_ANDROID
2771  setPathsFromEnv(qEnvironmentVariable("QT_BUNDLED_LIBS_PATH"));
2772 #endif
2773 #ifdef Q_OS_DARWIN
2774  // Check the main bundle's PlugIns directory as this is a standard location for Apple OSes.
2775  // Note that the QLibraryInfo::PluginsPath below will coincidentally be the same as this value
2776  // but with a different casing, so it can't be relied upon when the underlying filesystem
2777  // is case sensitive (and this is always the case on newer OSes like iOS).
2778  if (CFBundleRef bundleRef = CFBundleGetMainBundle()) {
2779  if (QCFType<CFURLRef> urlRef = CFBundleCopyBuiltInPlugInsURL(bundleRef)) {
2780  if (QCFType<CFURLRef> absoluteUrlRef = CFURLCopyAbsoluteURL(urlRef)) {
2781  if (QCFString path = CFURLCopyFileSystemPath(absoluteUrlRef, kCFURLPOSIXPathStyle)) {
2782  if (QFile::exists(path)) {
2783  path = QDir(path).canonicalPath();
2784  if (!app_libpaths->contains(path))
2785  app_libpaths->append(path);
2786  }
2787  }
2788  }
2789  }
2790  }
2791 #endif // Q_OS_DARWIN
2792 
2794  if (QFile::exists(installPathPlugins)) {
2795  // Make sure we convert from backslashes to slashes.
2796  installPathPlugins = QDir(installPathPlugins).canonicalPath();
2797  if (!app_libpaths->contains(installPathPlugins))
2798  app_libpaths->append(installPathPlugins);
2799  }
2800 
2801  // If QCoreApplication is not yet instantiated,
2802  // make sure we add the application path when we construct the QCoreApplication
2803  if (self) self->d_func()->appendApplicationPathToLibraryPaths();
2804  }
2805  return *(coreappdata()->app_libpaths);
2806 }
2807 
2808 
2809 
2822 void QCoreApplication::setLibraryPaths(const QStringList &paths)
2823 {
2824  QMutexLocker locker(libraryPathMutex());
2825 
2826  // setLibraryPaths() is considered a "remove everything and then add some new ones" operation.
2827  // When the application is constructed it should still amend the paths. So we keep the originals
2828  // around, and even create them if they don't exist, yet.
2829  if (!coreappdata()->app_libpaths)
2830  libraryPathsLocked();
2831 
2832  if (coreappdata()->manual_libpaths)
2833  *(coreappdata()->manual_libpaths) = paths;
2834  else
2835  coreappdata()->manual_libpaths.reset(new QStringList(paths));
2836 
2837  locker.unlock();
2838  QFactoryLoader::refreshAll();
2839 }
2840 
2857 void QCoreApplication::addLibraryPath(const QString &path)
2858 {
2859  if (path.isEmpty())
2860  return;
2861 
2862  QString canonicalPath = QDir(path).canonicalPath();
2863  if (canonicalPath.isEmpty())
2864  return;
2865 
2866  QMutexLocker locker(libraryPathMutex());
2867 
2868  QStringList *libpaths = coreappdata()->manual_libpaths.get();
2869  if (libpaths) {
2870  if (libpaths->contains(canonicalPath))
2871  return;
2872  } else {
2873  // make sure that library paths are initialized
2874  libraryPathsLocked();
2875  QStringList *app_libpaths = coreappdata()->app_libpaths.get();
2876  if (app_libpaths->contains(canonicalPath))
2877  return;
2878 
2879  coreappdata()->manual_libpaths.reset(libpaths = new QStringList(*app_libpaths));
2880  }
2881 
2882  libpaths->prepend(canonicalPath);
2883  locker.unlock();
2884  QFactoryLoader::refreshAll();
2885 }
2886 
2896 void QCoreApplication::removeLibraryPath(const QString &path)
2897 {
2898  if (path.isEmpty())
2899  return;
2900 
2901  QString canonicalPath = QDir(path).canonicalPath();
2902  if (canonicalPath.isEmpty())
2903  return;
2904 
2905  QMutexLocker locker(libraryPathMutex());
2906 
2907  QStringList *libpaths = coreappdata()->manual_libpaths.get();
2908  if (libpaths) {
2909  if (libpaths->removeAll(canonicalPath) == 0)
2910  return;
2911  } else {
2912  // make sure that library paths is initialized
2913  libraryPathsLocked();
2914  QStringList *app_libpaths = coreappdata()->app_libpaths.get();
2915  if (!app_libpaths->contains(canonicalPath))
2916  return;
2917 
2918  coreappdata()->manual_libpaths.reset(libpaths = new QStringList(*app_libpaths));
2919  libpaths->removeAll(canonicalPath);
2920  }
2921 
2922  locker.unlock();
2923  QFactoryLoader::refreshAll();
2924 }
2925 
2926 #endif // QT_CONFIG(library)
2927 
2928 #ifndef QT_NO_QOBJECT
2929 
2960 {
2962  qWarning("Native event filters are not applied when the Qt::AA_PluginApplication attribute is set");
2963  return;
2964  }
2965 
2967  if (!filterObj || !eventDispatcher)
2968  return;
2970 }
2971 
2986 {
2988  if (!filterObject || !eventDispatcher)
2989  return;
2991 }
2992 
2998 {
2999  if (QCoreApplicationPrivate::theMainThread.loadAcquire())
3001  return nullptr;
3002 }
3003 
3011 {
3013  if (!mainThread)
3014  mainThread = QThread::currentThread(); // will also setup theMainThread
3015  mainThread->setEventDispatcher(eventDispatcher);
3016 }
3017 
3018 #endif // QT_NO_QOBJECT
3019 
3129 void *QCoreApplication::resolveInterface(const char *name, int revision) const
3130 {
3131  Q_UNUSED(name); Q_UNUSED(revision);
3132  return nullptr;
3133 }
3134 
3136 
3137 #ifndef QT_NO_QOBJECT
3138 #include "moc_qcoreapplication.cpp"
3139 #endif
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
The QAbstractEventDispatcher class provides an interface to manage Qt's event queue.
static QAbstractEventDispatcher * instance(QThread *thread=nullptr)
virtual void wakeUp()=0
void installNativeEventFilter(QAbstractNativeEventFilter *filterObj)
void removeNativeEventFilter(QAbstractNativeEventFilter *filterObj)
The QAbstractNativeEventFilter class provides an interface for receiving native events,...
Type loadAcquire() const noexcept
Definition: qbasicatomic.h:233
Type loadRelaxed() const noexcept
Definition: qbasicatomic.h:226
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
char * data()
Definition: qbytearray.h:516
const char * constData() const noexcept
Definition: qbytearray.h:144
qsizetype indexOf(char c, qsizetype from=0) const
void truncate(qsizetype pos)
bool isEmpty() const noexcept
Definition: qbytearray.h:129
static QByteArray fromRawData(const char *data, qsizetype size)
Definition: qbytearray.h:396
The QCommandLineOption class defines a possible command-line option. \inmodule QtCore.
The QCoreApplication class provides an event loop for Qt applications without UI.
void * resolveInterface(const char *name, int revision) const
static QAbstractEventDispatcher * eventDispatcher()
static QString applicationFilePath()
static QCoreApplication * instance()
void organizationDomainChanged()
static bool sendEvent(QObject *receiver, QEvent *event)
static bool isSetuidAllowed()
bool event(QEvent *) override
static void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
virtual bool compressEvent(QEvent *, QObject *receiver, QPostEventList *)
void removeNativeEventFilter(QAbstractNativeEventFilter *filterObj)
virtual bool notify(QObject *, QEvent *)
static void removePostedEvents(QObject *receiver, int eventType=0)
void qRemovePostRoutine(QtCleanUpFunction ptr)
static void processEvents(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
static void setOrganizationDomain(const QString &orgDomain)
void applicationNameChanged()
static bool isQuitLockEnabled()
void organizationNameChanged()
static void setAttribute(Qt::ApplicationAttribute attribute, bool on=true)
[95]
QString applicationVersion
the version of this application
static bool closingDown()
void qAddPostRoutine(QtCleanUpFunction ptr)
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
void installNativeEventFilter(QAbstractNativeEventFilter *filterObj)
static bool testAttribute(Qt::ApplicationAttribute attribute)
QString organizationName
the name of the organization that wrote this application
static void setOrganizationName(const QString &orgName)
[11]
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
static QString applicationDirPath()
static void setApplicationName(const QString &application)
static bool installTranslator(QTranslator *messageFile)
static bool startingUp()
static qint64 applicationPid() Q_DECL_CONST_FUNCTION
static void setApplicationVersion(const QString &version)
static bool removeTranslator(QTranslator *messageFile)
static QStringList arguments()
static void setQuitLockEnabled(bool enabled)
QString applicationName
the name of this application
void applicationVersionChanged()
static void setSetuidAllowed(bool allow)
static void sendPostedEvents(QObject *receiver=nullptr, int event_type=0)
static void exit(int retcode=0)
bool quitLockEnabled
Whether the use of the QEventLoopLocker feature can cause the application to quit.
QString organizationDomain
the Internet domain of the organization that wrote this application
static bool checkInstance(const char *method)
static bool isTranslatorInstalled(QTranslator *translator)
void appendApplicationPathToLibraryPaths(void)
static QPostEventListLocker lockThreadPostEventList(QObject *object)
static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data)
bool sendThroughApplicationEventFilters(QObject *, QEvent *)
static QAbstractEventDispatcher * eventDispatcher
static QString * cachedApplicationFilePath
virtual void eventDispatcherReady()
static bool sendThroughObjectEventFilters(QObject *, QEvent *)
static QBasicAtomicPointer< QThread > theMainThread
static void checkReceiverThread(QObject *receiver)
static bool testAttribute(uint flag)
virtual void createEventDispatcher()
static void clearApplicationFilePath()
static QThread * mainThread()
static void removePostedEvent(QEvent *)
QCoreApplicationPrivate(int &aargc, char **aargv, uint flags)
virtual bool canQuitAutomatically()
static void setApplicationFilePath(const QString &path)
static bool threadRequiresCoreApplication()
static bool notify_helper(QObject *, QEvent *)
int loopLevel() const
Definition: qcoreevent.h:420
The QDir class provides access to directory structures and their contents.
Definition: qdir.h:55
static QDir current()
Definition: qdir.h:244
QString canonicalPath() const
Definition: qdir.cpp:683
QString absoluteFilePath(const QString &fileName) const
Definition: qdir.cpp:796
constexpr static QChar listSeparator() noexcept
Definition: qdir.h:225
The QElapsedTimer class provides a fast way to calculate elapsed times.
Definition: qelapsedtimer.h:49
The QEvent class is the base class of all event classes. Event objects contain event parameters.
Definition: qcoreevent.h:58
@ DeferredDelete
Definition: qcoreevent.h:113
@ LanguageChange
Definition: qcoreevent.h:136
@ Timer
Definition: qcoreevent.h:72
@ Quit
Definition: qcoreevent.h:92
Type type() const
Definition: qcoreevent.h:307
The QEventLoop class provides a means of entering and leaving an event loop.
Definition: qeventloop.h:50
int exec(ProcessEventsFlags flags=AllEvents)
Definition: qeventloop.cpp:162
@ ApplicationExec
Definition: qeventloop.h:66
@ WaitForMoreEvents
Definition: qeventloop.h:62
void exit(int returnCode=0)
Definition: qeventloop.cpp:269
static QString decodeName(const QByteArray &localFileName)
Definition: qfile.h:163
bool exists() const
Definition: qfile.cpp:376
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:57
QString canonicalFilePath() const
Definition: qfileinfo.cpp:573
QString path() const
Definition: qfileinfo.cpp:634
static bool activateCallbacks(Callback, void **)
Definition: qglobal.cpp:4277
@ EventNotifyCallback
Definition: qnamespace.h:1862
A convenience wrapper around the Java Native Interface (JNI).
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
static QString path(LibraryPath p)
qsizetype size() const noexcept
Definition: qlist.h:414
bool isEmpty() const noexcept
Definition: qlist.h:418
void append(parameter_type t)
Definition: qlist.h:469
static QLoggingRegistry * instance()
The QMutex class provides access serialization between threads.
Definition: qmutex.h:285
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes.
Definition: qmutex.h:317
uint deleteLaterCalled
Definition: qobject.h:109
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
QObject * parent() const
Definition: qobject.h:409
void moveToThread(QThread *thread)
Definition: qobject.cpp:1572
QString objectName
the name of this object
Definition: qobject.h:129
virtual bool event(QEvent *event)
Definition: qobject.cpp:1329
void setParent(QObject *parent)
Definition: qobject.cpp:2108
friend class QCoreApplication
Definition: qobject.h:443
QThread * thread() const
Definition: qobject.cpp:1527
QScopedPointer< QObjectData > d_ptr
Definition: qobject.h:436
bool isWidgetType() const
Definition: qobject.h:148
static QObjectPrivate * get(QObject *o)
Definition: qobject_p.h:368
QAtomicPointer< QThreadData > threadData
Definition: qobject_p.h:420
Definition: qthread_p.h:76
QObject * receiver
Definition: qthread_p.h:78
QEvent * event
Definition: qthread_p.h:79
Definition: qthread_p.h:98
qsizetype startOffset
Definition: qthread_p.h:104
QMutex mutex
Definition: qthread_p.h:108
The QReadLocker class is a convenience class that simplifies locking and unlocking read-write locks f...
The QRecursiveMutex class provides access serialization between threads.
Definition: qmutex.h:313
The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon dest...
static QString findExecutable(const QString &executableName, const QStringList &paths=QStringList())
The QString class provides a Unicode character string.
Definition: qstring.h:388
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition: qstring.h:514
void truncate(qsizetype pos)
Definition: qstring.cpp:5934
static QString fromLocal8Bit(QByteArrayView ba)
Definition: qstring.cpp:5563
static QString fromUtf8(QByteArrayView utf8)
Definition: qstring.cpp:5632
const QChar at(qsizetype i) const
Definition: qstring.h:1212
bool isEmpty() const
Definition: qstring.h:1216
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=QLatin1Char(' ')) const
Definition: qstring.cpp:8318
QByteArray toLocal8Bit() const &
Definition: qstring.h:753
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.h:1353
static QString number(int, int base=10)
Definition: qstring.cpp:7538
static QString static QString asprintf(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
Definition: qstring.cpp:6759
qsizetype length() const
Definition: qstring.h:415
The QStringList class provides a list of strings.
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
Definition: qthread.cpp:908
bool quitNow
Definition: qthread_p.h:302
QStack< QEventLoop * > eventLoops
Definition: qthread_p.h:294
static QThreadData * get2(QThread *thread)
Definition: qthread_p.h:244
QPostEventList postEventList
Definition: qthread_p.h:295
QAbstractEventDispatcher * eventDispatcher() const
Definition: qthread.cpp:967
static QThread * currentThread()
Definition: qthread.cpp:879
void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
Definition: qthread.cpp:985
The QThreadPool class manages a collection of QThreads.
Definition: qthreadpool.h:56
static QThreadPool * globalInstance()
bool waitForDone(int msecs=-1)
The QTimerEvent class contains parameters that describe a timer event.
Definition: qcoreevent.h:367
The QTranslator class provides internationalization support for text output.
Definition: qtranslator.h:55
virtual bool isEmpty() const
virtual QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
constexpr size_type size() const noexcept
void append(const T &t)
The QWriteLocker class is a convenience class that simplifies locking and unlocking read-write locks ...
void unlock() noexcept
uid_t getuid(void)
Definition: qplatformdefs.h:93
uid_t geteuid(void)
Definition: qplatformdefs.h:86
#define PATH_MAX
qSwap(pi, e)
qDeleteAll(list.begin(), list.end())
double e
set contains("Julia")
int const char * version
Definition: zlib.h:814
else
Definition: ftgrays.c:1658
#define forever
Definition: ftrandom.c:53
typename C::const_iterator const_iterator
typename C::iterator iterator
void(* StartupCallback)()
Definition: qhooks_p.h:76
@ Startup
Definition: qhooks_p.h:69
std::chrono::milliseconds ms
Lock qt_scoped_lock(Mutex &mutex)
Definition: qlocking_p.h:94
Lock qt_unique_lock(Mutex &mutex)
Definition: qlocking_p.h:100
QFuture< typename std::decay_t< Sequence >::value_type > filtered(QThreadPool *pool, Sequence &&sequence, KeepFunctor &&keep)
ApplicationAttribute
Definition: qnamespace.h:449
@ AA_UseSoftwareOpenGL
Definition: qnamespace.h:471
@ AA_UseDesktopOpenGL
Definition: qnamespace.h:469
@ AA_SynthesizeMouseForUnhandledTabletEvents
Definition: qnamespace.h:484
@ AA_ShareOpenGLContexts
Definition: qnamespace.h:472
@ AA_PluginApplication
Definition: qnamespace.h:455
@ AA_UseOpenGLES
Definition: qnamespace.h:470
@ AA_SynthesizeMouseForUnhandledTouchEvents
Definition: qnamespace.h:462
@ SkipEmptyParts
Definition: qnamespace.h:153
void initBindingStatusThreadId()
Definition: qproperty.cpp:2249
#define QString()
Definition: parse-defines.h:51
int PRIV() strcmp(PCRE2_SPTR str1, PCRE2_SPTR str2)
int PRIV() strncmp(PCRE2_SPTR str1, PCRE2_SPTR str2, size_t len)
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld endif[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld SRC pixld MASK if DST_R else pixld DST_R endif if
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
[3]
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld cleanup[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld SRC pixld MASK if DST_R else pixld DST_R endif if src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head if pixblock_size cache_preload_simple endif process_pixblock_tail pixinterleave dst_w_basereg irp if pixblock_size chunk_size tst beq if DST_W else pixst DST_W else mov ORIG_W endif add lsl if lsl endif if lsl endif lsl endif lsl endif lsl endif subs mov DST_W if regs_shortage str endif bge start_of_loop_label endm macro generate_composite_function
#define Q_BASIC_ATOMIC_INITIALIZER(a)
size_t qstrlen(const char *str)
#define Q_UNLIKELY(x)
#define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N)
QList< QString > QStringList
Definition: qcontainerfwd.h:64
QT_BEGIN_NAMESPACE QByteArray qt_readlink(const char *path)
Definition: qcore_unix.cpp:59
void qAddPreRoutine(QtStartUpFunction p)
QString qAppName()
QString qtTrId(const char *id, int n)
Q_CORE_EXPORT uint qGlobalPostedEventsCount()
QList< QtStartUpFunction > QStartUpFuncList
void Q_CORE_EXPORT qt_startup_hook()
void Q_CORE_EXPORT qt_call_post_routines()
void(* QtCleanUpFunction)()
void(* QtStartUpFunction)()
#define qApp
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint attribute
QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
Definition: qglobal.cpp:3493
#define QT_VERSION_CHECK(major, minor, patch)
Definition: qglobal.h:62
ptrdiff_t qsizetype
Definition: qglobal.h:308
unsigned int uint
Definition: qglobal.h:334
long long qint64
Definition: qglobal.h:298
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
QT_BEGIN_NAMESPACE quintptr Q_CORE_EXPORT qtHookData[]
Definition: qhooks.cpp:45
#define qDebug
[1]
Definition: qlogging.h:177
#define qWarning
Definition: qlogging.h:179
#define qFatal
Definition: qlogging.h:181
GLboolean GLboolean GLboolean b
GLenum GLuint GLint level
GLboolean r
[2]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLfloat GLfloat f
GLsizei const GLuint * paths
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLuint name
GLfloat n
struct _cl_event * event
Definition: qopenglext.h:2998
GLhandleARB obj
[2]
Definition: qopenglext.h:4164
GLuint GLfloat * val
Definition: qopenglext.h:1513
GLenum GLsizei len
Definition: qopenglext.h:3292
GLdouble GLdouble t
[9]
Definition: qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition: qopenglext.h:259
GLsizei const GLchar *const * path
Definition: qopenglext.h:4283
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
#define Q_ASSERT_X(cond, x, msg)
Definition: qrandom.cpp:85
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition: qscopeguard.h:93
SSL_CTX int(*) void arg)
QString qAppFileName()
#define QStringLiteral(str)
#define emit
Definition: qtmetamacros.h:85
#define Q_TRACE_SCOPE(x,...)
Definition: qtrace_p.h:138
#define Q_TRACE(x,...)
Definition: qtrace_p.h:136
#define Q_TRACE_EXIT(x,...)
Definition: qtrace_p.h:137
#define enabled
Definition: qopenglext.h:3098
Q_UNUSED(salary)
[21]
QThreadPool pool
QObject::connect nullptr
QAction * at
QStringList::Iterator it
QStringList list
[0]
QThreadData * threadData
std::unique_lock< QMutex > locker
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:53
Global global
Definition: main.cpp:114