kdecore Library API Documentation

kapplication.cpp

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