# kdecore Library API Documentation

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

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:01 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003