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