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