kapplication.cpp Source File (kdecore Library)

| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

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

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 12:46:19 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001