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