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