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