KDECore
kglobal.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 1999 Sirtaj Singh Kanq <taj@kde.org> 00003 Copyright (C) 2007 Matthias Kretz <kretz@kde.org> 00004 Copyright (C) 2009 Olivier Goffart <ogoffart@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License version 2 as published by the Free Software Foundation. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 /* 00022 * kglobal.cpp -- Implementation of namespace KGlobal. 00023 * Author: Sirtaj Singh Kang 00024 * Generated: Sat May 1 02:08:43 EST 1999 00025 */ 00026 00027 #undef KDE3_SUPPORT 00028 00029 #include "kglobal.h" 00030 #include "kglobal_p.h" 00031 #include <QThread> 00032 00033 #include <config.h> 00034 00035 #ifdef HAVE_SYS_STAT_H 00036 #include <sys/stat.h> 00037 #endif 00038 00039 #include <QtCore/QList> 00040 #include <QtCore/QSet> 00041 00042 #include <kaboutdata.h> 00043 #include <kconfig.h> 00044 #include <klocale.h> 00045 #include <kcharsets.h> 00046 #include <kstandarddirs.h> 00047 #include <kcomponentdata.h> 00048 #undef QT_NO_TRANSLATION 00049 #include <QtCore/QCoreApplication> 00050 #define QT_NO_TRANSLATION 00051 #include <QtCore/QDebug> 00052 #include <QtCore/QTextCodec> 00053 #include "kcmdlineargs.h" 00054 #include <unistd.h> // umask 00055 00056 #ifndef NDEBUG 00057 #define MYASSERT(x) if (!x) \ 00058 qFatal("Fatal error: you need to have a KComponentData object before\n" \ 00059 "you do anything that requires it! Examples of this are config\n" \ 00060 "objects, standard directories or translations."); 00061 #else 00062 #define MYASSERT(x) /* nope */ 00063 #endif 00064 00065 // ~KConfig needs qrand(). qrand() depends on a Q_GLOBAL_STATIC. With this Q_CONSTRUCTOR_FUNCTION we 00066 // try to make qrand() live longer than any KConfig object. 00067 Q_CONSTRUCTOR_FUNCTION(qrand) 00068 00069 typedef QSet<QString> KStringDict; 00070 mode_t s_umsk; 00071 00072 class KGlobalPrivate 00073 { 00074 public: 00075 inline KGlobalPrivate() 00076 : stringDict(0), 00077 locale(0), 00078 charsets(0), 00079 localeIsFromFakeComponent(false) 00080 { 00081 // the umask is read here before any threads are created to avoid race conditions 00082 mode_t tmp = 0; 00083 s_umsk = umask(tmp); 00084 umask(s_umsk); 00085 } 00086 00087 inline ~KGlobalPrivate() 00088 { 00089 delete locale; 00090 locale = 0; 00091 delete charsets; 00092 charsets = 0; 00093 delete stringDict; 00094 stringDict = 0; 00095 } 00096 00097 KComponentData activeComponent; 00098 KComponentData mainComponent; // holds a refcount 00099 KStringDict *stringDict; 00100 KLocale *locale; 00101 KCharsets *charsets; 00102 bool localeIsFromFakeComponent; 00103 QStringList catalogsToInsert; 00104 00109 static KComponentData initFakeComponent() 00110 { 00111 QString name = QCoreApplication::applicationName(); 00112 if(name.isEmpty() && QCoreApplication::instance()) 00113 name = qAppName(); 00114 if(name.isEmpty()) 00115 name = QString::fromLatin1("kde"); 00116 return KComponentData(name.toLatin1(), name.toLatin1(), 00117 KComponentData::SkipMainComponentRegistration); 00118 } 00119 }; 00120 00121 KCatalogLoader::KCatalogLoader(const QString &catalogName) 00122 { 00123 KGlobal::insertCatalog(catalogName); 00124 } 00125 00126 00127 K_GLOBAL_STATIC(KGlobalPrivate, globalData) 00128 K_GLOBAL_STATIC_WITH_ARGS(KComponentData, fakeComponent, (KGlobalPrivate::initFakeComponent())) 00129 00130 #define PRIVATE_DATA KGlobalPrivate *d = globalData 00131 00132 KStandardDirs *KGlobal::dirs() 00133 { 00134 PRIVATE_DATA; 00135 return d->mainComponent.isValid() ? d->mainComponent.dirs() : fakeComponent->dirs(); 00136 } 00137 00138 KSharedConfig::Ptr KGlobal::config() 00139 { 00140 PRIVATE_DATA; 00141 return d->mainComponent.isValid() ? d->mainComponent.config() : fakeComponent->config(); 00142 } 00143 00144 const KComponentData &KGlobal::mainComponent() 00145 { 00146 PRIVATE_DATA; 00147 return d->mainComponent.isValid() ? d->mainComponent : *fakeComponent; 00148 } 00149 00150 bool KGlobal::hasMainComponent() 00151 { 00152 if (globalData.isDestroyed()) { 00153 return false; 00154 } 00155 PRIVATE_DATA; 00156 return d->mainComponent.isValid(); 00157 } 00158 00159 void KGlobal::insertCatalog(const QString& catalog) 00160 { 00161 PRIVATE_DATA; 00162 if (d->locale) { 00163 locale()->insertCatalog(catalog); 00164 } else { 00165 d->catalogsToInsert.append(catalog); 00166 } 00167 } 00168 00169 KLocale *KGlobal::locale() 00170 { 00171 PRIVATE_DATA; 00172 if (d->locale == 0 || (d->localeIsFromFakeComponent && d->mainComponent.isValid() && d->mainComponent.config())) { 00173 // If you hit the warning below, here's how to debug it in gdb: 00174 // (gdb) set auto-solib-add on 00175 // (gdb) b qt_message_output 00176 // (gdb) run 00177 // It will stop at the "-nograb" information. 00178 // (gdb) b KLocalePrivate::KLocalePrivate 00179 // (gdb) c 00180 // And now it will stop at the first construction of the KLocale object, type bt or go up to find the 00181 // guilty i18n call. 00182 if (d->locale != 0) qDebug() << "KGlobal::locale::Warning your global KLocale is being recreated with a valid main component instead of a fake component, this usually means you tried to call i18n related functions before your main component was created. You should not do that since it most likely will not work"; 00183 delete d->locale; 00184 d->locale = 0; 00185 d->locale = new KLocale(mainComponent().catalogName()); 00186 d->localeIsFromFakeComponent = !d->mainComponent.isValid(); 00187 QTextCodec::setCodecForLocale(d->locale->codecForEncoding()); 00188 mainComponent().aboutData()->translateInternalProgramName(); 00189 QCoreApplication* coreApp = QCoreApplication::instance(); 00190 if (coreApp) { // testcase: kwrite --help: no qcore app 00191 if (coreApp->thread() != QThread::currentThread()) { 00192 qFatal("KGlobal::locale() must be called from the main thread before using i18n() in threads. KApplication takes care of this. If not using KApplication, call KGlobal::locale() during initialization."); 00193 } else { 00194 QCoreApplication::installTranslator(new KDETranslator(coreApp)); 00195 } 00196 } 00197 foreach(const QString &catalog, d->catalogsToInsert) 00198 d->locale->insertCatalog(catalog); 00199 d->catalogsToInsert.clear(); 00200 } 00201 return d->locale; 00202 } 00203 00204 bool KGlobal::hasLocale() 00205 { 00206 if (globalData.isDestroyed()) { 00207 return false; 00208 } 00209 PRIVATE_DATA; 00210 return (d->locale != 0); 00211 } 00212 00213 KCharsets *KGlobal::charsets() 00214 { 00215 PRIVATE_DATA; 00216 if (d->charsets == 0) { 00217 d->charsets = new KCharsets; 00218 } 00219 00220 return d->charsets; 00221 } 00222 00223 mode_t KGlobal::umask() 00224 { 00225 // Don't use PRIVATE_DATA here. This is called by ~KGlobalPrivate -> ~KConfig -> sync -> KSaveFile, so there's no KGlobalPrivate anymore. 00226 return s_umsk; 00227 } 00228 00229 KComponentData KGlobal::activeComponent() 00230 { 00231 PRIVATE_DATA; 00232 MYASSERT(d->activeComponent.isValid()); 00233 return d->activeComponent; 00234 } 00235 00236 void KGlobal::setActiveComponent(const KComponentData &c) 00237 { 00238 PRIVATE_DATA; 00239 d->activeComponent = c; 00240 if (c.isValid() && d->locale) { 00241 locale()->setActiveCatalog(c.catalogName()); 00242 } 00243 } 00244 00245 void KGlobal::newComponentData(const KComponentData &c) 00246 { 00247 PRIVATE_DATA; 00248 if (d->mainComponent.isValid()) { 00249 return; 00250 } 00251 d->mainComponent = c; 00252 KGlobal::setActiveComponent(c); 00253 } 00254 00255 void KGlobal::setLocale(KLocale *newLocale, CopyCatalogs copy) 00256 { 00257 PRIVATE_DATA; 00258 if (copy == DoCopyCatalogs && d->locale) 00259 locale()->copyCatalogsTo(newLocale); 00260 delete d->locale; 00261 d->locale = newLocale; 00262 } 00263 00270 const QString &KGlobal::staticQString(const char *str) 00271 { 00272 return staticQString(QLatin1String(str)); 00273 } 00274 00281 const QString &KGlobal::staticQString(const QString &str) 00282 { 00283 PRIVATE_DATA; 00284 if (!d->stringDict) { 00285 d->stringDict = new KStringDict; 00286 } 00287 00288 return *d->stringDict->insert(str); 00289 } 00290 00291 QString KGlobal::caption() 00292 { 00293 PRIVATE_DATA; 00294 // Caption set from command line ? 00295 KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde"); 00296 if (args && args->isSet("caption")) { 00297 return args->getOption("caption"); 00298 } else { 00299 // We have some about data ? 00300 if (d->mainComponent.isValid() && d->mainComponent.aboutData()) { 00301 return d->mainComponent.aboutData()->programName(); 00302 } else { 00303 // Last resort : application name 00304 return QCoreApplication::instance()->applicationName(); 00305 } 00306 } 00307 } 00308 00317 static int s_refCount = 0; 00318 static bool s_allowQuit = false; 00319 00320 void KGlobal::ref() 00321 { 00322 ++s_refCount; 00323 //kDebug() << "KGlobal::ref() : refCount = " << s_refCount; 00324 } 00325 00326 void KGlobal::deref() 00327 { 00328 --s_refCount; 00329 //kDebug() << "KGlobal::deref() : refCount = " << s_refCount; 00330 if (s_refCount <= 0 && s_allowQuit) { 00331 QCoreApplication::instance()->quit(); 00332 } 00333 } 00334 00335 void KGlobal::setAllowQuit(bool allowQuit) 00336 { 00337 s_allowQuit = allowQuit; 00338 } 00339 00340 #undef PRIVATE_DATA 00341 00342 QObject* KGlobal::findDirectChild_helper(const QObject* parent, const QMetaObject& mo) 00343 { 00344 if (!parent) 00345 return 0; 00346 00347 const QObjectList &children = parent->children(); 00348 for (int i = 0; i < children.size(); ++i) { 00349 QObject* obj = children.at(i); 00350 if (mo.cast(obj)) { 00351 return obj; 00352 } 00353 } 00354 return 0; 00355 00356 }
KDE 4.7 API Reference