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