kdecore Library API Documentation

kapplication.cpp

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