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