kdecore Library API Documentation

kapplication.cpp

00001 /* This file is part of the KDE libraries 00002 Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org) 00003 Copyright (C) 1998, 1999, 2000 KDE Team 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 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., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 */ 00020 00021 // $Id: kapplication.cpp,v 1.637.2.14 2004/06/08 09:27:57 waba Exp $ 00022 00023 #include "config.h" 00024 00025 #undef QT_NO_TRANSLATION 00026 #include <qtranslator.h> 00027 #define QT_NO_TRANSLATION 00028 #include <qdir.h> 00029 #include <qptrcollection.h> 00030 #include <qwidgetlist.h> 00031 #include <qstrlist.h> 00032 #include <qfile.h> 00033 #include <qmessagebox.h> 00034 #include <qtextstream.h> 00035 #include <qregexp.h> 00036 #include <qlineedit.h> 00037 #include <qtextedit.h> 00038 #include <qsessionmanager.h> 00039 #include <qptrlist.h> 00040 #include <qtimer.h> 00041 #include <qstylesheet.h> 00042 #include <qpixmapcache.h> 00043 #include <qtooltip.h> 00044 #include <qstylefactory.h> 00045 #include <qmetaobject.h> 00046 #ifndef QT_NO_SQL 00047 #include <qsqlpropertymap.h> 00048 #endif 00049 00050 #undef QT_NO_TRANSLATION 00051 #include "kapplication.h" 00052 #define QT_NO_TRANSLATION 00053 #include <kglobal.h> 00054 #include <kstandarddirs.h> 00055 #include <kdebug.h> 00056 #include <klocale.h> 00057 #include <kstyle.h> 00058 #include <kiconloader.h> 00059 #include <kclipboard.h> 00060 #include <kconfig.h> 00061 #include <ksimpleconfig.h> 00062 #include <kcmdlineargs.h> 00063 #include <kaboutdata.h> 00064 #include <kglobalsettings.h> 00065 #include <kcrash.h> 00066 #include <kdatastream.h> 00067 #include <klibloader.h> 00068 #include <kmimesourcefactory.h> 00069 #include <kstdaccel.h> 00070 #include <kaccel.h> 00071 #include "kcheckaccelerators.h" 00072 #include <qptrdict.h> 00073 #include <kmacroexpander.h> 00074 #include <kshell.h> 00075 #include <kprotocolinfo.h> 00076 00077 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00078 #include <kstartupinfo.h> // schroder 00079 #endif 00080 00081 #include <dcopclient.h> 00082 #include <dcopref.h> 00083 00084 #include <sys/types.h> 00085 #ifdef HAVE_SYS_STAT_H 00086 #include <sys/stat.h> 00087 #endif 00088 #include <sys/wait.h> 00089 00090 #include "kwin.h" 00091 00092 #include <fcntl.h> 00093 #include <stdlib.h> // getenv(), srand(), rand() 00094 #include <signal.h> 00095 #include <unistd.h> 00096 #include <time.h> 00097 #include <sys/time.h> 00098 #include <errno.h> 00099 #include <string.h> 00100 #include <netdb.h> 00101 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00102 //#ifndef Q_WS_QWS //FIXME(E): NetWM should talk to QWS... 00103 #include <netwm.h> // schroder 00104 #endif 00105 00106 #include "kprocctrl.h" 00107 00108 #ifdef HAVE_PATHS_H 00109 #include <paths.h> 00110 #endif 00111 00112 //#if defined Q_WS_X11 && ! defined K_WS_QTONLY 00113 #ifdef Q_WS_X11 00114 #include <X11/Xlib.h> // schrode 00115 #include <X11/Xutil.h> // schrode 00116 #include <X11/Xatom.h> // schrode 00117 #include <X11/SM/SMlib.h> // schrode 00118 #include <fixx11h.h> // schrode 00119 #endif 00120 #include <KDE-ICE/ICElib.h> 00121 00122 #ifdef Q_WS_X11 00123 #define DISPLAY "DISPLAY" 00124 #elif defined(Q_WS_QWS) 00125 #define DISPLAY "QWS_DISPLAY" 00126 #endif 00127 00128 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00129 #include <kipc.h> // schroder 00130 #endif 00131 00132 #include "kappdcopiface.h" 00133 00134 bool kde_have_kipc = true; // magic hook to disable kipc in kdm 00135 bool kde_kiosk_exception = false; // flag to disable kiosk restrictions 00136 bool kde_kiosk_admin = false; 00137 00138 KApplication* KApplication::KApp = 0L; 00139 bool KApplication::loadedByKdeinit = false; 00140 DCOPClient *KApplication::s_DCOPClient = 0L; 00141 bool KApplication::s_dcopClientNeedsPostInit = false; 00142 00143 static Atom atom_DesktopWindow; 00144 static Atom atom_NetSupported; 00145 #if KDE_IS_VERSION( 3, 2, 91 ) 00146 #warning Obsolete, remove. 00147 // remove atom_KdeNetUserTime related stuff (l.lunak@kde.org) 00148 #endif 00149 static Atom atom_KdeNetUserTime; 00150 static Atom kde_net_wm_user_time = 0; 00151 #if KDE_IS_VERSION( 3, 2, 91 ) 00152 #warning This should be in Qt already, check. 00153 // remove things related to qt_x_user_time that should be in Qt by now (l.lunak@kde.org) 00154 #endif 00155 Time qt_x_user_time = CurrentTime; 00156 extern Time qt_x_time; 00157 static Atom kde_xdnd_drop; 00158 00159 // duplicated from patched Qt, so that there won't be unresolved symbols if Qt gets 00160 // replaced by unpatched one 00161 bool qt_qclipboard_bailout_hack = false; 00162 00163 template class QPtrList<KSessionManaged>; 00164 00165 #ifdef Q_WS_X11 00166 extern "C" { 00167 static int kde_xio_errhandler( Display * dpy ) 00168 { 00169 return kapp->xioErrhandler( dpy ); 00170 } 00171 00172 static int kde_x_errhandler( Display *dpy, XErrorEvent *err ) 00173 { 00174 return kapp->xErrhandler( dpy, err ); 00175 } 00176 00177 } 00178 #endif 00179 00180 extern "C" { 00181 static void kde_ice_ioerrorhandler( IceConn conn ) 00182 { 00183 if(kapp) 00184 kapp->iceIOErrorHandler( conn ); 00185 // else ignore the error for now 00186 } 00187 } 00188 00189 /* 00190 Private data to make keeping binary compatibility easier 00191 */ 00192 class KApplicationPrivate 00193 { 00194 public: 00195 KApplicationPrivate() 00196 : actionRestrictions( false ), 00197 refCount( 1 ), 00198 oldIceIOErrorHandler( 0 ), 00199 checkAccelerators( 0 ), 00200 overrideStyle( QString::null ), 00201 startup_id( "0" ), 00202 app_started_timer( NULL ), 00203 m_KAppDCOPInterface( 0L ), 00204 session_save( false ), 00205 oldXErrorHandler( NULL ), 00206 oldXIOErrorHandler( NULL ) 00207 { 00208 } 00209 00210 ~KApplicationPrivate() 00211 {} 00212 00213 00214 bool actionRestrictions : 1; 00215 bool guiEnabled : 1; 00222 int refCount; 00223 IceIOErrorHandler oldIceIOErrorHandler; 00224 KCheckAccelerators* checkAccelerators; 00225 QString overrideStyle; 00226 QString geometry_arg; 00227 QCString startup_id; 00228 QTimer* app_started_timer; 00229 KAppDCOPInterface *m_KAppDCOPInterface; 00230 bool session_save; 00231 int (*oldXErrorHandler)(Display*,XErrorEvent*); 00232 int (*oldXIOErrorHandler)(Display*); 00233 00234 class URLActionRule 00235 { 00236 public: 00237 #define checkExactMatch(s, b) \ 00238 if (s.isEmpty()) b = true; \ 00239 else if (s[s.length()-1] == '!') \ 00240 { b = false; s.truncate(s.length()-1); } \ 00241 else b = true; 00242 #define checkStartWildCard(s, b) \ 00243 if (s.isEmpty()) b = true; \ 00244 else if (s[0] == '*') \ 00245 { b = true; s = s.mid(1); } \ 00246 else b = false; 00247 #define checkEqual(s, b) \ 00248 b = (s == "="); 00249 00250 URLActionRule(const QString &act, 00251 const QString &bProt, const QString &bHost, const QString &bPath, 00252 const QString &dProt, const QString &dHost, const QString &dPath, 00253 bool perm) 00254 : action(act), 00255 baseProt(bProt), baseHost(bHost), basePath(bPath), 00256 destProt(dProt), destHost(dHost), destPath(dPath), 00257 permission(perm) 00258 { 00259 checkExactMatch(baseProt, baseProtWildCard); 00260 checkStartWildCard(baseHost, baseHostWildCard); 00261 checkExactMatch(basePath, basePathWildCard); 00262 checkExactMatch(destProt, destProtWildCard); 00263 checkStartWildCard(destHost, destHostWildCard); 00264 checkExactMatch(destPath, destPathWildCard); 00265 checkEqual(destProt, destProtEqual); 00266 checkEqual(destHost, destHostEqual); 00267 } 00268 00269 bool baseMatch(const KURL &url, const QString &protClass) 00270 { 00271 if (baseProtWildCard) 00272 { 00273 if ( !baseProt.isEmpty() && !url.protocol().startsWith(baseProt) && 00274 (protClass.isEmpty() || (protClass != baseProt)) ) 00275 return false; 00276 } 00277 else 00278 { 00279 if ( (url.protocol() != baseProt) && 00280 (protClass.isEmpty() || (protClass != baseProt)) ) 00281 return false; 00282 } 00283 if (baseHostWildCard) 00284 { 00285 if (!baseHost.isEmpty() && !url.host().endsWith(baseHost)) 00286 return false; 00287 } 00288 else 00289 { 00290 if (url.host() != baseHost) 00291 return false; 00292 } 00293 if (basePathWildCard) 00294 { 00295 if (!basePath.isEmpty() && !url.path().startsWith(basePath)) 00296 return false; 00297 } 00298 else 00299 { 00300 if (url.path() != basePath) 00301 return false; 00302 } 00303 return true; 00304 } 00305 00306 bool destMatch(const KURL &url, const QString &protClass, const KURL &base, const QString &baseClass) 00307 { 00308 if (destProtEqual) 00309 { 00310 if ( (url.protocol() != base.protocol()) && 00311 (protClass.isEmpty() || baseClass.isEmpty() || protClass != baseClass) ) 00312 return false; 00313 } 00314 else if (destProtWildCard) 00315 { 00316 if ( !destProt.isEmpty() && !url.protocol().startsWith(destProt) && 00317 (protClass.isEmpty() || (protClass != destProt)) ) 00318 return false; 00319 } 00320 else 00321 { 00322 if ( (url.protocol() != destProt) && 00323 (protClass.isEmpty() || (protClass != destProt)) ) 00324 return false; 00325 } 00326 if (destHostWildCard) 00327 { 00328 if (!destHost.isEmpty() && !url.host().endsWith(destHost)) 00329 return false; 00330 } 00331 else if (destHostEqual) 00332 { 00333 if (url.host() != base.host()) 00334 return false; 00335 } 00336 else 00337 { 00338 if (url.host() != destHost) 00339 return false; 00340 } 00341 if (destPathWildCard) 00342 { 00343 if (!destPath.isEmpty() && !url.path().startsWith(destPath)) 00344 return false; 00345 } 00346 else 00347 { 00348 if (url.path() != destPath) 00349 return false; 00350 } 00351 return true; 00352 } 00353 00354 QString action; 00355 QString baseProt; 00356 QString baseHost; 00357 QString basePath; 00358 QString destProt; 00359 QString destHost; 00360 QString destPath; 00361 bool baseProtWildCard : 1; 00362 bool baseHostWildCard : 1; 00363 bool basePathWildCard : 1; 00364 bool destProtWildCard : 1; 00365 bool destHostWildCard : 1; 00366 bool destPathWildCard : 1; 00367 bool destProtEqual : 1; 00368 bool destHostEqual : 1; 00369 bool permission; 00370 }; 00371 QPtrList<URLActionRule> urlActionRestrictions; 00372 00373 QString sessionKey; 00374 QString pSessionConfigFile; 00375 }; 00376 00377 00378 static QPtrList<QWidget>*x11Filter = 0; 00379 static bool autoDcopRegistration = true; 00380 00381 void KApplication::installX11EventFilter( QWidget* filter ) 00382 { 00383 if ( !filter ) 00384 return; 00385 if (!x11Filter) 00386 x11Filter = new QPtrList<QWidget>; 00387 connect ( filter, SIGNAL( destroyed() ), this, SLOT( x11FilterDestroyed() ) ); 00388 x11Filter->append( filter ); 00389 } 00390 00391 void KApplication::x11FilterDestroyed() 00392 { 00393 removeX11EventFilter( static_cast< const QWidget* >( sender())); 00394 } 00395 00396 void KApplication::removeX11EventFilter( const QWidget* filter ) 00397 { 00398 if ( !x11Filter || !filter ) 00399 return; 00400 x11Filter->removeRef( filter ); 00401 if ( x11Filter->isEmpty() ) { 00402 delete x11Filter; 00403 x11Filter = 0; 00404 } 00405 } 00406 00407 // FIXME: remove this when we've get a better method of 00408 // customizing accelerator handling -- hopefully in Qt. 00409 // For now, this is set whenever an accelerator is overridden 00410 // in KAccelEventHandler so that the AccelOverride isn't sent twice. -- ellis, 19/10/02 00411 extern bool kde_g_bKillAccelOverride; 00412 00413 bool KApplication::notify(QObject *receiver, QEvent *event) 00414 { 00415 QEvent::Type t = event->type(); 00416 if (kde_g_bKillAccelOverride) 00417 { 00418 kde_g_bKillAccelOverride = false; 00419 // Indicate that the accelerator has been overridden. 00420 if (t == QEvent::AccelOverride) 00421 { 00422 static_cast<QKeyEvent *>(event)->accept(); 00423 return true; 00424 } 00425 else 00426 kdWarning(125) << "kde_g_bKillAccelOverride set, but received an event other than AccelOverride." << endl; 00427 } 00428 00429 if ((t == QEvent::AccelOverride) || (t == QEvent::KeyPress)) 00430 { 00431 static const KShortcut& _selectAll = KStdAccel::selectAll(); 00432 if (receiver && receiver->inherits("QLineEdit")) 00433 { 00434 QLineEdit *edit = static_cast<QLineEdit *>(receiver); 00435 // We have a keypress for a lineedit... 00436 QKeyEvent *kevent = static_cast<QKeyEvent *>(event); 00437 KKey key(kevent); 00438 if (_selectAll.contains(key)) 00439 { 00440 if (t == QEvent::KeyPress) 00441 { 00442 edit->selectAll(); 00443 return true; 00444 } 00445 else 00446 { 00447 kevent->accept(); 00448 } 00449 } 00450 // Ctrl-U deletes from start of line. 00451 if (key == KKey(Qt::CTRL + Qt::Key_U)) 00452 { 00453 if (t == QEvent::KeyPress) 00454 { 00455 if (!edit->isReadOnly()) 00456 { 00457 QString t(edit->text()); 00458 t = t.mid(edit->cursorPosition()); 00459 edit->validateAndSet(t, 0, 0, 0); 00460 } 00461 return true; 00462 } 00463 else 00464 { 00465 kevent->accept(); 00466 } 00467 00468 } 00469 } 00470 if (receiver && receiver->inherits("QTextEdit")) 00471 { 00472 QTextEdit *medit = static_cast<QTextEdit *>(receiver); 00473 // We have a keypress for a multilineedit... 00474 QKeyEvent *kevent = static_cast<QKeyEvent *>(event); 00475 if (_selectAll.contains(KKey(kevent))) 00476 { 00477 if (t == QEvent::KeyPress) 00478 { 00479 medit->selectAll(); 00480 return true; 00481 } 00482 else 00483 { 00484 kevent->accept(); 00485 } 00486 } 00487 } 00488 } 00489 if( event->type() == QEvent::Show && receiver->isWidgetType()) 00490 { 00491 QWidget* w = static_cast< QWidget* >( receiver ); 00492 if( w->isTopLevel() && !startupId().isEmpty()) // TODO better done using window group leader? 00493 KStartupInfo::setWindowStartupId( w->winId(), startupId()); 00494 if( w->isTopLevel() && qt_x_user_time != CurrentTime ) // CurrentTime means no input event yet 00495 XChangeProperty( qt_xdisplay(), w->winId(), kde_net_wm_user_time, XA_CARDINAL, 00496 32, PropModeReplace, (unsigned char*)&qt_x_user_time, 1 ); 00497 } 00498 if( event->type() == QEvent::Show && receiver->isWidgetType()) 00499 { 00500 QWidget* w = static_cast< QWidget* >( receiver ); 00501 if( w->isTopLevel() && !w->testWFlags( WX11BypassWM ) && !w->isPopup() && !event->spontaneous()) 00502 { 00503 if( d->app_started_timer == NULL ) 00504 { 00505 d->app_started_timer = new QTimer( this ); 00506 connect( d->app_started_timer, SIGNAL( timeout()), SLOT( checkAppStartedSlot())); 00507 } 00508 if( !d->app_started_timer->isActive()) 00509 d->app_started_timer->start( 0, true ); 00510 } 00511 } 00512 return QApplication::notify(receiver, event); 00513 } 00514 00515 void KApplication::checkAppStartedSlot() 00516 { 00517 KStartupInfo::handleAutoAppStartedSending(); 00518 } 00519 00520 // the help class for session management communication 00521 static QPtrList<KSessionManaged>* sessionClients() 00522 { 00523 static QPtrList<KSessionManaged>* session_clients = 0L; 00524 if ( !session_clients ) 00525 session_clients = new QPtrList<KSessionManaged>; 00526 return session_clients; 00527 } 00528 00529 /* 00530 Auxiliary function to calculate a a session config name used for the 00531 instance specific config object. 00532 Syntax: "session/<appname>_<sessionId>" 00533 */ 00534 QString KApplication::sessionConfigName() const 00535 { 00536 #if QT_VERSION < 0x030100 00537 return QString("session/%1_%2_%3").arg(name()).arg(sessionId()).arg(d->sessionKey); 00538 #else 00539 QString sessKey = sessionKey(); 00540 if ( sessKey.isEmpty() && !d->sessionKey.isEmpty() ) 00541 sessKey = d->sessionKey; 00542 return QString("session/%1_%2_%3").arg(name()).arg(sessionId()).arg(sessKey); 00543 #endif 00544 } 00545 00546 #ifndef Q_WS_QWS 00547 static SmcConn mySmcConnection = 0; 00548 static SmcConn tmpSmcConnection = 0; 00549 #else 00550 // FIXME(E): Implement for Qt Embedded 00551 // Possibly "steal" XFree86's libSM? 00552 #endif 00553 static QTime* smModificationTime = 0; 00554 00555 KApplication::KApplication( int& argc, char** argv, const QCString& rAppName, 00556 bool allowStyles, bool GUIenabled ) : 00557 QApplication( argc, argv, GUIenabled ), KInstance(rAppName), 00558 #ifdef Q_WS_X11 00559 display(0L), 00560 #endif 00561 d (new KApplicationPrivate()) 00562 { 00563 read_app_startup_id(); 00564 if (!GUIenabled) 00565 allowStyles = false; 00566 useStyles = allowStyles; 00567 Q_ASSERT (!rAppName.isEmpty()); 00568 setName(rAppName); 00569 00570 installSigpipeHandler(); 00571 KCmdLineArgs::initIgnore(argc, argv, rAppName.data()); 00572 parseCommandLine( ); 00573 init(GUIenabled); 00574 d->m_KAppDCOPInterface = new KAppDCOPInterface(this); 00575 } 00576 00577 KApplication::KApplication( bool allowStyles, bool GUIenabled ) : 00578 QApplication( *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(), 00579 GUIenabled ), 00580 KInstance( KCmdLineArgs::about), 00581 #ifdef Q_WS_X11 00582 display(0L), 00583 #endif 00584 d (new KApplicationPrivate) 00585 { 00586 read_app_startup_id(); 00587 if (!GUIenabled) 00588 allowStyles = false; 00589 useStyles = allowStyles; 00590 setName( instanceName() ); 00591 00592 installSigpipeHandler(); 00593 parseCommandLine( ); 00594 init(GUIenabled); 00595 d->m_KAppDCOPInterface = new KAppDCOPInterface(this); 00596 } 00597 00598 KApplication::KApplication( bool allowStyles, bool GUIenabled, KInstance* _instance ) : 00599 QApplication( *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(), 00600 GUIenabled ), 00601 KInstance( _instance ), 00602 #ifdef Q_WS_X11 00603 display(0L), 00604 #endif 00605 d (new KApplicationPrivate) 00606 { 00607 read_app_startup_id(); 00608 if (!GUIenabled) 00609 allowStyles = false; 00610 useStyles = allowStyles; 00611 setName( instanceName() ); 00612 00613 installSigpipeHandler(); 00614 parseCommandLine( ); 00615 init(GUIenabled); 00616 d->m_KAppDCOPInterface = new KAppDCOPInterface(this); 00617 } 00618 00619 #ifdef Q_WS_X11 00620 KApplication::KApplication(Display *display, int& argc, char** argv, const QCString& rAppName, 00621 bool allowStyles, bool GUIenabled ) : 00622 QApplication( display ), KInstance(rAppName), 00623 display(0L), 00624 d (new KApplicationPrivate()) 00625 { 00626 read_app_startup_id(); 00627 if (!GUIenabled) 00628 allowStyles = false; 00629 useStyles = allowStyles; 00630 00631 Q_ASSERT (!rAppName.isEmpty()); 00632 setName(rAppName); 00633 00634 installSigpipeHandler(); 00635 KCmdLineArgs::initIgnore(argc, argv, rAppName.data()); 00636 parseCommandLine( ); 00637 init(GUIenabled); 00638 d->m_KAppDCOPInterface = new KAppDCOPInterface(this); 00639 } 00640 #endif 00641 00642 int KApplication::xioErrhandler( Display* dpy ) 00643 { 00644 if(kapp) 00645 { 00646 emit shutDown(); 00647 d->oldXIOErrorHandler( dpy ); 00648 } 00649 exit( 1 ); 00650 return 0; 00651 } 00652 00653 int KApplication::xErrhandler( Display* dpy, void* err_ ) 00654 { // no idea how to make forward decl. for XErrorEvent 00655 XErrorEvent* err = static_cast< XErrorEvent* >( err_ ); 00656 if(kapp) 00657 { 00658 // add KDE specific stuff here 00659 d->oldXErrorHandler( dpy, err ); 00660 } 00661 return 0; 00662 } 00663 00664 void KApplication::iceIOErrorHandler( _IceConn *conn ) 00665 { 00666 emit shutDown(); 00667 00668 if ( d->oldIceIOErrorHandler != NULL ) 00669 (*d->oldIceIOErrorHandler)( conn ); 00670 00671 exit( 1 ); 00672 } 00673 00674 class KDETranslator : public QTranslator 00675 { 00676 public: 00677 KDETranslator(QObject *parent) : QTranslator(parent, "kdetranslator") {} 00678 virtual QTranslatorMessage findMessage(const char* context, 00679 const char *sourceText, 00680 const char* message) const 00681 { 00682 QTranslatorMessage res; 00683 res.setTranslation(KGlobal::locale()->translateQt(context, sourceText, message)); 00684 return res; 00685 } 00686 }; 00687 00688 void KApplication::init(bool GUIenabled) 00689 { 00690 d->guiEnabled = GUIenabled; 00691 if ((getuid() != geteuid()) || 00692 (getgid() != getegid())) 00693 { 00694 fprintf(stderr, "The KDE libraries are not designed to run with suid privileges.\n"); 00695 ::exit(127); 00696 } 00697 00698 KProcessController::ref(); 00699 00700 (void) KClipboardSynchronizer::self(); 00701 00702 QApplication::setDesktopSettingsAware( false ); 00703 00704 KApp = this; 00705 00706 00707 #ifdef Q_WS_X11 //FIXME(E) 00708 // create all required atoms in _one_ roundtrip to the X server 00709 if ( GUIenabled ) { 00710 const int max = 20; 00711 Atom* atoms[max]; 00712 char* names[max]; 00713 Atom atoms_return[max]; 00714 int n = 0; 00715 00716 atoms[n] = &kipcCommAtom; 00717 names[n++] = (char *) "KIPC_COMM_ATOM"; 00718 00719 atoms[n] = &atom_DesktopWindow; 00720 names[n++] = (char *) "KDE_DESKTOP_WINDOW"; 00721 00722 atoms[n] = &atom_NetSupported; 00723 names[n++] = (char *) "_NET_SUPPORTED"; 00724 00725 atoms[n] = &atom_KdeNetUserTime; 00726 names[n++] = (char *) "_KDE_NET_USER_TIME"; 00727 00728 atoms[n] = &kde_net_wm_user_time; 00729 names[n++] = (char *) "_NET_WM_USER_TIME"; 00730 00731 atoms[n] = &kde_xdnd_drop; 00732 names[n++] = (char *) "XdndDrop"; 00733 00734 XInternAtoms( qt_xdisplay(), names, n, false, atoms_return ); 00735 00736 for (int i = 0; i < n; i++ ) 00737 *atoms[i] = atoms_return[i]; 00738 } 00739 #endif 00740 00741 dcopAutoRegistration(); 00742 dcopClientPostInit(); 00743 00744 smw = 0; 00745 00746 // Initial KIPC event mask. 00747 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00748 kipcEventMask = (1 << KIPC::StyleChanged) | (1 << KIPC::PaletteChanged) | 00749 (1 << KIPC::FontChanged) | (1 << KIPC::BackgroundChanged) | 00750 (1 << KIPC::ToolbarStyleChanged) | (1 << KIPC::SettingsChanged) | 00751 (1 << KIPC::ClipboardConfigChanged); 00752 #endif 00753 00754 // Trigger creation of locale. 00755 (void) KGlobal::locale(); 00756 00757 KConfig* config = KGlobal::config(); 00758 d->actionRestrictions = config->hasGroup("KDE Action Restrictions" ) && !kde_kiosk_exception; 00759 // For brain-dead configurations where the user's local config file is not writable. 00760 // * We use kdialog to warn the user, so we better not generate warnings from 00761 // kdialog itself. 00762 // * Don't warn if we run with a read-only $HOME 00763 QCString readOnly = getenv("KDE_HOME_READONLY"); 00764 if (readOnly.isEmpty() && (qstrcmp(name(), "kdialog") != 0)) 00765 { 00766 KConfigGroupSaver saver(config, "KDE Action Restrictions"); 00767 if (config->readBoolEntry("warn_unwritable_config",true)) 00768 config->checkConfigFilesWritable(true); 00769 } 00770 00771 if (GUIenabled) 00772 { 00773 #ifdef Q_WS_X11 00774 // this is important since we fork() to launch the help (Matthias) 00775 fcntl(ConnectionNumber(qt_xdisplay()), F_SETFD, FD_CLOEXEC); 00776 // set up the fancy (=robust and error ignoring ) KDE xio error handlers (Matthias) 00777 d->oldXErrorHandler = XSetErrorHandler( kde_x_errhandler ); 00778 d->oldXIOErrorHandler = XSetIOErrorHandler( kde_xio_errhandler ); 00779 #endif 00780 00781 connect( this, SIGNAL( aboutToQuit() ), this, SIGNAL( shutDown() ) ); 00782 00783 #ifdef Q_WS_X11 //FIXME(E) 00784 display = desktop()->x11Display(); 00785 #endif 00786 00787 { 00788 QStringList plugins = KGlobal::dirs()->resourceDirs( "qtplugins" ); 00789 QStringList::Iterator it = plugins.begin(); 00790 while (it != plugins.end()) { 00791 addLibraryPath( *it ); 00792 ++it; 00793 } 00794 00795 } 00796 kdisplaySetStyle(); 00797 kdisplaySetFont(); 00798 // kdisplaySetPalette(); done by kdisplaySetStyle 00799 propagateSettings(SETTINGS_QT); 00800 00801 // Set default mime-source factory 00802 // XXX: This is a hack. Make our factory the default factory, but add the 00803 // previous default factory to the list of factories. Why? When the default 00804 // factory can't resolve something, it iterates in the list of factories. 00805 // But it QWhatsThis only uses the default factory. So if there was already 00806 // a default factory (which happens when using an image library using uic), 00807 // we prefer KDE's factory and so we put that old default factory in the 00808 // list and use KDE as the default. This may speed up things as well. 00809 QMimeSourceFactory* oldDefaultFactory = QMimeSourceFactory::takeDefaultFactory(); 00810 QMimeSourceFactory::setDefaultFactory( mimeSourceFactory() ); 00811 if ( oldDefaultFactory ) { 00812 QMimeSourceFactory::addFactory( oldDefaultFactory ); 00813 } 00814 00815 KConfigGroupSaver saver( config, "Development" ); 00816 if( config->hasKey( "CheckAccelerators" ) || config->hasKey( "AutoCheckAccelerators" )) 00817 d->checkAccelerators = new KCheckAccelerators( this ); 00818 } 00819 00820 // save and restore the RTL setting, as installTranslator calls qt_detectRTLLanguage, 00821 // which makes it impossible to use the -reverse cmdline switch with KDE apps 00822 bool rtl = reverseLayout(); 00823 installTranslator(new KDETranslator(this)); 00824 setReverseLayout( rtl ); 00825 if (i18n( "_: Dear Translator! Translate this string to the string 'LTR' in " 00826 "left-to-right languages (as english) or to 'RTL' in right-to-left " 00827 "languages (such as Hebrew and Arabic) to get proper widget layout." ) == "RTL") 00828 setReverseLayout( !rtl ); 00829 00830 // install appdata resource type 00831 KGlobal::dirs()->addResourceType("appdata", KStandardDirs::kde_default("data") 00832 + QString::fromLatin1(name()) + '/'); 00833 pSessionConfig = 0L; 00834 bSessionManagement = true; 00835 00836 #ifdef Q_WS_X11 00837 // register a communication window for desktop changes (Matthias) 00838 if (GUIenabled && kde_have_kipc ) 00839 { 00840 smw = new QWidget(0,0); 00841 long data = 1; 00842 XChangeProperty(qt_xdisplay(), smw->winId(), 00843 atom_DesktopWindow, atom_DesktopWindow, 00844 32, PropModeReplace, (unsigned char *)&data, 1); 00845 } 00846 #else 00847 // FIXME(E): Implement for Qt Embedded 00848 #endif 00849 00850 d->oldIceIOErrorHandler = IceSetIOErrorHandler( kde_ice_ioerrorhandler ); 00851 } 00852 00853 static int my_system (const char *command) { 00854 int pid, status; 00855 00856 QApplication::flushX(); 00857 pid = fork(); 00858 if (pid == -1) 00859 return -1; 00860 if (pid == 0) { 00861 const char* shell = "/bin/sh"; 00862 execl(shell, shell, "-c", command, (void *)0); 00863 ::exit(127); 00864 } 00865 do { 00866 if (waitpid(pid, &status, 0) == -1) { 00867 if (errno != EINTR) 00868 return -1; 00869 } else 00870 return status; 00871 } while(1); 00872 } 00873 00874 00875 DCOPClient *KApplication::dcopClient() 00876 { 00877 if (s_DCOPClient) 00878 return s_DCOPClient; 00879 00880 s_DCOPClient = new DCOPClient(); 00881 KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde"); 00882 if (args && args->isSet("dcopserver")) 00883 { 00884 s_DCOPClient->setServerAddress( args->getOption("dcopserver")); 00885 } 00886 if( kapp ) { 00887 connect(s_DCOPClient, SIGNAL(attachFailed(const QString &)), 00888 kapp, SLOT(dcopFailure(const QString &))); 00889 connect(s_DCOPClient, SIGNAL(blockUserInput(bool) ), 00890 kapp, SLOT(dcopBlockUserInput(bool)) ); 00891 } 00892 else 00893 s_dcopClientNeedsPostInit = true; 00894 00895 DCOPClient::setMainClient( s_DCOPClient ); 00896 return s_DCOPClient; 00897 } 00898 00899 void KApplication::dcopClientPostInit() 00900 { 00901 if( s_dcopClientNeedsPostInit ) 00902 { 00903 s_dcopClientNeedsPostInit = false; 00904 connect(s_DCOPClient, SIGNAL(blockUserInput(bool) ), 00905 SLOT(dcopBlockUserInput(bool)) ); 00906 s_DCOPClient->bindToApp(); // Make sure we get events from the DCOPClient. 00907 } 00908 } 00909 00910 void KApplication::dcopAutoRegistration() 00911 { 00912 if (autoDcopRegistration) 00913 { 00914 ( void ) dcopClient(); 00915 if( dcopClient()->appId().isEmpty()) 00916 dcopClient()->registerAs(name()); 00917 } 00918 } 00919 00920 void KApplication::disableAutoDcopRegistration() 00921 { 00922 autoDcopRegistration = false; 00923 } 00924 00925 KConfig* KApplication::sessionConfig() 00926 { 00927 if (pSessionConfig) 00928 return pSessionConfig; 00929 00930 // create an instance specific config object 00931 pSessionConfig = new KConfig( sessionConfigName(), false, false); 00932 return pSessionConfig; 00933 } 00934 00935 void KApplication::ref() 00936 { 00937 d->refCount++; 00938 //kdDebug() << "KApplication::ref() : refCount = " << d->refCount << endl; 00939 } 00940 00941 void KApplication::deref() 00942 { 00943 d->refCount--; 00944 //kdDebug() << "KApplication::deref() : refCount = " << d->refCount << endl; 00945 if ( d->refCount <= 0 ) 00946 quit(); 00947 } 00948 00949 KSessionManaged::KSessionManaged() 00950 { 00951 sessionClients()->remove( this ); 00952 sessionClients()->append( this ); 00953 } 00954 00955 KSessionManaged::~KSessionManaged() 00956 { 00957 sessionClients()->remove( this ); 00958 } 00959 00960 bool KSessionManaged::saveState(QSessionManager&) 00961 { 00962 return true; 00963 } 00964 00965 bool KSessionManaged::commitData(QSessionManager&) 00966 { 00967 return true; 00968 } 00969 00970 00971 void KApplication::disableSessionManagement() { 00972 bSessionManagement = false; 00973 } 00974 00975 void KApplication::enableSessionManagement() { 00976 bSessionManagement = true; 00977 // Session management support in Qt/KDE is awfully broken. 00978 // If konqueror disables session management right after its startup, 00979 // and enables it later (preloading stuff), it won't be properly 00980 // saved on session shutdown. 00981 // I'm not actually sure why it doesn't work, but saveState() 00982 // doesn't seem to be called on session shutdown, possibly 00983 // because disabling session management after konqueror startup 00984 // disabled it somehow. Forcing saveState() here for this application 00985 // seems to fix it. 00986 if( mySmcConnection ) { 00987 SmcRequestSaveYourself( mySmcConnection, SmSaveLocal, False, 00988 SmInteractStyleAny, 00989 False, False ); 00990 00991 // flush the request 00992 IceFlush(SmcGetIceConnection(mySmcConnection)); 00993 } 00994 } 00995 00996 00997 bool KApplication::requestShutDown( 00998 ShutdownConfirm confirm, ShutdownType sdtype, ShutdownMode sdmode ) 00999 { 01000 #ifdef Q_WS_X11 01001 QApplication::syncX(); 01002 /* use ksmserver's dcop interface if necessary */ 01003 if ( confirm == ShutdownConfirmYes || 01004 sdtype != ShutdownTypeDefault || 01005 sdmode != ShutdownModeDefault ) 01006 { 01007 QByteArray data; 01008 QDataStream arg(data, IO_WriteOnly); 01009 arg << (int)confirm << (int)sdtype << (int)sdmode; 01010 return dcopClient()->send( "ksmserver", "ksmserver", 01011 "logout(int,int,int)", data ); 01012 } 01013 01014 if ( mySmcConnection ) { 01015 // we already have a connection to the session manager, use it. 01016 SmcRequestSaveYourself( mySmcConnection, SmSaveBoth, True, 01017 SmInteractStyleAny, 01018 confirm == ShutdownConfirmNo, True ); 01019 01020 // flush the request 01021 IceFlush(SmcGetIceConnection(mySmcConnection)); 01022 return true; 01023 } 01024 01025 // open a temporary connection, if possible 01026 01027 propagateSessionManager(); 01028 QCString smEnv = ::getenv("SESSION_MANAGER"); 01029 if (smEnv.isEmpty()) 01030 return false; 01031 01032 if (! tmpSmcConnection) { 01033 char cerror[256]; 01034 char* myId = 0; 01035 char* prevId = 0; 01036 SmcCallbacks cb; 01037 tmpSmcConnection = SmcOpenConnection( 0, 0, 1, 0, 01038 0, &cb, 01039 prevId, 01040 &myId, 01041 255, 01042 cerror ); 01043 ::free( myId ); // it was allocated by C 01044 if (!tmpSmcConnection ) 01045 return false; 01046 } 01047 01048 SmcRequestSaveYourself( tmpSmcConnection, SmSaveBoth, True, 01049 SmInteractStyleAny, False, True ); 01050 01051 // flush the request 01052 IceFlush(SmcGetIceConnection(tmpSmcConnection)); 01053 return true; 01054 #else 01055 // FIXME(E): Implement for Qt Embedded 01056 return false; 01057 #endif 01058 } 01059 01060 void KApplication::propagateSessionManager() 01061 { 01062 QCString fName = QFile::encodeName(locateLocal("socket", "KSMserver")); 01063 QCString display = ::getenv(DISPLAY); 01064 // strip the screen number from the display 01065 display.replace(QRegExp("\\.[0-9]+$"), ""); 01066 int i; 01067 while( (i = display.find(':')) >= 0) 01068 display[i] = '_'; 01069 01070 fName += "_"+display; 01071 QCString smEnv = ::getenv("SESSION_MANAGER"); 01072 bool check = smEnv.isEmpty(); 01073 if ( !check && smModificationTime ) { 01074 QFileInfo info( fName ); 01075 QTime current = info.lastModified().time(); 01076 check = current > *smModificationTime; 01077 } 01078 if ( check ) { 01079 delete smModificationTime; 01080 QFile f( fName ); 01081 if ( !f.open( IO_ReadOnly ) ) 01082 return; 01083 QFileInfo info ( f ); 01084 smModificationTime = new QTime( info.lastModified().time() ); 01085 QTextStream t(&f); 01086 t.setEncoding( QTextStream::Latin1 ); 01087 QString s = t.readLine(); 01088 f.close(); 01089 ::setenv( "SESSION_MANAGER", s.latin1(), true ); 01090 } 01091 } 01092 01093 void KApplication::commitData( QSessionManager& sm ) 01094 { 01095 d->session_save = true; 01096 bool canceled = false; 01097 for (KSessionManaged* it = sessionClients()->first(); 01098 it && !canceled; 01099 it = sessionClients()->next() ) { 01100 canceled = !it->commitData( sm ); 01101 } 01102 if ( canceled ) 01103 sm.cancel(); 01104 01105 if ( sm.allowsInteraction() ) { 01106 QWidgetList done; 01107 QWidgetList *list = QApplication::topLevelWidgets(); 01108 bool canceled = false; 01109 QWidget* w = list->first(); 01110 while ( !canceled && w ) { 01111 if ( !w->testWState( WState_ForceHide ) && !w->inherits("KMainWindow") ) { 01112 QCloseEvent e; 01113 sendEvent( w, &e ); 01114 canceled = !e.isAccepted(); 01115 if ( !canceled ) 01116 done.append( w ); 01117 delete list; // one never knows... 01118 list = QApplication::topLevelWidgets(); 01119 w = list->first(); 01120 } else { 01121 w = list->next(); 01122 } 01123 while ( w && done.containsRef( w ) ) 01124 w = list->next(); 01125 } 01126 delete list; 01127 } 01128 01129 01130 if ( !bSessionManagement ) 01131 sm.setRestartHint( QSessionManager::RestartNever ); 01132 else 01133 sm.setRestartHint( QSessionManager::RestartIfRunning ); 01134 d->session_save = false; 01135 } 01136 01137 void KApplication::saveState( QSessionManager& sm ) 01138 { 01139 d->session_save = true; 01140 #ifndef Q_WS_QWS 01141 static bool firstTime = true; 01142 mySmcConnection = (SmcConn) sm.handle(); 01143 01144 if ( !bSessionManagement ) { 01145 sm.setRestartHint( QSessionManager::RestartNever ); 01146 d->session_save = false; 01147 return; 01148 } 01149 else 01150 sm.setRestartHint( QSessionManager::RestartIfRunning ); 01151 01152 #if QT_VERSION < 0x030100 01153 { 01154 // generate a new session key 01155 timeval tv; 01156 gettimeofday( &tv, 0 ); 01157 d->sessionKey = QString::number( tv.tv_sec ) + "_" + QString::number(tv.tv_usec); 01158 } 01159 #endif 01160 01161 if ( firstTime ) { 01162 firstTime = false; 01163 d->session_save = false; 01164 return; // no need to save the state. 01165 } 01166 01167 // remove former session config if still existing, we want a new 01168 // and fresh one. Note that we do not delete the config file here, 01169 // this is done by the session manager when it executes the 01170 // discard commands. In fact it would be harmful to remove the 01171 // file here, as the session might be stored under a different 01172 // name, meaning the user still might need it eventually. 01173 if ( pSessionConfig ) { 01174 delete pSessionConfig; 01175 pSessionConfig = 0; 01176 } 01177 01178 // tell the session manager about our new lifecycle 01179 QStringList restartCommand = sm.restartCommand(); 01180 #if QT_VERSION < 0x030100 01181 restartCommand.clear(); 01182 restartCommand << argv()[0] << "-session" << sm.sessionId() << "-smkey" << d->sessionKey; 01183 sm.setRestartCommand( restartCommand ); 01184 #endif 01185 01186 01187 QCString multiHead = getenv("KDE_MULTIHEAD"); 01188 if (multiHead.lower() == "true") { 01189 // if multihead is enabled, we save our -display argument so that 01190 // we are restored onto the correct head... one problem with this 01191 // is that the display is hard coded, which means we cannot restore 01192 // to a different display (ie. if we are in a university lab and try, 01193 // try to restore a multihead session, our apps could be started on 01194 // someone else's display instead of our own) 01195 QCString displayname = getenv(DISPLAY); 01196 if (! displayname.isNull()) { 01197 // only store the command if we actually have a DISPLAY 01198 // environment variable 01199 restartCommand.append("-display"); 01200 restartCommand.append(displayname); 01201 } 01202 sm.setRestartCommand( restartCommand ); 01203 } 01204 01205 01206 // finally: do session management 01207 emit saveYourself(); // for compatibility 01208 bool canceled = false; 01209 for (KSessionManaged* it = sessionClients()->first(); 01210 it && !canceled; 01211 it = sessionClients()->next() ) { 01212 canceled = !it->saveState( sm ); 01213 } 01214 01215 // if we created a new session config object, register a proper discard command 01216 if ( pSessionConfig ) { 01217 pSessionConfig->sync(); 01218 QStringList discard; 01219 discard << "rm" << locateLocal("config", sessionConfigName()); 01220 sm.setDiscardCommand( discard ); 01221 } else { 01222 sm.setDiscardCommand( "" ); 01223 } 01224 01225 if ( canceled ) 01226 sm.cancel(); 01227 #else 01228 // FIXME(E): Implement for Qt Embedded 01229 #endif 01230 d->session_save = false; 01231 } 01232 01233 bool KApplication::sessionSaving() const 01234 { 01235 return d->session_save; 01236 } 01237 01238 void KApplication::startKdeinit() 01239 { 01240 // Try to launch kdeinit. 01241 QString srv = KStandardDirs::findExe(QString::fromLatin1("kdeinit")); 01242 if (srv.isEmpty()) 01243 srv = KStandardDirs::findExe(QString::fromLatin1("kdeinit"), KDEDIR+QString::fromLatin1("/bin")); 01244 if (srv.isEmpty()) 01245 return; 01246 if (kapp && (Tty != kapp->type())) 01247 setOverrideCursor( Qt::waitCursor ); 01248 my_system(QFile::encodeName(srv)+" --suicide"); 01249 if (kapp && (Tty != kapp->type())) 01250 restoreOverrideCursor(); 01251 } 01252 01253 void KApplication::dcopFailure(const QString &msg) 01254 { 01255 static int failureCount = 0; 01256 failureCount++; 01257 if (failureCount == 1) 01258 { 01259 startKdeinit(); 01260 return; 01261 } 01262 if (failureCount == 2) 01263 { 01264 QString msgStr(i18n("There was an error setting up inter-process\n" 01265 "communications for KDE. The message returned\n" 01266 "by the system was:\n\n")); 01267 msgStr += msg; 01268 msgStr += i18n("\n\nPlease check that the \"dcopserver\" program is running!"); 01269 01270 if (Tty != kapp->type()) 01271 { 01272 QMessageBox::critical 01273 ( 01274 kapp->mainWidget(), 01275 i18n("DCOP communications error (%1)").arg(kapp->caption()), 01276 msgStr, 01277 i18n("OK") 01278 ); 01279 } 01280 else 01281 { 01282 fprintf(stderr, "%s\n", msgStr.local8Bit().data()); 01283 } 01284 01285 return; 01286 } 01287 } 01288 01289 static const KCmdLineOptions qt_options[] = 01290 { 01291 //FIXME: Check if other options are specific to Qt/X11 01292 #ifdef Q_WS_X11 01293 { "display <displayname>", I18N_NOOP("Use the X-server display 'displayname'."), 0}, 01294 #else 01295 { "display <displayname>", I18N_NOOP("Use the QWS display 'displayname'."), 0}, 01296 #endif 01297 { "session <sessionId>", I18N_NOOP("Restore the application for the given 'sessionId'."), 0}, 01298 { "cmap", I18N_NOOP("Causes the application to install a private color\nmap on an 8-bit display."), 0}, 01299 { "ncols <count>", I18N_NOOP("Limits the number of colors allocated in the color\ncube on an 8-bit display, if the application is\nusing the QApplication::ManyColor color\nspecification."), 0}, 01300 { "nograb", I18N_NOOP("tells Qt to never grab the mouse or the keyboard."), 0}, 01301 { "dograb", I18N_NOOP("running under a debugger can cause an implicit\n-nograb, use -dograb to override."), 0}, 01302 { "sync", I18N_NOOP("switches to synchronous mode for debugging."), 0}, 01303 { "fn", 0, 0}, 01304 { "font <fontname>", I18N_NOOP("defines the application font."), 0}, 01305 { "bg", 0, 0}, 01306 { "background <color>", I18N_NOOP("sets the default background color and an\napplication palette (light and dark shades are\ncalculated)."), 0}, 01307 { "fg", 0, 0}, 01308 { "foreground <color>", I18N_NOOP("sets the default foreground color."), 0}, 01309 { "btn", 0, 0}, 01310 { "button <color>", I18N_NOOP("sets the default button color."), 0}, 01311 { "name <name>", I18N_NOOP("sets the application name."), 0}, 01312 { "title <title>", I18N_NOOP("sets the application title (caption)."), 0}, 01313 #ifdef Q_WS_X11 01314 { "visual TrueColor", I18N_NOOP("forces the application to use a TrueColor visual on\nan 8-bit display."), 0}, 01315 { "inputstyle <inputstyle>", I18N_NOOP("sets XIM (X Input Method) input style. Possible\nvalues are onthespot, overthespot, offthespot and\nroot."), 0 }, 01316 { "im <XIM server>", I18N_NOOP("set XIM server."),0}, 01317 { "noxim", I18N_NOOP("disable XIM."), 0 }, 01318 #endif 01319 #ifdef Q_WS_QWS 01320 { "qws", I18N_NOOP("forces the application to run as QWS Server."), 0}, 01321 #endif 01322 { "reverse", I18N_NOOP("mirrors the whole layout of widgets."), 0}, 01323 KCmdLineLastOption 01324 }; 01325 01326 static const KCmdLineOptions kde_options[] = 01327 { 01328 { "caption <caption>", I18N_NOOP("Use 'caption' as name in the titlebar."), 0}, 01329 { "icon <icon>", I18N_NOOP("Use 'icon' as the application icon."), 0}, 01330 { "miniicon <icon>", I18N_NOOP("Use 'icon' as the icon in the titlebar."), 0}, 01331 { "config <filename>", I18N_NOOP("Use alternative configuration file."), 0}, 01332 { "dcopserver <server>", I18N_NOOP("Use the DCOP Server specified by 'server'."), 0}, 01333 { "nocrashhandler", I18N_NOOP("Disable crash handler, to get core dumps."), 0}, 01334 { "waitforwm", I18N_NOOP("Waits for a WM_NET compatible windowmanager."), 0}, 01335 { "style <style>", I18N_NOOP("sets the application GUI style."), 0}, 01336 { "geometry <geometry>", I18N_NOOP("sets the client geometry of the main widget."), 0}, 01337 #if QT_VERSION < 0x030100 01338 { "smkey <sessionKey>", I18N_NOOP("Define a 'sessionKey' for the session id. Only valid with -session"), 0}, 01339 #else 01340 { "smkey <sessionKey>", 0, 0}, // this option is obsolete and exists only to allow smooth upgrades from sessions 01341 // saved under Qt 3.0.x -- Qt 3.1.x includes the session key now automatically in 01342 // the session id (Simon) 01343 #endif 01344 KCmdLineLastOption 01345 }; 01346 01347 void 01348 KApplication::addCmdLineOptions() 01349 { 01350 KCmdLineArgs::addCmdLineOptions(qt_options, "Qt", "qt"); 01351 KCmdLineArgs::addCmdLineOptions(kde_options, "KDE", "kde"); 01352 } 01353 01354 void KApplication::parseCommandLine( ) 01355 { 01356 KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde"); 01357 01358 if ( !args ) return; 01359 01360 if (args->isSet("config")) 01361 { 01362 QString config = QString::fromLocal8Bit(args->getOption("config")); 01363 setConfigName(config); 01364 } 01365 01366 if (args->isSet("style")) 01367 { 01368 01369 QStringList styles = QStyleFactory::keys(); 01370 QString reqStyle(args->getOption("style").lower()); 01371 01372 for (QStringList::ConstIterator it = styles.begin(); it != styles.end(); ++it) 01373 if ((*it).lower() == reqStyle) 01374 { 01375 d->overrideStyle = *it; 01376 break; 01377 } 01378 01379 if (d->overrideStyle.isEmpty()) 01380 fprintf(stderr, "%s", i18n("The style %1 was not found\n").arg(reqStyle).local8Bit().data()); 01381 } 01382 01383 if (args->isSet("caption")) 01384 { 01385 aCaption = QString::fromLocal8Bit(args->getOption("caption")); 01386 } 01387 01388 if (args->isSet("miniicon")) 01389 { 01390 const char *tmp = args->getOption("miniicon"); 01391 aMiniIconPixmap = SmallIcon(tmp); 01392 aMiniIconName = tmp; 01393 } 01394 01395 if (args->isSet("icon")) 01396 { 01397 const char *tmp = args->getOption("icon"); 01398 aIconPixmap = DesktopIcon( tmp ); 01399 aIconName = tmp; 01400 if (aMiniIconPixmap.isNull()) 01401 { 01402 aMiniIconPixmap = SmallIcon( tmp ); 01403 aMiniIconName = tmp; 01404 } 01405 } 01406 01407 bool nocrashhandler = (getenv("KDE_DEBUG") != NULL); 01408 if (!nocrashhandler && args->isSet("crashhandler")) 01409 { 01410 // set default crash handler / set emergency save function to nothing 01411 KCrash::setCrashHandler(KCrash::defaultCrashHandler); 01412 KCrash::setEmergencySaveFunction(NULL); 01413 01414 KCrash::setApplicationName(QString(args->appName())); 01415 } 01416 01417 #ifdef Q_WS_X11 01418 if ( args->isSet( "waitforwm" ) ) { 01419 Atom type; 01420 (void) desktop(); // trigger desktop creation, we need PropertyNotify events for the root window 01421 int format; 01422 unsigned long length, after; 01423 unsigned char *data; 01424 while ( XGetWindowProperty( qt_xdisplay(), qt_xrootwin(), atom_NetSupported, 01425 0, 1, false, AnyPropertyType, &type, &format, 01426 &length, &after, &data ) != Success || !length ) { 01427 if ( data ) 01428 XFree( data ); 01429 XEvent event; 01430 XWindowEvent( qt_xdisplay(), qt_xrootwin(), PropertyChangeMask, &event ); 01431 } 01432 if ( data ) 01433 XFree( data ); 01434 } 01435 #else 01436 // FIXME(E): Implement for Qt Embedded 01437 #endif 01438 01439 if (args->isSet("geometry")) 01440 { 01441 d->geometry_arg = args->getOption("geometry"); 01442 } 01443 01444 if (args->isSet("smkey")) 01445 { 01446 d->sessionKey = args->getOption("smkey"); 01447 } 01448 01449 } 01450 01451 QString KApplication::geometryArgument() const 01452 { 01453 return d->geometry_arg; 01454 } 01455 01456 QPixmap KApplication::icon() const 01457 { 01458 if( aIconPixmap.isNull()) { 01459 KApplication *that = const_cast<KApplication *>(this); 01460 that->aIconPixmap = DesktopIcon( instanceName() ); 01461 } 01462 return aIconPixmap; 01463 } 01464 01465 QString KApplication::iconName() const 01466 { 01467 return aIconName.isNull() ? (QString)instanceName() : aIconName; 01468 } 01469 01470 QPixmap KApplication::miniIcon() const 01471 { 01472 if (aMiniIconPixmap.isNull()) { 01473 KApplication *that = const_cast<KApplication *>(this); 01474 that->aMiniIconPixmap = SmallIcon( instanceName() ); 01475 } 01476 return aMiniIconPixmap; 01477 } 01478 01479 QString KApplication::miniIconName() const 01480 { 01481 return aMiniIconName.isNull() ? (QString)instanceName() : aMiniIconName; 01482 } 01483 01484 extern void kDebugCleanup(); 01485 01486 KApplication::~KApplication() 01487 { 01488 delete d->m_KAppDCOPInterface; 01489 01490 // First call the static deleters and then call KLibLoader::cleanup() 01491 // The static deleters may delete libraries for which they need KLibLoader. 01492 // KLibLoader will take care of the remaining ones. 01493 KGlobal::deleteStaticDeleters(); 01494 KLibLoader::cleanUp(); 01495 01496 delete smw; 01497 01498 // close down IPC 01499 delete s_DCOPClient; 01500 s_DCOPClient = 0L; 01501 01502 KProcessController::deref(); 01503 01504 if ( d->oldXErrorHandler != NULL ) 01505 XSetErrorHandler( d->oldXErrorHandler ); 01506 if ( d->oldXIOErrorHandler != NULL ) 01507 XSetIOErrorHandler( d->oldXIOErrorHandler ); 01508 if ( d->oldIceIOErrorHandler != NULL ) 01509 IceSetIOErrorHandler( d->oldIceIOErrorHandler ); 01510 01511 delete d; 01512 KApp = 0; 01513 01514 #ifndef Q_WS_QWS 01515 mySmcConnection = 0; 01516 delete smModificationTime; 01517 smModificationTime = 0; 01518 01519 // close the temporary smc connection 01520 if (tmpSmcConnection) { 01521 SmcCloseConnection( tmpSmcConnection, 0, 0 ); 01522 tmpSmcConnection = 0; 01523 } 01524 #else 01525 // FIXME(E): Implement for Qt Embedded 01526 #endif 01527 } 01528 01529 01530 #ifdef Q_WS_X11 01531 class KAppX11HackWidget: public QWidget 01532 { 01533 public: 01534 bool publicx11Event( XEvent * e) { return x11Event( e ); } 01535 }; 01536 #endif 01537 01538 01539 01540 static bool kapp_block_user_input = false; 01541 01542 void KApplication::dcopBlockUserInput( bool b ) 01543 { 01544 kapp_block_user_input = b; 01545 } 01546 01547 #ifdef Q_WS_X11 01548 bool KApplication::x11EventFilter( XEvent *_event ) 01549 { 01550 switch ( _event->type ) { 01551 case ButtonPress: 01552 case XKeyPress: 01553 { 01554 if( _event->type == ButtonPress ) 01555 qt_x_user_time = _event->xbutton.time; 01556 else // KeyPress 01557 qt_x_user_time = _event->xkey.time; 01558 QWidget* w = activeWindow(); 01559 if( w ) { 01560 XChangeProperty( qt_xdisplay(), w->winId(), kde_net_wm_user_time, XA_CARDINAL, 01561 32, PropModeReplace, (unsigned char*)&qt_x_user_time, 1 ); 01562 timeval tv; 01563 gettimeofday( &tv, NULL ); 01564 unsigned long now = tv.tv_sec * 10 + tv.tv_usec / 100000; 01565 XChangeProperty(qt_xdisplay(), w->winId(), 01566 atom_KdeNetUserTime, XA_CARDINAL, 01567 32, PropModeReplace, (unsigned char *)&now, 1); 01568 } 01569 } 01570 break; 01571 case ClientMessage: 01572 { 01573 #if KDE_IS_VERSION( 3, 2, 91 ) 01574 #warning This should be already in Qt, check. 01575 #endif 01576 // Workaround for focus stealing prevention not working when dragging e.g. text from KWrite 01577 // to KDesktop -> the dialog asking for filename doesn't get activated. This is because 01578 // Qt-3.2.x doesn't have concept of qt_x_user_time at all, and Qt-3.3.0b1 passes the timestamp 01579 // in the XdndDrop message in incorrect field (and doesn't update qt_x_user_time either). 01580 // Patch already sent, future Qt version should have this fixed. 01581 if( _event->xclient.message_type == kde_xdnd_drop ) 01582 { // if the message is XdndDrop 01583 if( _event->xclient.data.l[ 1 ] == 1 << 24 // and it's broken the way it's in Qt-3.2.x 01584 && _event->xclient.data.l[ 2 ] == 0 01585 && _event->xclient.data.l[ 4 ] == 0 01586 && _event->xclient.data.l[ 3 ] != 0 ) 01587 { 01588 if( qt_x_user_time == 0 01589 || ( _event->xclient.data.l[ 3 ] - qt_x_user_time ) < 100000U ) 01590 { // and the timestamp looks reasonable 01591 qt_x_user_time = _event->xclient.data.l[ 3 ]; // update our qt_x_user_time from it 01592 } 01593 } 01594 else // normal DND, only needed until Qt updates qt_x_user_time from XdndDrop 01595 { 01596 if( qt_x_user_time == 0 01597 || ( _event->xclient.data.l[ 2 ] - qt_x_user_time ) < 100000U ) 01598 { // the timestamp looks reasonable 01599 qt_x_user_time = _event->xclient.data.l[ 2 ]; // update our qt_x_user_time from it 01600 } 01601 } 01602 } 01603 } 01604 default: break; 01605 } 01606 01607 if ( kapp_block_user_input ) { 01608 switch ( _event->type ) { 01609 case ButtonPress: 01610 case ButtonRelease: 01611 case XKeyPress: 01612 case XKeyRelease: 01613 case MotionNotify: 01614 return true; 01615 default: 01616 break; 01617 } 01618 } 01619 01620 if (x11Filter) { 01621 for (QWidget *w=x11Filter->first(); w; w=x11Filter->next()) { 01622 if (((KAppX11HackWidget*) w)->publicx11Event(_event)) 01623 return true; 01624 } 01625 } 01626 01627 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 01628 if ((_event->type == ClientMessage) && 01629 (_event->xclient.message_type == kipcCommAtom)) 01630 { 01631 XClientMessageEvent *cme = (XClientMessageEvent *) _event; 01632 01633 int id = cme->data.l[0]; 01634 int arg = cme->data.l[1]; 01635 if ((id < 32) && (kipcEventMask & (1 << id))) 01636 { 01637 switch (id) 01638 { 01639 case KIPC::StyleChanged: 01640 KGlobal::config()->reparseConfiguration(); 01641 kdisplaySetStyle(); 01642 break; 01643 01644 case KIPC::ToolbarStyleChanged: 01645 KGlobal::config()->reparseConfiguration(); 01646 if (useStyles) 01647 emit toolbarAppearanceChanged(arg); 01648 break; 01649 01650 case KIPC::PaletteChanged: 01651 KGlobal::config()->reparseConfiguration(); 01652 kdisplaySetPalette(); 01653 break; 01654 01655 case KIPC::FontChanged: 01656 KGlobal::config()->reparseConfiguration(); 01657 KGlobalSettings::rereadFontSettings(); 01658 kdisplaySetFont(); 01659 break; 01660 01661 case KIPC::BackgroundChanged: 01662 emit backgroundChanged(arg); 01663 break; 01664 01665 case KIPC::SettingsChanged: 01666 KGlobal::config()->reparseConfiguration(); 01667 if (arg == SETTINGS_PATHS) 01668 KGlobalSettings::rereadPathSettings(); 01669 else if (arg == SETTINGS_MOUSE) 01670 KGlobalSettings::rereadMouseSettings(); 01671 propagateSettings((SettingsCategory)arg); 01672 break; 01673 01674 case KIPC::IconChanged: 01675 QPixmapCache::clear(); 01676 KGlobal::config()->reparseConfiguration(); 01677 KGlobal::instance()->newIconLoader(); 01678 emit iconChanged(arg); 01679 break; 01680 01681 case KIPC::ClipboardConfigChanged: 01682 KClipboardSynchronizer::newConfiguration(arg); 01683 break; 01684 } 01685 } 01686 else if (id >= 32) 01687 { 01688 emit kipcMessage(id, arg); 01689 } 01690 return true; 01691 } 01692 #endif // Q_WS_X11 && ! K_WS_QTONLY 01693 return false; 01694 } 01695 #endif 01696 01697 void KApplication::updateUserTimestamp( unsigned long time ) 01698 { 01699 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 01700 if( time == 0 ) 01701 { // get current X timestamp 01702 Window w = XCreateSimpleWindow( qt_xdisplay(), qt_xrootwin(), 0, 0, 1, 1, 0, 0, 0 ); 01703 XSelectInput( qt_xdisplay(), w, PropertyChangeMask ); 01704 unsigned char data[ 1 ]; 01705 XChangeProperty( qt_xdisplay(), w, XA_ATOM, XA_ATOM, 8, PropModeAppend, data, 1 ); 01706 XEvent ev; 01707 XWindowEvent( qt_xdisplay(), w, PropertyChangeMask, &ev ); 01708 time = ev.xproperty.time; 01709 XDestroyWindow( qt_xdisplay(), w ); 01710 } 01711 if( qt_x_user_time == 0 01712 || time - qt_x_user_time < 1000000000U ) // check time > qt_x_user_time, handle wrapping 01713 qt_x_user_time = time; 01714 #endif 01715 } 01716 01717 unsigned long KApplication::userTimestamp() const 01718 { 01719 return qt_x_user_time; 01720 } 01721 01722 void KApplication::invokeEditSlot( const char *slot ) 01723 { 01724 QObject *object = focusWidget(); 01725 if( !object ) 01726 return; 01727 01728 QMetaObject *meta = object->metaObject(); 01729 01730 int idx = meta->findSlot( slot + 1, true ); 01731 if( idx < 0 ) 01732 return; 01733 01734 object->qt_invoke( idx, 0 ); 01735 } 01736 01737 void KApplication::addKipcEventMask(int id) 01738 { 01739 if (id >= 32) 01740 { 01741 kdDebug(101) << "Cannot use KIPC event mask for message IDs >= 32\n"; 01742 return; 01743 } 01744 kipcEventMask |= (1 << id); 01745 } 01746 01747 void KApplication::removeKipcEventMask(int id) 01748 { 01749 if (id >= 32) 01750 { 01751 kdDebug(101) << "Cannot use KIPC event mask for message IDs >= 32\n"; 01752 return; 01753 } 01754 kipcEventMask &= ~(1 << id); 01755 } 01756 01757 void KApplication::enableStyles() 01758 { 01759 if (!useStyles) 01760 { 01761 useStyles = true; 01762 applyGUIStyle(); 01763 } 01764 } 01765 01766 void KApplication::disableStyles() 01767 { 01768 useStyles = false; 01769 } 01770 01771 void KApplication::applyGUIStyle() 01772 { 01773 if ( !useStyles ) return; 01774 01775 KConfigGroup pConfig (KGlobal::config(), "General"); 01776 QString defaultStyle = KStyle::defaultStyle(); 01777 QString styleStr = pConfig.readEntry("widgetStyle", defaultStyle); 01778 01779 if (d->overrideStyle.isEmpty()) { 01780 // ### add check wether we already use the correct style to return then 01781 // (workaround for Qt misbehavior to avoid double style initialization) 01782 01783 QStyle* sp = QStyleFactory::create( styleStr ); 01784 01785 // If there is no default style available, try falling back any available style 01786 if ( !sp && styleStr != defaultStyle) 01787 sp = QStyleFactory::create( defaultStyle ); 01788 if ( !sp ) 01789 sp = QStyleFactory::create( *(QStyleFactory::keys().begin()) ); 01790 setStyle(sp); 01791 } 01792 else 01793 setStyle(d->overrideStyle); 01794 // Reread palette from config file. 01795 kdisplaySetPalette(); 01796 } 01797 01798 QString KApplication::caption() const 01799 { 01800 // Caption set from command line ? 01801 if( !aCaption.isNull() ) 01802 return aCaption; 01803 else 01804 // We have some about data ? 01805 if ( KGlobal::instance()->aboutData() ) 01806 return KGlobal::instance()->aboutData()->programName(); 01807 else 01808 // Last resort : application name 01809 return name(); 01810 } 01811 01812 01813 // 01814 // 1999-09-20: Espen Sand 01815 // An attempt to simplify consistent captions. 01816 // 01817 QString KApplication::makeStdCaption( const QString &userCaption, 01818 bool withAppName, bool modified ) const 01819 { 01820 QString s = userCaption.isEmpty() ? caption() : userCaption; 01821 01822 // If the document is modified, add '[modified]'. 01823 if (modified) 01824 s += QString::fromUtf8(" [") + i18n("modified") + QString::fromUtf8("]"); 01825 01826 if ( !userCaption.isEmpty() ) { 01827 // Add the application name if: 01828 // User asked for it, it's not a duplication and the app name (caption()) is not empty 01829 if ( withAppName && !caption().isNull() && !userCaption.endsWith(caption()) ) 01830 s += QString::fromUtf8(" - ") + caption(); 01831 } 01832 01833 return s; 01834 } 01835 01836 QPalette KApplication::createApplicationPalette() 01837 { 01838 KConfig *config = KGlobal::config(); 01839 KConfigGroupSaver saver( config, "General" ); 01840 return createApplicationPalette( config, KGlobalSettings::contrast() ); 01841 } 01842 01843 QPalette KApplication::createApplicationPalette( KConfig *config, int contrast_ ) 01844 { 01845 QColor kde31Background( 238, 238, 230 ); 01846 QColor kde31Beige( 255,221,118 ); 01847 01848 QColor kde31Button; 01849 if ( QPixmap::defaultDepth() > 8 ) 01850 kde31Button.setRgb( 238, 234, 222 ); 01851 else 01852 kde31Button.setRgb( 220, 220, 220 ); 01853 01854 QColor kde31Link( 0, 0, 192 ); 01855 QColor kde31VisitedLink( 128, 0,128 ); 01856 01857 QColor background = config->readColorEntry( "background", &kde31Background ); 01858 QColor foreground = config->readColorEntry( "foreground", &black ); 01859 QColor button = config->readColorEntry( "buttonBackground", &kde31Button ); 01860 QColor buttonText = config->readColorEntry( "buttonForeground", &foreground ); 01861 QColor highlight = config->readColorEntry( "selectBackground", &kde31Beige ); 01862 QColor highlightedText = config->readColorEntry( "selectForeground", &black ); 01863 QColor base = config->readColorEntry( "windowBackground", &white ); 01864 QColor baseText = config->readColorEntry( "windowForeground", &black ); 01865 QColor link = config->readColorEntry( "linkColor", &kde31Link ); 01866 QColor visitedLink = config->readColorEntry( "visitedLinkColor", &kde31VisitedLink ); 01867 01868 int highlightVal, lowlightVal; 01869 highlightVal = 100 + (2*contrast_+4)*16/10; 01870 lowlightVal = 100 + (2*contrast_+4)*10; 01871 01872 QColor disfg = foreground; 01873 01874 int h, s, v; 01875 disfg.hsv( &h, &s, &v ); 01876 if (v > 128) 01877 // dark bg, light fg - need a darker disabled fg 01878 disfg = disfg.dark(lowlightVal); 01879 else if (disfg != black) 01880 // light bg, dark fg - need a lighter disabled fg - but only if !black 01881 disfg = disfg.light(highlightVal); 01882 else 01883 // black fg - use darkgray disabled fg 01884 disfg = Qt::darkGray; 01885 01886 01887 QColorGroup disabledgrp(disfg, background, 01888 background.light(highlightVal), 01889 background.dark(lowlightVal), 01890 background.dark(120), 01891 background.dark(120), base); 01892 01893 QColorGroup colgrp(foreground, background, background.light(highlightVal), 01894 background.dark(lowlightVal), 01895 background.dark(120), 01896 baseText, base); 01897 01898 int inlowlightVal = lowlightVal-25; 01899 if(inlowlightVal < 120) 01900 inlowlightVal = 120; 01901 01902 colgrp.setColor(QColorGroup::Highlight, highlight); 01903 colgrp.setColor(QColorGroup::HighlightedText, highlightedText); 01904 colgrp.setColor(QColorGroup::Button, button); 01905 colgrp.setColor(QColorGroup::ButtonText, buttonText); 01906 colgrp.setColor(QColorGroup::Midlight, background.light(110)); 01907 colgrp.setColor(QColorGroup::Link, link); 01908 colgrp.setColor(QColorGroup::LinkVisited, visitedLink); 01909 01910 disabledgrp.setColor(QColorGroup::Button, button); 01911 01912 QColor disbtntext = buttonText; 01913 disbtntext.hsv( &h, &s, &v ); 01914 if (v > 128) 01915 // dark button, light buttonText - need a darker disabled buttonText 01916 disbtntext = disbtntext.dark(lowlightVal); 01917 else if (disbtntext != black) 01918 // light buttonText, dark button - need a lighter disabled buttonText - but only if !black 01919 disbtntext = disbtntext.light(highlightVal); 01920 else 01921 // black button - use darkgray disabled buttonText 01922 disbtntext = Qt::darkGray; 01923 01924 disabledgrp.setColor(QColorGroup::ButtonText, disbtntext); 01925 disabledgrp.setColor(QColorGroup::Midlight, background.light(110)); 01926 disabledgrp.setColor(QColorGroup::Highlight, highlight.dark(120)); 01927 disabledgrp.setColor(QColorGroup::Link, link); 01928 disabledgrp.setColor(QColorGroup::LinkVisited, visitedLink); 01929 01930 return QPalette(colgrp, disabledgrp, colgrp); 01931 } 01932 01933 01934 void KApplication::kdisplaySetPalette() 01935 { 01936 QApplication::setPalette( createApplicationPalette(), true); 01937 emit kdisplayPaletteChanged(); 01938 emit appearanceChanged(); 01939 } 01940 01941 01942 void KApplication::kdisplaySetFont() 01943 { 01944 QApplication::setFont(KGlobalSettings::generalFont(), true); 01945 QApplication::setFont(KGlobalSettings::menuFont(), true, "QMenuBar"); 01946 QApplication::setFont(KGlobalSettings::menuFont(), true, "QPopupMenu"); 01947 QApplication::setFont(KGlobalSettings::menuFont(), true, "KPopupTitle"); 01948 01949 // "patch" standard QStyleSheet to follow our fonts 01950 QStyleSheet* sheet = QStyleSheet::defaultSheet(); 01951 sheet->item ("pre")->setFontFamily (KGlobalSettings::fixedFont().family()); 01952 sheet->item ("code")->setFontFamily (KGlobalSettings::fixedFont().family()); 01953 sheet->item ("tt")->setFontFamily (KGlobalSettings::fixedFont().family()); 01954 01955 emit kdisplayFontChanged(); 01956 emit appearanceChanged(); 01957 } 01958 01959 01960 void KApplication::kdisplaySetStyle() 01961 { 01962 if (useStyles) 01963 { 01964 applyGUIStyle(); 01965 emit kdisplayStyleChanged(); 01966 emit appearanceChanged(); 01967 } 01968 } 01969 01970 01971 void KApplication::propagateSettings(SettingsCategory arg) 01972 { 01973 KConfigBase* config = KGlobal::config(); 01974 KConfigGroupSaver saver( config, "KDE" ); 01975 01976 int num = config->readNumEntry("CursorBlinkRate", QApplication::cursorFlashTime()); 01977 if (num < 200) 01978 num = 200; 01979 if (num > 2000) 01980 num = 2000; 01981 QApplication::setCursorFlashTime(num); 01982 num = config->readNumEntry("DoubleClickInterval", QApplication::doubleClickInterval()); 01983 QApplication::setDoubleClickInterval(num); 01984 num = config->readNumEntry("StartDragTime", QApplication::startDragTime()); 01985 QApplication::setStartDragTime(num); 01986 num = config->readNumEntry("StartDragDist", QApplication::startDragDistance()); 01987 QApplication::setStartDragDistance(num); 01988 num = config->readNumEntry("WheelScrollLines", QApplication::wheelScrollLines()); 01989 QApplication::setWheelScrollLines(num); 01990 01991 bool b = config->readBoolEntry("EffectAnimateMenu", false); 01992 QApplication::setEffectEnabled( Qt::UI_AnimateMenu, b); 01993 b = config->readBoolEntry("EffectFadeMenu", false); 01994 QApplication::setEffectEnabled( Qt::UI_FadeMenu, b); 01995 b = config->readBoolEntry("EffectAnimateCombo", false); 01996 QApplication::setEffectEnabled( Qt::UI_AnimateCombo, b); 01997 b = config->readBoolEntry("EffectAnimateTooltip", false); 01998 QApplication::setEffectEnabled( Qt::UI_AnimateTooltip, b); 01999 b = config->readBoolEntry("EffectFadeTooltip", false); 02000 QApplication::setEffectEnabled( Qt::UI_FadeTooltip, b); 02001 b = !config->readBoolEntry("EffectNoTooltip", false); 02002 QToolTip::setGloballyEnabled( b ); 02003 02004 emit settingsChanged(arg); 02005 } 02006 02007 void KApplication::installKDEPropertyMap() 02008 { 02009 #ifndef QT_NO_SQL 02010 static bool installed = false; 02011 if (installed) return; 02012 installed = true; 02019 // QSqlPropertyMap takes ownership of the new default map. 02020 QSqlPropertyMap *kdeMap = new QSqlPropertyMap; 02021 kdeMap->insert( "KColorButton", "color" ); 02022 kdeMap->insert( "KComboBox", "currentItem" ); 02023 kdeMap->insert( "KDatePicker", "date" ); 02024 kdeMap->insert( "KEditListBox", "currentItem" ); 02025 kdeMap->insert( "KFontCombo", "family" ); 02026 kdeMap->insert( "KFontRequester", "font" ); 02027 kdeMap->insert( "KFontChooser", "font" ); 02028 kdeMap->insert( "KHistoryCombo", "currentItem" ); 02029 kdeMap->insert( "KListBox", "currentItem" ); 02030 kdeMap->insert( "KLineEdit", "text" ); 02031 kdeMap->insert( "KRestrictedLine", "text" ); 02032 kdeMap->insert( "KSqueezedTextLabel", "text" ); 02033 kdeMap->insert( "KTextBrowser", "source" ); 02034 kdeMap->insert( "KTextEdit", "text" ); 02035 kdeMap->insert( "KURLRequester", "url" ); 02036 kdeMap->insert( "KPasswordEdit", "password" ); 02037 kdeMap->insert( "KIntNumInput", "value" ); 02038 kdeMap->insert( "KIntSpinBox", "value" ); 02039 kdeMap->insert( "KDoubleNumInput", "value" ); 02040 #if QT_VERSION < 0x030200 02041 kdeMap->insert( "QRadioButton", "checked" ); 02042 #endif 02043 //#if QT_VERSION < 0x030300 02044 // Temp til fixed in QT then enable ifdef with the correct version num 02045 kdeMap->insert( "QTabWidget", "currentPage" ); 02046 //#endif 02047 QSqlPropertyMap::installDefaultMap( kdeMap ); 02048 #endif 02049 } 02050 02051 void KApplication::invokeHelp( const QString& anchor, 02052 const QString& _appname) const 02053 { 02054 return invokeHelp( anchor, _appname, "" ); 02055 } 02056 02057 void KApplication::invokeHelp( const QString& anchor, 02058 const QString& _appname, 02059 const QCString& startup_id ) const 02060 { 02061 QString url; 02062 QString appname; 02063 if (_appname.isEmpty()) 02064 appname = name(); 02065 else 02066 appname = _appname; 02067 02068 if (!anchor.isEmpty()) 02069 url = QString("help:/%1?anchor=%2").arg(appname).arg(anchor); 02070 else 02071 url = QString("help:/%1/index.html").arg(appname); 02072 02073 QString error; 02074 if ( !dcopClient()->isApplicationRegistered("khelpcenter") ) 02075 { 02076 if (startServiceByDesktopName("khelpcenter", url, &error, 0, 0, startup_id, false)) 02077 { 02078 kdWarning() << "Could not launch help:\n" << error << endl; 02079 return; 02080 } 02081 } 02082 else 02083 DCOPRef( "khelpcenter", "KHelpCenterIface" ).send( "openUrl", url, startup_id ); 02084 } 02085 02086 void KApplication::invokeHTMLHelp( const QString& _filename, const QString& topic ) const 02087 { 02088 kdWarning() << "invoking HTML help is deprecated! use docbook and invokeHelp!\n"; 02089 02090 QString filename; 02091 02092 if( _filename.isEmpty() ) 02093 filename = QString(name()) + "/index.html"; 02094 else 02095 filename = _filename; 02096 02097 QString url; 02098 if (!topic.isEmpty()) 02099 url = QString("help:/%1#%2").arg(filename).arg(topic); 02100 else 02101 url = QString("help:/%1").arg(filename); 02102 02103 QString error; 02104 if ( !dcopClient()->isApplicationRegistered("khelpcenter") ) 02105 { 02106 if (startServiceByDesktopName("khelpcenter", url, &error, 0, 0, "", false)) 02107 { 02108 kdWarning() << "Could not launch help:\n" << error << endl; 02109 return; 02110 } 02111 } 02112 else 02113 DCOPRef( "khelpcenter", "KHelpCenterIface" ).send( "openUrl", url ); 02114 } 02115 02116 02117 void KApplication::invokeMailer(const QString &address, const QString &subject) 02118 { 02119 return invokeMailer(address,subject,""); 02120 } 02121 02122 void KApplication::invokeMailer(const QString &address, const QString &subject, const QCString& startup_id) 02123 { 02124 invokeMailer(address, QString::null, QString::null, subject, QString::null, QString::null, 02125 QStringList(), startup_id ); 02126 } 02127 02128 void KApplication::invokeMailer(const KURL &mailtoURL) 02129 { 02130 return invokeMailer( mailtoURL, "" ); 02131 } 02132 02133 void KApplication::invokeMailer(const KURL &mailtoURL, const QCString& startup_id ) 02134 { 02135 QString address = KURL::decode_string(mailtoURL.path()), subject, cc, bcc, body, attach; 02136 QStringList queries = QStringList::split('&', mailtoURL.query().mid(1)); 02137 for (QStringList::Iterator it = queries.begin(); it != queries.end(); ++it) 02138 { 02139 QString q = (*it).lower(); 02140 if (q.startsWith("subject=")) 02141 subject = KURL::decode_string((*it).mid(8)); 02142 else 02143 if (q.startsWith("cc=")) 02144 cc = KURL::decode_string((*it).mid(3)); 02145 else 02146 if (q.startsWith("bcc=")) 02147 bcc = KURL::decode_string((*it).mid(4)); 02148 else 02149 if (q.startsWith("body=")) 02150 body = KURL::decode_string((*it).mid(5)); 02151 //else 02152 // if (q.startsWith("attach=")) 02153 // attach = KURL::decode_string((*it).mid(7)); 02154 } 02155 02156 invokeMailer( address, cc, bcc, subject, body, QString::null, QStringList(), startup_id ); 02157 } 02158 02159 void KApplication::invokeMailer(const QString &to, const QString &cc, const QString &bcc, 02160 const QString &subject, const QString &body, 02161 const QString & messageFile, const QStringList &attachURLs) 02162 { 02163 return invokeMailer(to,cc,bcc,subject,body,messageFile,attachURLs,""); 02164 } 02165 02166 void KApplication::invokeMailer(const QString &to, const QString &cc, const QString &bcc, 02167 const QString &subject, const QString &body, 02168 const QString & /*messageFile TODO*/, const QStringList &attachURLs, 02169 const QCString& startup_id ) 02170 { 02171 KConfig config("emaildefaults"); 02172 02173 config.setGroup("Defaults"); 02174 QString group = config.readEntry("Profile","Default"); 02175 02176 config.setGroup( QString("PROFILE_%1").arg(group) ); 02177 QString command = config.readPathEntry("EmailClient"); 02178 02179 if (command.isEmpty() || command == QString::fromLatin1("kmail") 02180 || command.endsWith("/kmail")) 02181 command = QString::fromLatin1("kmail --composer -s %s -c %c -b %b --body %B --attach %A -- %t"); 02182 02183 // TODO: Take care of the preferred terminal app (instead of hardcoding 02184 // Konsole), this will probably require a rewrite of the configurable 02185 // terminal client option because the placeholder for the program which 02186 // has to be executed by the terminal has to be supplied (e.g. something 02187 // like '/opt/kde2/bin/konsole -e %p'). - Frerich 02188 if (config.readBoolEntry("TerminalClient", false)) 02189 command = "konsole -e " + command; 02190 02191 QStringList cmdTokens = KShell::splitArgs(command); 02192 QString cmd = cmdTokens[0]; 02193 cmdTokens.remove(cmdTokens.begin()); 02194 02195 QMap<QChar, QString> keyMap; 02196 keyMap.insert('t', to); 02197 keyMap.insert('s', subject); 02198 keyMap.insert('c', cc); 02199 keyMap.insert('b', bcc); 02200 keyMap.insert('B', body); 02201 02202 for (QStringList::Iterator it = cmdTokens.begin(); it != cmdTokens.end(); ) 02203 { 02204 if (*it == "%A") 02205 { 02206 if (it == cmdTokens.begin()) // better safe than sorry ... 02207 continue; 02208 QStringList::ConstIterator urlit = attachURLs.begin(); 02209 QStringList::ConstIterator urlend = attachURLs.end(); 02210 if ( urlit != urlend ) 02211 { 02212 QStringList::Iterator previt = it; 02213 --previt; 02214 *it = *urlit; 02215 ++it; 02216 while ( ++urlit != urlend ) 02217 { 02218 cmdTokens.insert( it, *previt ); 02219 cmdTokens.insert( it, *urlit ); 02220 } 02221 } else { 02222 --it; 02223 it = cmdTokens.remove( cmdTokens.remove( it ) ); 02224 } 02225 } else { 02226 *it = KMacroExpander::expandMacros(*it, keyMap); 02227 ++it; 02228 } 02229 } 02230 02231 QString error; 02232 // TODO this should check if cmd has a .desktop file, and use data from it, together 02233 // with sending more ASN data 02234 if (kdeinitExec(cmd, cmdTokens, &error, NULL, startup_id )) 02235 kdWarning() << "Could not launch mail client:\n" << error << endl; 02236 } 02237 02238 02239 void KApplication::invokeBrowser( const QString &url ) 02240 { 02241 return invokeBrowser( url, "" ); 02242 } 02243 02244 void KApplication::invokeBrowser( const QString &url, const QCString& startup_id ) 02245 { 02246 QString error; 02247 02248 if (startServiceByDesktopName("kfmclient", url, &error, 0, 0, startup_id, false)) 02249 { 02250 kdWarning() << "Could not launch browser:\n" << error << endl; 02251 return; 02252 } 02253 } 02254 02255 void KApplication::cut() 02256 { 02257 invokeEditSlot( SLOT( cut() ) ); 02258 } 02259 02260 void KApplication::copy() 02261 { 02262 invokeEditSlot( SLOT( copy() ) ); 02263 } 02264 02265 void KApplication::paste() 02266 { 02267 invokeEditSlot( SLOT( paste() ) ); 02268 } 02269 02270 void KApplication::clear() 02271 { 02272 invokeEditSlot( SLOT( clear() ) ); 02273 } 02274 02275 void KApplication::selectAll() 02276 { 02277 invokeEditSlot( SLOT( selectAll() ) ); 02278 } 02279 02280 QCString 02281 KApplication::launcher() 02282 { 02283 return "klauncher"; 02284 } 02285 02286 static int 02287 startServiceInternal( const QCString &function, 02288 const QString& _name, const QStringList &URLs, 02289 QString *error, QCString *dcopService, int *pid, const QCString& startup_id, bool noWait ) 02290 { 02291 struct serviceResult 02292 { 02293 int result; 02294 QCString dcopName; 02295 QString error; 02296 pid_t pid; 02297 }; 02298 02299 // Register app as able to send DCOP messages 02300 DCOPClient *dcopClient; 02301 if (kapp) 02302 dcopClient = kapp->dcopClient(); 02303 else 02304 dcopClient = new DCOPClient; 02305 02306 if (!dcopClient->isAttached()) 02307 { 02308 if (!dcopClient->attach()) 02309 { 02310 if (error) 02311 *error = i18n("Could not register with DCOP.\n"); 02312 return -1; 02313 } 02314 } 02315 QByteArray params; 02316 QDataStream stream(params, IO_WriteOnly); 02317 stream << _name << URLs; 02318 QCString replyType; 02319 QByteArray replyData; 02320 QCString _launcher = KApplication::launcher(); 02321 QValueList<QCString> envs; 02322 #ifdef Q_WS_X11 02323 if (qt_xdisplay()) { 02324 QCString dpystring(XDisplayString(qt_xdisplay())); 02325 envs.append( QCString("DISPLAY=") + dpystring ); 02326 } else if( getenv( "DISPLAY" )) { 02327 QCString dpystring( getenv( "DISPLAY" )); 02328 envs.append( QCString("DISPLAY=") + dpystring ); 02329 } 02330 #endif 02331 stream << envs << startup_id; 02332 if( function.left( 12 ) != "kdeinit_exec" ) 02333 stream << noWait; 02334 02335 if (!dcopClient->call(_launcher, _launcher, 02336 function, params, replyType, replyData)) 02337 { 02338 if (error) 02339 *error = i18n("KLauncher could not be reached via DCOP.\n"); 02340 if (!kapp) 02341 delete dcopClient; 02342 return -1; 02343 } 02344 if (!kapp) 02345 delete dcopClient; 02346 02347 if (noWait) 02348 return 0; 02349 02350 QDataStream stream2(replyData, IO_ReadOnly); 02351 serviceResult result; 02352 stream2 >> result.result >> result.dcopName >> result.error >> result.pid; 02353 if (dcopService) 02354 *dcopService = result.dcopName; 02355 if (error) 02356 *error = result.error; 02357 if (pid) 02358 *pid = result.pid; 02359 return result.result; 02360 } 02361 02362 int 02363 KApplication::startServiceByName( const QString& _name, const QString &URL, 02364 QString *error, QCString *dcopService, int *pid, const QCString& startup_id, bool noWait ) 02365 { 02366 QStringList URLs; 02367 if (!URL.isEmpty()) 02368 URLs.append(URL); 02369 return startServiceInternal( 02370 "start_service_by_name(QString,QStringList,QValueList<QCString>,QCString,bool)", 02371 _name, URLs, error, dcopService, pid, startup_id, noWait); 02372 } 02373 02374 int 02375 KApplication::startServiceByName( const QString& _name, const QStringList &URLs, 02376 QString *error, QCString *dcopService, int *pid, const QCString& startup_id, bool noWait ) 02377 { 02378 return startServiceInternal( 02379 "start_service_by_name(QString,QStringList,QValueList<QCString>,QCString,bool)", 02380 _name, URLs, error, dcopService, pid, startup_id, noWait); 02381 } 02382 02383 int 02384 KApplication::startServiceByDesktopPath( const QString& _name, const QString &URL, 02385 QString *error, QCString *dcopService, int *pid, const QCString& startup_id, bool noWait ) 02386 { 02387 QStringList URLs; 02388 if (!URL.isEmpty()) 02389 URLs.append(URL); 02390 return startServiceInternal( 02391 "start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString,bool)", 02392 _name, URLs, error, dcopService, pid, startup_id, noWait); 02393 } 02394 02395 int 02396 KApplication::startServiceByDesktopPath( const QString& _name, const QStringList &URLs, 02397 QString *error, QCString *dcopService, int *pid, const QCString& startup_id, bool noWait ) 02398 { 02399 return startServiceInternal( 02400 "start_service_by_desktop_path(QString,QStringList,QValueList<QCString>,QCString,bool)", 02401 _name, URLs, error, dcopService, pid, startup_id, noWait); 02402 } 02403 02404 int 02405 KApplication::startServiceByDesktopName( const QString& _name, const QString &URL, 02406 QString *error, QCString *dcopService, int *pid, const QCString& startup_id, bool noWait ) 02407 { 02408 QStringList URLs; 02409 if (!URL.isEmpty()) 02410 URLs.append(URL); 02411 return startServiceInternal( 02412 "start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString,bool)", 02413 _name, URLs, error, dcopService, pid, startup_id, noWait); 02414 } 02415 02416 int 02417 KApplication::startServiceByDesktopName( const QString& _name, const QStringList &URLs, 02418 QString *error, QCString *dcopService, int *pid, const QCString& startup_id, bool noWait ) 02419 { 02420 return startServiceInternal( 02421 "start_service_by_desktop_name(QString,QStringList,QValueList<QCString>,QCString,bool)", 02422 _name, URLs, error, dcopService, pid, startup_id, noWait); 02423 } 02424 02425 int 02426 KApplication::kdeinitExec( const QString& name, const QStringList &args, 02427 QString *error, int *pid ) 02428 { 02429 return kdeinitExec( name, args, error, pid, "" ); 02430 } 02431 02432 int 02433 KApplication::kdeinitExec( const QString& name, const QStringList &args, 02434 QString *error, int *pid, const QCString& startup_id ) 02435 { 02436 return startServiceInternal("kdeinit_exec(QString,QStringList,QValueList<QCString>,QCString)", 02437 name, args, error, 0, pid, startup_id, false); 02438 } 02439 02440 int 02441 KApplication::kdeinitExecWait( const QString& name, const QStringList &args, 02442 QString *error, int *pid ) 02443 { 02444 return kdeinitExecWait( name, args, error, pid, "" ); 02445 } 02446 02447 int 02448 KApplication::kdeinitExecWait( const QString& name, const QStringList &args, 02449 QString *error, int *pid, const QCString& startup_id ) 02450 { 02451 return startServiceInternal("kdeinit_exec_wait(QString,QStringList,QValueList<QCString>,QCString)", 02452 name, args, error, 0, pid, startup_id, false); 02453 } 02454 02455 QString KApplication::tempSaveName( const QString& pFilename ) const 02456 { 02457 QString aFilename; 02458 02459 if( pFilename[0] != '/' ) 02460 { 02461 kdWarning(101) << "Relative filename passed to KApplication::tempSaveName" << endl; 02462 aFilename = QFileInfo( QDir( "." ), pFilename ).absFilePath(); 02463 } 02464 else 02465 aFilename = pFilename; 02466 02467 QDir aAutosaveDir( QDir::homeDirPath() + "/autosave/" ); 02468 if( !aAutosaveDir.exists() ) 02469 { 02470 if( !aAutosaveDir.mkdir( aAutosaveDir.absPath() ) ) 02471 { 02472 // Last chance: use temp dir 02473 aAutosaveDir.setPath( KGlobal::dirs()->saveLocation("tmp") ); 02474 } 02475 } 02476 02477 aFilename.replace( "/", "\\!" ).prepend( "#" ).append( "#" ).prepend( "/" ).prepend( aAutosaveDir.absPath() ); 02478 02479 return aFilename; 02480 } 02481 02482 02483 QString KApplication::checkRecoverFile( const QString& pFilename, 02484 bool& bRecover ) const 02485 { 02486 QString aFilename; 02487 02488 if( pFilename[0] != '/' ) 02489 { 02490 kdWarning(101) << "Relative filename passed to KApplication::tempSaveName" << endl; 02491 aFilename = QFileInfo( QDir( "." ), pFilename ).absFilePath(); 02492 } 02493 else 02494 aFilename = pFilename; 02495 02496 QDir aAutosaveDir( QDir::homeDirPath() + "/autosave/" ); 02497 if( !aAutosaveDir.exists() ) 02498 { 02499 if( !aAutosaveDir.mkdir( aAutosaveDir.absPath() ) ) 02500 { 02501 // Last chance: use temp dir 02502 aAutosaveDir.setPath( KGlobal::dirs()->saveLocation("tmp") ); 02503 } 02504 } 02505 02506 aFilename.replace( "/", "\\!" ).prepend( "#" ).append( "#" ).prepend( "/" ).prepend( aAutosaveDir.absPath() ); 02507 02508 if( QFile( aFilename ).exists() ) 02509 { 02510 bRecover = true; 02511 return aFilename; 02512 } 02513 else 02514 { 02515 bRecover = false; 02516 return pFilename; 02517 } 02518 } 02519 02520 02521 bool checkAccess(const QString& pathname, int mode) 02522 { 02523 int accessOK = access( QFile::encodeName(pathname), mode ); 02524 if ( accessOK == 0 ) 02525 return true; // OK, I can really access the file 02526 02527 // else 02528 // if we want to write the file would be created. Check, if the 02529 // user may write to the directory to create the file. 02530 if ( (mode & W_OK) == 0 ) 02531 return false; // Check for write access is not part of mode => bail out 02532 02533 02534 if (!access( QFile::encodeName(pathname), F_OK)) // if it already exists 02535 return false; 02536 02537 //strip the filename (everything until '/' from the end 02538 QString dirName(pathname); 02539 int pos = dirName.findRev('/'); 02540 if ( pos == -1 ) 02541 return false; // No path in argument. This is evil, we won't allow this 02542 else if ( pos == 0 ) // don't turn e.g. /root into an empty string 02543 pos = 1; 02544 02545 dirName.truncate(pos); // strip everything starting from the last '/' 02546 02547 accessOK = access( QFile::encodeName(dirName), W_OK ); 02548 // -?- Can I write to the accessed diretory 02549 if ( accessOK == 0 ) 02550 return true; // Yes 02551 else 02552 return false; // No 02553 } 02554 02555 void KApplication::setTopWidget( QWidget *topWidget ) 02556 { 02557 if( topWidget != 0 ) 02558 { 02559 #ifdef Q_WS_X11 // FIXME(E): Implement for Qt/Embedded 02560 Window leader = topWidget->winId(); 02561 char* argv = const_cast< char* >( KCmdLineArgs::appName()); 02562 XSetCommand(display, leader, &argv, 1); 02563 // this hints thing may go after Qt always sets window_group 02564 XWMHints *hints = XGetWMHints(display, topWidget->winId()); 02565 if (hints) 02566 { 02567 if (!(hints->flags & WindowGroupHint)) 02568 { 02569 hints->window_group = leader; 02570 hints->flags |= WindowGroupHint; 02571 } 02572 if (!(hints->flags & InputHint)) 02573 { 02574 hints->input = True; 02575 hints->flags |= InputHint; 02576 } 02577 XSetWMHints(display, topWidget->winId(), hints); 02578 XFree(reinterpret_cast<char *>(hints)); 02579 } 02580 02581 #endif 02582 // set the specified caption 02583 if ( !topWidget->inherits("KMainWindow") ) { // KMainWindow does this already for us 02584 topWidget->setCaption( caption() ); 02585 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 02586 //#ifndef Q_WS_QWS // FIXME(E): Implement for Qt/Embedded 02587 NETWinInfo info(qt_xdisplay(), topWidget->winId(), qt_xrootwin(), NET::WMName ); 02588 info.setName( caption().utf8().data() ); 02589 #endif 02590 } 02591 02592 // set the specified icons 02593 topWidget->setIcon( icon() ); //standard X11 02594 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 02595 //#ifdef Q_WS_X11 // FIXME(E): Implement for Qt/Embedded 02596 KWin::setIcons(topWidget->winId(), icon(), miniIcon() ); // NET_WM hints for KWin 02597 02598 // set the app startup notification window property 02599 KStartupInfo::setWindowStartupId( topWidget->winId(), startupId()); 02600 #endif 02601 } 02602 } 02603 02604 QCString KApplication::startupId() const 02605 { 02606 return d->startup_id; 02607 } 02608 02609 void KApplication::setStartupId( const QCString& startup_id ) 02610 { 02611 if( startup_id.isEmpty()) 02612 d->startup_id = "0"; 02613 else 02614 d->startup_id = startup_id; 02615 } 02616 02617 // read the startup notification env variable, save it and unset it in order 02618 // not to propagate it to processes started from this app 02619 void KApplication::read_app_startup_id() 02620 { 02621 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 02622 KStartupInfoId id = KStartupInfo::currentStartupIdEnv(); 02623 KStartupInfo::resetStartupEnv(); 02624 d->startup_id = id.id(); 02625 #endif 02626 } 02627 02628 int KApplication::random() 02629 { 02630 static int init = false; 02631 if (!init) 02632 { 02633 unsigned int seed; 02634 init = true; 02635 int fd = open("/dev/urandom", O_RDONLY); 02636 if (fd <= 0 || ::read(fd, &seed, sizeof(seed)) != sizeof(seed)) 02637 { 02638 // No /dev/urandom... try something else. 02639 srand(getpid()); 02640 seed = rand()+time(0); 02641 } 02642 if (fd >= 0) close(fd); 02643 srand(seed); 02644 } 02645 return rand(); 02646 } 02647 02648 QString KApplication::randomString(int length) 02649 { 02650 if (length <=0 ) return QString::null; 02651 02652 QString str; str.setLength( length ); 02653 int i = 0; 02654 while (length--) 02655 { 02656 int r=random() % 62; 02657 r+=48; 02658 if (r>57) r+=7; 02659 if (r>90) r+=6; 02660 str[i++] = char(r); 02661 // so what if I work backwards? 02662 } 02663 return str; 02664 } 02665 02666 bool KApplication::authorize(const QString &genericAction) 02667 { 02668 if (!d->actionRestrictions) 02669 return true; 02670 02671 KConfig *config = KGlobal::config(); 02672 KConfigGroupSaver saver( config, "KDE Action Restrictions" ); 02673 return config->readBoolEntry(genericAction, true); 02674 } 02675 02676 bool KApplication::authorizeKAction(const char *action) 02677 { 02678 if (!d->actionRestrictions || !action) 02679 return true; 02680 02681 static const QString &action_prefix = KGlobal::staticQString( "action/" ); 02682 02683 return authorize(action_prefix + action); 02684 } 02685 02686 bool KApplication::authorizeControlModule(const QString &menuId) 02687 { 02688 if (menuId.isEmpty()) 02689 return true; 02690 KConfig *config = KGlobal::config(); 02691 KConfigGroupSaver saver( config, "KDE Control Module Restrictions" ); 02692 return config->readBoolEntry(menuId, true); 02693 } 02694 02695 QStringList KApplication::authorizeControlModules(const QStringList &menuIds) 02696 { 02697 KConfig *config = KGlobal::config(); 02698 KConfigGroupSaver saver( config, "KDE Control Module Restrictions" ); 02699 QStringList result; 02700 for(QStringList::ConstIterator it = menuIds.begin(); 02701 it != menuIds.end(); ++it) 02702 { 02703 if (config->readBoolEntry(*it, true)) 02704 result.append(*it); 02705 } 02706 return result; 02707 } 02708 02709 void KApplication::initUrlActionRestrictions() 02710 { 02711 d->urlActionRestrictions.setAutoDelete(true); 02712 d->urlActionRestrictions.clear(); 02713 d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule 02714 ("open", QString::null, QString::null, QString::null, QString::null, QString::null, QString::null, true)); 02715 d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule 02716 ("list", QString::null, QString::null, QString::null, QString::null, QString::null, QString::null, true)); 02717 // TEST: 02718 // d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule 02719 // ("list", QString::null, QString::null, QString::null, QString::null, QString::null, QString::null, false)); 02720 // d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule 02721 // ("list", QString::null, QString::null, QString::null, "file", QString::null, QDir::homeDirPath(), true)); 02722 d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule 02723 ("link", QString::null, QString::null, QString::null, ":internet", QString::null, QString::null, true)); 02724 d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule 02725 ("redirect", QString::null, QString::null, QString::null, ":internet", QString::null, QString::null, true)); 02726 02727 // We allow redirections to file: but not from internet protocols, redirecting to file: 02728 // is very popular among io-slaves and we don't want to break them 02729 d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule 02730 ("redirect", QString::null, QString::null, QString::null, "file", QString::null, QString::null, true)); 02731 d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule 02732 ("redirect", ":internet", QString::null, QString::null, "file", QString::null, QString::null, false)); 02733 02734 // local protocols may redirect everywhere 02735 d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule 02736 ("redirect", ":local", QString::null, QString::null, QString::null, QString::null, QString::null, true)); 02737 02738 // Anyone may redirect to about: 02739 d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule 02740 ("redirect", QString::null, QString::null, QString::null, "about", QString::null, QString::null, true)); 02741 02742 // Anyone may redirect to itself, cq. within it's own group 02743 d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule 02744 ("redirect", QString::null, QString::null, QString::null, "=", QString::null, QString::null, true)); 02745 02746 KConfig *config = KGlobal::config(); 02747 KConfigGroupSaver saver( config, "KDE URL Restrictions" ); 02748 int count = config->readNumEntry("rule_count"); 02749 QString keyFormat = QString("rule_%1"); 02750 for(int i = 1; i <= count; i++) 02751 { 02752 QString key = keyFormat.arg(i); 02753 QStringList rule = config->readListEntry(key); 02754 if (rule.count() != 8) 02755 continue; 02756 QString action = rule[0]; 02757 QString refProt = rule[1]; 02758 QString refHost = rule[2]; 02759 QString refPath = rule[3]; 02760 QString urlProt = rule[4]; 02761 QString urlHost = rule[5]; 02762 QString urlPath = rule[6]; 02763 QString strEnabled = rule[7].lower(); 02764 02765 bool bEnabled = (strEnabled == "true"); 02766 02767 if (refPath.startsWith("$HOME")) 02768 refPath.replace(0, 5, QDir::homeDirPath()); 02769 else if (refPath.startsWith("~")) 02770 refPath.replace(0, 1, QDir::homeDirPath()); 02771 if (urlPath.startsWith("$HOME")) 02772 urlPath.replace(0, 5, QDir::homeDirPath()); 02773 else if (urlPath.startsWith("~")) 02774 urlPath.replace(0, 1, QDir::homeDirPath()); 02775 02776 if (refPath.startsWith("$TMP")) 02777 refPath.replace(0, 4, KGlobal::dirs()->saveLocation("tmp")); 02778 if (urlPath.startsWith("$TMP")) 02779 urlPath.replace(0, 4, KGlobal::dirs()->saveLocation("tmp")); 02780 02781 d->urlActionRestrictions.append(new KApplicationPrivate::URLActionRule 02782 ( action, refProt, refHost, refPath, urlProt, urlHost, urlPath, bEnabled)); 02783 } 02784 } 02785 02786 void KApplication::allowURLAction(const QString &action, const KURL &_baseURL, const KURL &_destURL) 02787 { 02788 if (authorizeURLAction(action, _baseURL, _destURL)) 02789 return; 02790 02791 d->urlActionRestrictions.append(new KApplicationPrivate::URLActionRule 02792 ( action, _baseURL.protocol(), _baseURL.host(), _baseURL.path(-1), 02793 _destURL.protocol(), _destURL.host(), _destURL.path(-1), true)); 02794 } 02795 02796 bool KApplication::authorizeURLAction(const QString &action, const KURL &_baseURL, const KURL &_destURL) 02797 { 02798 if (_destURL.isEmpty()) 02799 return true; 02800 02801 bool result = false; 02802 if (d->urlActionRestrictions.isEmpty()) 02803 initUrlActionRestrictions(); 02804 02805 KURL baseURL(_baseURL); 02806 baseURL.setPath(QDir::cleanDirPath(baseURL.path())); 02807 QString baseClass = KProtocolInfo::protocolClass(baseURL.protocol()); 02808 KURL destURL(_destURL); 02809 destURL.setPath(QDir::cleanDirPath(destURL.path())); 02810 QString destClass = KProtocolInfo::protocolClass(destURL.protocol()); 02811 02812 for(KApplicationPrivate::URLActionRule *rule = d->urlActionRestrictions.first(); 02813 rule; rule = d->urlActionRestrictions.next()) 02814 { 02815 if ((result != rule->permission) && // No need to check if it doesn't make a difference 02816 (action == rule->action) && 02817 rule->baseMatch(baseURL, baseClass) && 02818 rule->destMatch(destURL, destClass, baseURL, baseClass)) 02819 { 02820 result = rule->permission; 02821 } 02822 } 02823 return result; 02824 } 02825 02826 02827 uint KApplication::keyboardModifiers() 02828 { 02829 Window root; 02830 Window child; 02831 int root_x, root_y, win_x, win_y; 02832 uint keybstate; 02833 XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, 02834 &root_x, &root_y, &win_x, &win_y, &keybstate ); 02835 return keybstate & 0x00ff; 02836 } 02837 02838 uint KApplication::mouseState() 02839 { 02840 Window root; 02841 Window child; 02842 int root_x, root_y, win_x, win_y; 02843 uint keybstate; 02844 XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, 02845 &root_x, &root_y, &win_x, &win_y, &keybstate ); 02846 return keybstate & 0xff00; 02847 } 02848 02849 void KApplication::installSigpipeHandler() 02850 { 02851 struct sigaction act; 02852 act.sa_handler = SIG_IGN; 02853 sigemptyset( &act.sa_mask ); 02854 act.sa_flags = 0; 02855 sigaction( SIGPIPE, &act, 0 ); 02856 } 02857 02858 void KApplication::sigpipeHandler(int) 02859 { 02860 int saved_errno = errno; 02861 // Using kdDebug from a signal handler is not a good idea. 02862 #ifndef NDEBUG 02863 char msg[1000]; 02864 sprintf(msg, "*** SIGPIPE *** (ignored, pid = %ld)\n", (long) getpid()); 02865 write(2, msg, strlen(msg)); 02866 #endif 02867 02868 // Do nothing. 02869 errno = saved_errno; 02870 } 02871 02872 bool KApplication::guiEnabled() 02873 { 02874 return kapp && kapp->d->guiEnabled; 02875 } 02876 02877 void KApplication::virtual_hook( int id, void* data ) 02878 { KInstance::virtual_hook( id, data ); } 02879 02880 void KSessionManaged::virtual_hook( int, void* ) 02881 { /*BASE::virtual_hook( id, data );*/ } 02882 02883 #include "kapplication.moc"
KDE Logo
This file is part of the documentation for kdecore Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 16 17:21:40 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003