1 /* This file is part of the KDE libraries
2 Copyright (C) 1999 Sirtaj Singh Kanq <taj@kde.org>
3 Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18 */
19 #ifndef _KGLOBAL_H
20 #define _KGLOBAL_H
21
22 #include <kdelibs4support_export.h>
23
24 #ifdef KDELIBS4SUPPORT_NO_DEPRECATED_NOISE
25 #warning "This file is deprecated."
26 #endif
27
28 #include <QAtomicPointer>
29 #include <sys/types.h>
30 #include <QDebug>
31 // To simplify Qt5 porting in KDE code not yet ported to frameworks.
32 #include <QMimeData>
33 #include <klocale.h>
34
35 // TODO: Re-add for source compat: #include <kdemacros.h>
36
37 //
38 // WARNING!!
39 // This code uses undocumented Qt API
40 // Do not copy it to your application! Use only the functions that are here!
41 // Otherwise, it could break when a new version of Qt ships.
42 //
43
44 class KComponentData;
45 class KCharsets;
46 class KConfig;
47 class KStandardDirs;
48 class KSharedConfig;
49 template <typename T>
50 class QExplicitlySharedDataPointer;
51 typedef QExplicitlySharedDataPointer<KSharedConfig> KSharedConfigPtr;
52
53 /// @cond InternalDocs
54
55 /**
56 * @internal
57 */
58 typedef void (*KdeCleanUpFunction)();
59
60 /**
61 * @internal
62 *
63 * Helper class for K_GLOBAL_STATIC to clean up the object on library unload or application
64 * shutdown.
65 */
66 class KCleanUpGlobalStatic
67 {
68 public:
69 KdeCleanUpFunction func;
70
~KCleanUpGlobalStatic()71 inline ~KCleanUpGlobalStatic()
72 {
73 func();
74 }
75 };
76
77 #ifdef Q_CC_MSVC
78 /**
79 * @internal
80 *
81 * MSVC seems to give anonymous structs the same name which fails at link time. So instead we name
82 * the struct and hope that by adding the line number to the name it's unique enough to never clash.
83 */
84 # define K_GLOBAL_STATIC_STRUCT_NAME(NAME) _k_##NAME##__LINE__
85 #else
86 /**
87 * @internal
88 *
89 * Make the struct of the K_GLOBAL_STATIC anonymous.
90 */
91 # define K_GLOBAL_STATIC_STRUCT_NAME(NAME)
92 #endif
93
94 /// @endcond
95
96 /**
97 * This macro makes it easy to use non-POD types as global statics.
98 * The object is created on first use and creation is threadsafe.
99 *
100 * The object is destructed on library unload or application exit.
101 * Be careful with calling other objects in the destructor of the class
102 * as you have to be sure that they (or objects they depend on) are not already destructed.
103 *
104 * @param TYPE The type of the global static object. Do not add a *.
105 * @param NAME The name of the function to get a pointer to the global static object.
106 *
107 * If you have code that might be called after the global object has been destroyed you can check
108 * for that using the isDestroyed() function.
109 *
110 * If needed (If the destructor of the global object calls other functions that depend on other
111 * global statics (e.g. KConfig::sync) your destructor has to be called before those global statics
112 * are destroyed. A Qt post routine does that.) you can also install a post routine (qAddPostRoutine) to clean up the object
113 * using the destroy() method. If you registered a post routine and the object is destroyed because
114 * of a lib unload you have to call qRemovePostRoutine!
115 *
116 * Example:
117 * @code
118 * class A {
119 * public:
120 * ~A();
121 * ...
122 * };
123 *
124 * K_GLOBAL_STATIC(A, globalA)
125 * // The above creates a new globally static variable named 'globalA' which you
126 * // can use as a pointer to an instance of A.
127 *
128 * void doSomething()
129 * {
130 * // The first time you access globalA a new instance of A will be created automatically.
131 * A *a = globalA;
132 * ...
133 * }
134 *
135 * void doSomethingElse()
136 * {
137 * if (globalA.isDestroyed()) {
138 * return;
139 * }
140 * A *a = globalA;
141 * ...
142 * }
143 *
144 * void installPostRoutine()
145 * {
146 * // A post routine can be used to delete the object when QCoreApplication destructs,
147 * // not adding such a post routine will delete the object normally at program unload
148 * qAddPostRoutine(globalA.destroy);
149 * }
150 *
151 * A::~A()
152 * {
153 * // When you install a post routine you have to remove the post routine from the destructor of
154 * // the class used as global static!
155 * qRemovePostRoutine(globalA.destroy);
156 * }
157 * @endcode
158 *
159 * A common case for the need of deletion on lib unload/app shutdown are Singleton classes. Here's
160 * an example how to do it:
161 * @code
162 * class MySingletonPrivate;
163 * class EXPORT_MACRO MySingleton
164 * {
165 * friend class MySingletonPrivate;
166 * public:
167 * static MySingleton *self();
168 * QString someFunction();
169 *
170 * private:
171 * MySingleton();
172 * ~MySingleton();
173 * };
174 * @endcode
175 * in the .cpp file:
176 * @code
177 * // This class will be instantiated and referenced as a singleton in this example
178 * class MySingletonPrivate
179 * {
180 * public:
181 * QString foo;
182 * MySingleton instance;
183 * };
184 *
185 * K_GLOBAL_STATIC(MySingletonPrivate, mySingletonPrivate)
186 *
187 * MySingleton *MySingleton::self()
188 * {
189 * // returns the singleton; automatically creates a new instance if that has not happened yet.
190 * return &mySingletonPrivate->instance;
191 * }
192 * QString MySingleton::someFunction()
193 * {
194 * // Refencing the singleton directly is possible for your convenience
195 * return mySingletonPrivate->foo;
196 * }
197 * @endcode
198 *
199 * Instead of the above you can use also the following pattern (ignore the name of the namespace):
200 * @code
201 * namespace MySingleton
202 * {
203 * EXPORT_MACRO QString someFunction();
204 * }
205 * @endcode
206 * in the .cpp file:
207 * @code
208 * class MySingletonPrivate
209 * {
210 * public:
211 * QString foo;
212 * };
213 *
214 * K_GLOBAL_STATIC(MySingletonPrivate, mySingletonPrivate)
215 *
216 * QString MySingleton::someFunction()
217 * {
218 * return mySingletonPrivate->foo;
219 * }
220 * @endcode
221 *
222 * Now code that wants to call someFunction() doesn't have to do
223 * @code
224 * MySingleton::self()->someFunction();
225 * @endcode
226 * anymore but instead:
227 * @code
228 * MySingleton::someFunction();
229 * @endcode
230 *
231 * @ingroup KDEMacros
232 */
233 #define K_GLOBAL_STATIC(TYPE, NAME) K_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ())
234
235 /**
236 * @overload
237 * This is the same as K_GLOBAL_STATIC, but can take arguments that are passed
238 * to the object's constructor
239 *
240 * @param TYPE The type of the global static object. Do not add a *.
241 * @param NAME The name of the function to get a pointer to the global static object.
242 * @param ARGS the list of arguments, between brackets
243 *
244 * Example:
245 * @code
246 * class A
247 * {
248 * public:
249 * A(const char *s, int i);
250 * ...
251 * };
252 *
253 * K_GLOBAL_STATIC_WITH_ARGS(A, globalA, ("foo", 0))
254 * // The above creates a new globally static variable named 'globalA' which you
255 * // can use as a pointer to an instance of A.
256 *
257 * void doSomething()
258 * {
259 * // The first time you access globalA a new instance of A will be created automatically.
260 * A *a = globalA;
261 * ...
262 * }
263 * @endcode
264 *
265 * @ingroup KDEMacros
266 */
267
268 // In Qt5 QBasicAtomicPointer<T> no longer implicit casts to T*
269 // Instead it has load() and store() methods which do not exist in Qt4.
270 // In practice, we should be porting frameworks to the new Q_GLOBAL_STATIC
271 // which isn't in Qt5 yet, so duplicate for now.
272
273 #define K_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
274 static QBasicAtomicPointer<TYPE > _k_static_##NAME = Q_BASIC_ATOMIC_INITIALIZER(nullptr); \
275 static bool _k_static_##NAME##_destroyed; \
276 static struct K_GLOBAL_STATIC_STRUCT_NAME(NAME) \
277 { \
278 inline bool isDestroyed() const \
279 { \
280 return _k_static_##NAME##_destroyed; \
281 } \
282 inline bool exists() const \
283 { \
284 return _k_static_##NAME.load() != nullptr; \
285 } \
286 inline operator TYPE*() \
287 { \
288 return operator->(); \
289 } \
290 inline TYPE *operator->() \
291 { \
292 if (!_k_static_##NAME.load()) { \
293 if (isDestroyed()) { \
294 qFatal("Fatal Error: Accessed global static '%s *%s()' after destruction. " \
295 "Defined at %s:%d", #TYPE, #NAME, __FILE__, __LINE__); \
296 } \
297 TYPE *x = new TYPE ARGS; \
298 if (!_k_static_##NAME.testAndSetOrdered(nullptr, x) \
299 && _k_static_##NAME.load() != x ) { \
300 delete x; \
301 } else { \
302 static KCleanUpGlobalStatic cleanUpObject = { destroy }; \
303 } \
304 } \
305 return _k_static_##NAME.load(); \
306 } \
307 inline TYPE &operator*() \
308 { \
309 return *operator->(); \
310 } \
311 static void destroy() \
312 { \
313 _k_static_##NAME##_destroyed = true; \
314 TYPE *x = _k_static_##NAME.load(); \
315 _k_static_##NAME.store(nullptr); \
316 delete x; \
317 } \
318 } NAME;
319
320 /**
321 * Access to the KDE global objects.
322 * KGlobal provides you with pointers of many central
323 * objects that exist only once in the process. It is also
324 * responsible for managing instances of KStaticDeleterBase.
325 *
326 * @see KStaticDeleterBase
327 * @author Sirtaj Singh Kang (taj@kde.org)
328 */
329 namespace KGlobal
330 {
331
332 struct KDELIBS4SUPPORT_DEPRECATED_EXPORT_NOISE LocaleWrapper : public KLocale {
LocaleWrapperLocaleWrapper333 KDELIBS4SUPPORT_DEPRECATED explicit LocaleWrapper(KLocale *locale)
334 : KLocale(*locale)
335 {
336
337 }
338
insertCatalogLocaleWrapper339 KDELIBS4SUPPORT_DEPRECATED static void insertCatalog(const QString &)
340 {
341 qWarning() << "Your code needs to be ported in KF5. See the Ki18n programmers guide.";
342 }
343
344 LocaleWrapper *operator->()
345 {
346 return this;
347 }
348
349 operator KLocale *()
350 {
351 return this;
352 }
353 };
354
355 /**
356 * Returns the global component data. There is always at least
357 * one instance of a component in one application (in most
358 * cases the application itself).
359 * @return the global component data
360 * @deprecated since 5.0 use KComponentData::mainComponent() if you really need a KComponentData
361 */
362 KDELIBS4SUPPORT_DEPRECATED_EXPORT const KComponentData &mainComponent(); //krazy:exclude=constref (don't mess up ref-counting)
363
364 /**
365 * @internal
366 * Returns whether a main KComponentData is available.
367 * @deprecated since 5.0, use KComponentData::hasMainComponent() if you really need a KComponentData
368 */
369 KDELIBS4SUPPORT_DEPRECATED_EXPORT bool hasMainComponent();
370
371 /**
372 * Returns the application standard dirs object.
373 * @return the global standard dir object
374 */
375 KDELIBS4SUPPORT_DEPRECATED_EXPORT KStandardDirs *dirs();
376
377 /**
378 * Returns the general config object.
379 * @return the global configuration object.
380 * @deprecated since 5.0, use KSharedConfig::openConfig()
381 */
382 KDELIBS4SUPPORT_DEPRECATED_EXPORT KSharedConfigPtr config();
383
384 /**
385 * Returns the global locale object.
386 * @return the global locale object
387 *
388 * Note: in multi-threaded programs, you should call KLocale::global()
389 * in the main thread (e.g. in main(), after creating the QCoreApplication
390 * and setting the main component), to ensure that the initialization is
391 * done in the main thread. However KApplication takes care of this, so this
392 * is only needed when not using KApplication.
393 *
394 * @deprecated since 5.0, use KLocale::global()
395 */
396 KDELIBS4SUPPORT_DEPRECATED_EXPORT LocaleWrapper locale();
397 /**
398 * @internal
399 * Returns whether KGlobal has a valid KLocale object
400 * @deprecated since 5.0, port to if (qApp) because KLocale::global() can be called, as soon as a qApp exists.
401 */
402 KDELIBS4SUPPORT_DEPRECATED_EXPORT bool hasLocale();
403
404 /**
405 * The global charset manager.
406 * @return the global charset manager
407 * @deprecated since 5.0, use KCharsets::charsets()
408 */
409 KDELIBS4SUPPORT_DEPRECATED_EXPORT KCharsets *charsets();
410
411 /**
412 * Returns the umask of the process.
413 * @return the umask of the process
414 */
415 KDELIBS4SUPPORT_DEPRECATED_EXPORT mode_t umask();
416
417 /**
418 * Creates a static QString.
419 *
420 * To be used inside functions(!) like:
421 * @code
422 * static const QString &myString = KGlobal::staticQString("myText");
423 * @endcode
424 *
425 * @attention Do @b NOT use code such as:
426 * @code
427 * static QString myString = KGlobal::staticQString("myText");
428 * @endcode
429 * This creates a static object (instead of a static reference)
430 * and as you know static objects are EVIL.
431 * @param str the string to create
432 * @return the static string
433 * @deprecated since 5.0, use QLatin1String() or QStringLiteral()
434 */
435 KDELIBS4SUPPORT_DEPRECATED_EXPORT const QString &staticQString(const char *str); //krazy:exclude=constref (doesn't make sense otherwise)
436
437 /**
438 * Creates a static QString.
439 *
440 * To be used inside functions(!) like:
441 * @code
442 * static const QString &myString = KGlobal::staticQString(i18n("My Text"));
443 * @endcode
444 *
445 * @attention Do @b NOT use code such as:
446 * @code
447 * static QString myString = KGlobal::staticQString(i18n("myText"));
448 * @endcode
449 * This creates a static object (instead of a static reference)
450 * and as you know static objects are EVIL.
451 * @param str the string to create
452 * @return the static string
453 * @deprecated since 5.0 don't make the string static
454 */
455 KDELIBS4SUPPORT_DEPRECATED_EXPORT const QString &staticQString(const QString &str); //krazy:exclude=constref (doesn't make sense otherwise)
456
457 /**
458 * Tells KGlobal about one more operations that should be finished
459 * before the application exits. The standard behavior is to exit on the
460 * "last window closed" event, but some events should outlive the last window closed
461 * (e.g. a file copy for a file manager, or 'compacting folders on exit' for a mail client),
462 * or simply any application with a system tray icon.
463 *
464 * We have some use cases that we want to take care of (the format is "action refcount"):
465 * - open window -> setAllowQuit(true) 1 ; close window 0 => EXIT
466 * - job start 1; job end 0 [don't exit yet]; open window -> setAllowQuit(true) 1 ; close window 0 => EXIT
467 * - job start 1; open window -> setAllowQuit(true) 2; close window 1; job end 0 => EXIT
468 * - job start 1; open window -> setAllowQuit(true) 2; job end 1; close window 0 => EXIT
469 * - open dialog 0; close dialog 0; => DO NOT EXIT
470 * - job start 1; job end 0; create two main objects 2; delete both main objects 0 => EXIT
471 * - open window -> setAllowQuit(true) 1; add systray icon 2; close window 1 => DO NOT EXIT
472 * - open window -> setAllowQuit(true) 1; add systray icon 2; remove systray icon 1; close window 0 => EXIT
473 * - unit test which opens and closes many windows: should call ref() to avoid subevent-loops quitting too early.
474 *
475 * Note that for this to happen you must call qApp->setQuitOnLastWindowClosed(false),
476 * in main() for instance.
477 *
478 * @deprecated since 5.0, use QEventLoopLocker, its constructor does the equivalent of ref
479 */
480 KDELIBS4SUPPORT_DEPRECATED_EXPORT void ref();
481
482 /**
483 * Tells KGlobal that one operation such as those described in ref() just finished.
484 * This call makes the QApplication quit if the counter is back to 0.
485 *
486 * @deprecated since 5.0, use QEventLoopLocker, its destructor does the equivalent of unref
487 */
488 KDELIBS4SUPPORT_DEPRECATED_EXPORT void deref();
489
490 /**
491 * If refcounting reaches 0 (or less), and @p allowQuit is true, the instance of the application
492 * will automatically be exited. Otherwise, the application will not exit automatically.
493 *
494 * This is used by KMainWindow to allow quitting after the first mainwindow is created,
495 * and is used by special applications like kfmclient, to allow quitting even though
496 * no mainwindow was created.
497 *
498 * However, don't try to call setAllowQuit(false) in applications, it doesn't make sense.
499 * If you find that the application quits too early when closing a window, then consider
500 * _what_ is making your application still alive to the user (like a systray icon or a D-Bus object)
501 * and use KGlobal::ref() + KGlobal::deref() in that object.
502 *
503 * @since 4.1.1
504 * @deprecated since 5.0, not necessary anymore, with QCoreApplication and QEventLoopLocker
505 */
506 KDELIBS4SUPPORT_DEPRECATED_EXPORT void setAllowQuit(bool allowQuit);
507
508 /**
509 * The component currently active (useful in a multi-component
510 * application, such as a KParts application).
511 * Don't use this - it's mainly for KAboutDialog and KBugReport.
512 * @internal
513 * @deprecated since 5.0 see KComponentData::activeComponent() about
514 * why you should do without this concept (or let your app remember the active
515 * part/plugin if it cares)
516 */
517 KDELIBS4SUPPORT_DEPRECATED_EXPORT KComponentData activeComponent();
518
519 /**
520 * Set the active component for use by KAboutDialog and KBugReport.
521 * To be used only by a multi-component (KParts) application.
522 *
523 * @see activeComponent()
524 * @deprecated since 5.0 see KComponentData::setActiveComponent about
525 * why you can probably just remove the call.
526 */
527 KDELIBS4SUPPORT_DEPRECATED_EXPORT void setActiveComponent(const KComponentData &d);
528
529 /**
530 * Returns a text for the window caption.
531 *
532 * This may be set by
533 * "-caption", otherwise it will be equivalent to the name of the
534 * executable.
535 * @return the text for the window caption
536 * @deprecated since 5.0. Don't use in window titles anymore, Qt takes care of it.
537 * If you really need this, use QGuiApplication::applicationDisplayName(), and if that's empty, QCoreApplication::applicationName().
538 */
539 KDELIBS4SUPPORT_DEPRECATED_EXPORT QString caption();
540
541 /// @internal
542 KDELIBS4SUPPORT_DEPRECATED_EXPORT QObject *findDirectChild_helper(const QObject *parent, const QMetaObject &mo);
543
544 /**
545 * Returns the child of the given object that can be cast into type T, or 0 if there is no such object.
546 * Unlike QObject::findChild, the search is NOT performed recursively.
547 * @since 4.4
548 * @deprecated since Qt 5, use QObject::findChild(FindDirectChildrenOnly)
549 */
550 template<typename T>
findDirectChild(const QObject * object)551 KDELIBS4SUPPORT_DEPRECATED inline T findDirectChild(const QObject *object)
552 {
553 return static_cast<T>(findDirectChild_helper(object, (static_cast<T>(nullptr))->staticMetaObject));
554 }
555 }
556
557 struct KCatalogLoader {
KCatalogLoaderKCatalogLoader558 KDELIBS4SUPPORT_DEPRECATED KCatalogLoader(const QString &)
559 {
560 qWarning() << "Your code needs to be ported in KF5. See the Ki18n programmers guide.";
561 }
562 };
563
564 #endif // _KGLOBAL_H
565
566