00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
#if 0
00029
#define KSTARTUPINFO_ALL_DEBUG
00030
#warning Extra KStartupInfo debug messages enabled.
00031
#endif
00032
00033
#include <qwidget.h>
00034
00035
#include "config.h"
00036
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00037
00038
#include <qglobal.h>
00039
#ifdef HAVE_CONFIG_H
00040
#include <config.h>
00041
#endif
00042
00043
00044
#ifndef QT_CLEAN_NAMESPACE
00045
#define QT_CLEAN_NAMESPACE
00046
#endif
00047
00048
#include "kstartupinfo.h"
00049
00050
#include <unistd.h>
00051
#include <sys/time.h>
00052
#include <stdlib.h>
00053
#include <qtimer.h>
00054
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00055
#include <netwm.h>
00056
#endif
00057
#include <kdebug.h>
00058
#include <kapplication.h>
00059
#include <signal.h>
00060
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00061
#include <kwinmodule.h>
00062
#include <kxmessages.h>
00063
#include <kwin.h>
00064
#endif
00065
00066
static const char*
const NET_STARTUP_MSG =
"_NET_STARTUP_INFO";
00067
static const char*
const NET_STARTUP_WINDOW =
"_NET_STARTUP_ID";
00068
00069
static const char*
const NET_STARTUP_ENV =
"DESKTOP_STARTUP_ID";
00070
00071
static bool auto_app_started_sending =
true;
00072
00073
static long get_num(
const QString& item_P );
00074
static unsigned long get_unum(
const QString& item_P );
00075
static QString get_str(
const QString& item_P );
00076
static QCString get_cstr(
const QString& item_P );
00077
static QStringList get_fields(
const QString& txt_P );
00078
static QString escape_str(
const QString& str_P );
00079
00080
static Atom utf8_string_atom = None;
00081
00082
class KStartupInfo::Data
00083 :
public KStartupInfoData
00084 {
00085
public:
00086 Data() {};
00087 Data(
const QString& txt_P )
00088 :
KStartupInfoData( txt_P ), age( 0 ) {};
00089
unsigned int age;
00090 };
00091
00092
struct KStartupInfoPrivate
00093 {
00094
public:
00095
QMap< KStartupInfoId, KStartupInfo::Data > startups;
00096
00097
QMap< KStartupInfoId, KStartupInfo::Data > silent_startups;
00098
00099
QMap< KStartupInfoId, KStartupInfo::Data > uninited_startups;
00100
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00101
KWinModule* wm_module;
00102
KXMessages msgs;
00103
#endif
00104
QTimer* cleanup;
00105
int flags;
00106 KStartupInfoPrivate(
int flags_P )
00107 :
00108 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00109 msgs( NET_STARTUP_MSG, NULL, false ),
00110 #endif
00111 flags( flags_P ) {}
00112 };
00113
00114 KStartupInfo::KStartupInfo(
int flags_P,
QObject* parent_P,
const char* name_P )
00115 :
QObject( parent_P, name_P ),
00116 timeout( 60 ), d( NULL )
00117 {
00118 init( flags_P );
00119 }
00120
00121 KStartupInfo::KStartupInfo(
bool clean_on_cantdetect_P,
QObject* parent_P,
const char* name_P )
00122 :
QObject( parent_P, name_P ),
00123 timeout( 60 ), d( NULL )
00124 {
00125 init( clean_on_cantdetect_P ? CleanOnCantDetect : 0 );
00126 }
00127
00128
void KStartupInfo::init(
int flags_P )
00129 {
00130
00131
if( !
KApplication::kApplication())
00132
return;
00133
if( !
KApplication::kApplication()->
getDisplay())
00134
return;
00135
00136 d =
new KStartupInfoPrivate( flags_P );
00137
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00138
if( !( d->flags & DisableKWinModule ))
00139 {
00140 d->wm_module =
new KWinModule(
this );
00141 connect( d->wm_module, SIGNAL( windowAdded( WId )), SLOT( slot_window_added( WId )));
00142 connect( d->wm_module, SIGNAL( systemTrayWindowAdded( WId )), SLOT( slot_window_added( WId )));
00143 }
00144
else
00145 d->wm_module = NULL;
00146 connect( &d->msgs, SIGNAL( gotMessage(
const QString& )), SLOT( got_message(
const QString& )));
00147
#endif
00148
d->cleanup =
new QTimer(
this );
00149 connect( d->cleanup, SIGNAL( timeout()), SLOT( startups_cleanup()));
00150 }
00151
00152 KStartupInfo::~KStartupInfo()
00153 {
00154
delete d;
00155 }
00156
00157
void KStartupInfo::got_message(
const QString& msg_P )
00158 {
00159
00160 kdDebug( 172 ) <<
"got:" << msg_P <<
endl;
00161
QString msg = msg_P.stripWhiteSpace();
00162
if( msg.startsWith(
"new:" ))
00163 got_startup_info( msg.mid( 4 ),
false );
00164
else if( msg.startsWith(
"change:" ))
00165 got_startup_info( msg.mid( 7 ),
true );
00166
else if( msg.startsWith(
"remove:" ))
00167 got_remove_startup_info( msg.mid( 7 ));
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
namespace
00177
{
00178
class DelayedWindowEvent
00179 :
public QCustomEvent
00180 {
00181
public:
00182 DelayedWindowEvent( WId w_P )
00183 :
QCustomEvent(
QEvent::User + 15 ), w( w_P ) {}
00184 Window w;
00185 };
00186 }
00187
00188
void KStartupInfo::slot_window_added( WId w_P )
00189 {
00190 kapp->postEvent(
this,
new DelayedWindowEvent( w_P ));
00191 }
00192
00193
void KStartupInfo::customEvent(
QCustomEvent* e_P )
00194 {
00195
if( e_P->type() == QEvent::User + 15 )
00196 window_added( static_cast< DelayedWindowEvent* >( e_P )->w );
00197
else
00198 QObject::customEvent( e_P );
00199 }
00200
00201
void KStartupInfo::window_added( WId w_P )
00202 {
00203
KStartupInfoId id;
00204
KStartupInfoData data;
00205
startup_t ret = check_startup_internal( w_P, &
id, &data );
00206
switch( ret )
00207 {
00208
case Match:
00209 kdDebug( 172 ) <<
"new window match" <<
endl;
00210
break;
00211
case NoMatch:
00212
break;
00213
case CantDetect:
00214
if( d->flags & CleanOnCantDetect )
00215 clean_all_noncompliant();
00216
break;
00217 }
00218 }
00219
00220
void KStartupInfo::got_startup_info(
const QString& msg_P,
bool update_P )
00221 {
00222
KStartupInfoId id( msg_P );
00223
if(
id.none())
00224
return;
00225 KStartupInfo::Data data( msg_P );
00226 new_startup_info_internal(
id, data, update_P );
00227 }
00228
00229
void KStartupInfo::new_startup_info_internal(
const KStartupInfoId& id_P,
00230 Data& data_P,
bool update_P )
00231 {
00232
if( d == NULL )
00233
return;
00234
if( id_P.
none())
00235
return;
00236
if( d->startups.contains( id_P ))
00237 {
00238 d->startups[ id_P ].update( data_P );
00239 d->startups[ id_P ].age = 0;
00240 kdDebug( 172 ) <<
"updating" <<
endl;
00241
if( d->startups[ id_P ].silent() == Data::Yes
00242 && !( d->flags & AnnounceSilenceChanges ))
00243 {
00244 d->silent_startups[ id_P ] = d->startups[ id_P ];
00245 d->startups.remove( id_P );
00246 emit
gotRemoveStartup( id_P, d->silent_startups[ id_P ] );
00247
return;
00248 }
00249 emit
gotStartupChange( id_P, d->startups[ id_P ] );
00250
return;
00251 }
00252
if( d->silent_startups.contains( id_P ))
00253 {
00254 d->silent_startups[ id_P ].update( data_P );
00255 d->silent_startups[ id_P ].age = 0;
00256 kdDebug( 172 ) <<
"updating silenced" <<
endl;
00257
if( d->silent_startups[ id_P ].silent() != Data::Yes )
00258 {
00259 d->startups[ id_P ] = d->silent_startups[ id_P ];
00260 d->silent_startups.remove( id_P );
00261 emit
gotNewStartup( id_P, d->startups[ id_P ] );
00262
return;
00263 }
00264 emit
gotStartupChange( id_P, d->startups[ id_P ] );
00265
return;
00266 }
00267
if( d->uninited_startups.contains( id_P ))
00268 {
00269 d->uninited_startups[ id_P ].update( data_P );
00270 kdDebug( 172 ) <<
"updating uninited" <<
endl;
00271
if( !update_P )
00272 {
00273 d->startups[ id_P ] = d->uninited_startups[ id_P ];
00274 d->uninited_startups.remove( id_P );
00275 emit
gotNewStartup( id_P, d->startups[ id_P ] );
00276
return;
00277 }
00278
00279
return;
00280 }
00281
if( update_P )
00282 {
00283 kdDebug( 172 ) <<
"adding uninited" <<
endl;
00284 d->uninited_startups.insert( id_P, data_P );
00285 }
00286
else if( data_P.silent() != Data::Yes || d->flags & AnnounceSilenceChanges )
00287 {
00288 kdDebug( 172 ) <<
"adding" <<
endl;
00289 d->startups.insert( id_P, data_P );
00290 emit
gotNewStartup( id_P, data_P );
00291 }
00292
else
00293 {
00294 kdDebug( 172 ) <<
"adding silent" <<
endl;
00295 d->silent_startups.insert( id_P, data_P );
00296 }
00297 d->cleanup->start( 1000 );
00298 }
00299
00300
void KStartupInfo::got_remove_startup_info(
const QString& msg_P )
00301 {
00302
KStartupInfoId id( msg_P );
00303
KStartupInfoData data( msg_P );
00304
if( data.pids().count() > 0 )
00305 {
00306
if( !
id.none())
00307 remove_startup_pids(
id, data );
00308
else
00309 remove_startup_pids( data );
00310
return;
00311 }
00312 remove_startup_info_internal(
id );
00313 }
00314
00315
void KStartupInfo::remove_startup_info_internal(
const KStartupInfoId& id_P )
00316 {
00317
if( d == NULL )
00318
return;
00319
if( d->startups.contains( id_P ))
00320 {
00321 kdDebug( 172 ) <<
"removing" <<
endl;
00322 emit
gotRemoveStartup( id_P, d->startups[ id_P ]);
00323 d->startups.remove( id_P );
00324 }
00325
else if( d->silent_startups.contains( id_P ))
00326 {
00327 kdDebug( 172 ) <<
"removing silent" <<
endl;
00328 d->silent_startups.remove( id_P );
00329 }
00330
else if( d->uninited_startups.contains( id_P ))
00331 {
00332 kdDebug( 172 ) <<
"removing uninited" <<
endl;
00333 d->uninited_startups.remove( id_P );
00334 }
00335
return;
00336 }
00337
00338
void KStartupInfo::remove_startup_pids(
const KStartupInfoData& data_P )
00339 {
00340
if( d == NULL )
00341
return;
00342
for(
QMap< KStartupInfoId, Data >::Iterator it = d->startups.begin();
00343 it != d->startups.end();
00344 ++it )
00345 {
00346
if( ( *it ).hostname() != data_P.
hostname())
00347
continue;
00348
if( !( *it ).is_pid( data_P.
pids().first()))
00349
continue;
00350 remove_startup_pids( it.key(), data_P );
00351
break;
00352 }
00353 }
00354
00355
void KStartupInfo::remove_startup_pids(
const KStartupInfoId& id_P,
00356
const KStartupInfoData& data_P )
00357 {
00358
if( d == NULL )
00359
return;
00360 kdFatal( data_P.
pids().count() == 0, 172 );
00361 Data* data = NULL;
00362
if( d->startups.contains( id_P ))
00363 data = &d->startups[ id_P ];
00364
else if( d->silent_startups.contains( id_P ))
00365 data = &d->silent_startups[ id_P ];
00366
else if( d->uninited_startups.contains( id_P ))
00367 data = &d->uninited_startups[ id_P ];
00368
else
00369
return;
00370
for(
QValueList< pid_t >::ConstIterator it2 = data_P.
pids().begin();
00371 it2 != data_P.
pids().end();
00372 ++it2 )
00373 data->remove_pid( *it2 );
00374
if( data->pids().count() == 0 )
00375 remove_startup_info_internal( id_P );
00376 }
00377
00378 bool KStartupInfo::sendStartup(
const KStartupInfoId& id_P,
const KStartupInfoData& data_P )
00379 {
00380
if( id_P.
none())
00381
return false;
00382
KXMessages msgs;
00383
QString msg = QString::fromLatin1(
"new: %1 %2" )
00384 .arg( id_P.
to_text()).arg( data_P.
to_text());
00385 msg = check_required_startup_fields( msg, data_P, qt_xscreen());
00386 kdDebug( 172 ) <<
"sending " << msg <<
endl;
00387 msgs.
broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
00388
return true;
00389 }
00390
00391 bool KStartupInfo::sendStartupX( Display* disp_P,
const KStartupInfoId& id_P,
00392
const KStartupInfoData& data_P )
00393 {
00394
if( id_P.
none())
00395
return false;
00396
QString msg = QString::fromLatin1(
"new: %1 %2" )
00397 .arg( id_P.
to_text()).arg( data_P.
to_text());
00398 msg = check_required_startup_fields( msg, data_P, DefaultScreen( disp_P ));
00399
#ifdef KSTARTUPINFO_ALL_DEBUG
00400
kdDebug( 172 ) <<
"sending " << msg <<
endl;
00401
#endif
00402
return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
00403 }
00404
00405
QString KStartupInfo::check_required_startup_fields(
const QString& msg,
const KStartupInfoData& data_P,
00406
int screen )
00407 {
00408
QString ret = msg;
00409
if( data_P.
name().isEmpty())
00410 {
00411
00412
QString name = data_P.
bin();
00413
if( name.isEmpty())
00414 name =
"UNKNOWN";
00415 ret +=
QString(
" NAME=\"%1\"" ).arg( escape_str( name ));
00416 }
00417
if( data_P.
screen() == -1 )
00418 ret +=
QString(
" SCREEN=%1" ).arg( screen );
00419
return ret;
00420 }
00421
00422 bool KStartupInfo::sendChange(
const KStartupInfoId& id_P,
const KStartupInfoData& data_P )
00423 {
00424
if( id_P.
none())
00425
return false;
00426
KXMessages msgs;
00427
QString msg = QString::fromLatin1(
"change: %1 %2" )
00428 .arg( id_P.
to_text()).arg( data_P.
to_text());
00429 kdDebug( 172 ) <<
"sending " << msg <<
endl;
00430 msgs.
broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
00431
return true;
00432 }
00433
00434 bool KStartupInfo::sendChangeX( Display* disp_P,
const KStartupInfoId& id_P,
00435
const KStartupInfoData& data_P )
00436 {
00437
if( id_P.
none())
00438
return false;
00439
QString msg = QString::fromLatin1(
"change: %1 %2" )
00440 .arg( id_P.
to_text()).arg( data_P.
to_text());
00441
#ifdef KSTARTUPINFO_ALL_DEBUG
00442
kdDebug( 172 ) <<
"sending " << msg <<
endl;
00443
#endif
00444
return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
00445 }
00446
00447 bool KStartupInfo::sendFinish(
const KStartupInfoId& id_P )
00448 {
00449
if( id_P.
none())
00450
return false;
00451
KXMessages msgs;
00452
QString msg = QString::fromLatin1(
"remove: %1" ).arg( id_P.
to_text());
00453 kdDebug( 172 ) <<
"sending " << msg <<
endl;
00454 msgs.
broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
00455
return true;
00456 }
00457
00458 bool KStartupInfo::sendFinishX( Display* disp_P,
const KStartupInfoId& id_P )
00459 {
00460
if( id_P.
none())
00461
return false;
00462
QString msg = QString::fromLatin1(
"remove: %1" ).arg( id_P.
to_text());
00463
#ifdef KSTARTUPINFO_ALL_DEBUG
00464
kdDebug( 172 ) <<
"sending " << msg <<
endl;
00465
#endif
00466
return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
00467 }
00468
00469 bool KStartupInfo::sendFinish(
const KStartupInfoId& id_P,
const KStartupInfoData& data_P )
00470 {
00471
00472
00473
KXMessages msgs;
00474
QString msg = QString::fromLatin1(
"remove: %1 %2" )
00475 .arg( id_P.
to_text()).arg( data_P.
to_text());
00476 kdDebug( 172 ) <<
"sending " << msg <<
endl;
00477 msgs.
broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
00478
return true;
00479 }
00480
00481 bool KStartupInfo::sendFinishX( Display* disp_P,
const KStartupInfoId& id_P,
00482
const KStartupInfoData& data_P )
00483 {
00484
00485
00486
QString msg = QString::fromLatin1(
"remove: %1 %2" )
00487 .arg( id_P.
to_text()).arg( data_P.
to_text());
00488
#ifdef KSTARTUPINFO_ALL_DEBUG
00489
kdDebug( 172 ) <<
"sending " << msg <<
endl;
00490
#endif
00491
return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
00492 }
00493
00494 void KStartupInfo::appStarted()
00495 {
00496
if( kapp != NULL )
00497
appStarted( kapp->startupId());
00498
else
00499
appStarted(
KStartupInfo::currentStartupIdEnv().
id());
00500 }
00501
00502 void KStartupInfo::appStarted(
const QCString& startup_id )
00503 {
00504
KStartupInfoId id;
00505
id.initId( startup_id );
00506
if(
id.none())
00507
return;
00508
if( kapp != NULL )
00509
KStartupInfo::sendFinish(
id );
00510
else if( getenv(
"DISPLAY" ) != NULL )
00511 {
00512
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00513
Display* disp = XOpenDisplay( NULL );
00514
if( disp != NULL )
00515 {
00516
KStartupInfo::sendFinishX( disp,
id );
00517 XCloseDisplay( disp );
00518 }
00519
#endif
00520
}
00521 }
00522
00523 void KStartupInfo::disableAutoAppStartedSending(
bool disable )
00524 {
00525 auto_app_started_sending = !disable;
00526 }
00527
00528 void KStartupInfo::silenceStartup(
bool silence )
00529 {
00530
KStartupInfoId id;
00531
id.initId( kapp->startupId());
00532
if(
id.none())
00533
return;
00534
KStartupInfoData data;
00535 data.
setSilent( silence ? KStartupInfoData::Yes : KStartupInfoData::No );
00536
sendChange(
id, data );
00537 }
00538
00539
void KStartupInfo::handleAutoAppStartedSending()
00540 {
00541
if( auto_app_started_sending )
00542
appStarted();
00543 }
00544
00545 void KStartupInfo::setNewStartupId(
QWidget* window,
const QCString& startup_id )
00546 {
00547
long activate =
true;
00548 kapp->setStartupId( startup_id );
00549
if( window != NULL )
00550 {
00551
if( !startup_id.isEmpty() && startup_id !=
"0" )
00552 {
00553
NETRootInfo i( qt_xdisplay(), NET::Supported );
00554
if( i.
isSupported( NET::WM2StartupId ))
00555 {
00556
KStartupInfo::setWindowStartupId( window->winId(), startup_id );
00557 activate =
false;
00558 }
00559 }
00560
if( activate )
00561
00562
00563
00564
00565
KWin::forceActiveWindow( window->winId());
00566 }
00567 KStartupInfo::handleAutoAppStartedSending();
00568 }
00569
00570 KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P,
KStartupInfoId& id_O,
00571
KStartupInfoData& data_O )
00572 {
00573
return check_startup_internal( w_P, &id_O, &data_O );
00574 }
00575
00576 KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P,
KStartupInfoId& id_O )
00577 {
00578
return check_startup_internal( w_P, &id_O, NULL );
00579 }
00580
00581 KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P,
KStartupInfoData& data_O )
00582 {
00583
return check_startup_internal( w_P, NULL, &data_O );
00584 }
00585
00586 KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P )
00587 {
00588
return check_startup_internal( w_P, NULL, NULL );
00589 }
00590
00591 KStartupInfo::startup_t KStartupInfo::check_startup_internal( WId w_P,
KStartupInfoId* id_O,
00592
KStartupInfoData* data_O )
00593 {
00594
if( d == NULL )
00595
return NoMatch;
00596
if( d->startups.count() == 0 )
00597
return NoMatch;
00598
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00599
00600
NETWinInfo info( qt_xdisplay(), w_P, qt_xrootwin(),
00601 NET::WMWindowType | NET::WMPid | NET::WMState );
00602
00603 NET::WindowType type = info.windowType( NET::NormalMask | NET::DesktopMask
00604 | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
00605 | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
00606
if( type != NET::Normal
00607 && type != NET::Override
00608 && type != NET::Unknown
00609 && type != NET::Dialog
00610 && type != NET::Utility )
00611
00612
return NoMatch;
00613
00614 Window transient_for;
00615
if( XGetTransientForHint( qt_xdisplay(), static_cast< Window >( w_P ), &transient_for )
00616 && static_cast< WId >( transient_for ) != qt_xrootwin()
00617 && transient_for != None )
00618
return NoMatch;
00619
#endif
00620
00621
00622
00623
00624
00625
00626
00627 kdDebug( 172 ) <<
"check_startup" <<
endl;
00628
QCString id =
windowStartupId( w_P );
00629
if( !
id.isNull())
00630 {
00631
if(
id.isEmpty() ||
id ==
"0" )
00632 {
00633 kdDebug( 172 ) <<
"ignore" <<
endl;
00634
return NoMatch;
00635 }
00636
return find_id(
id, id_O, data_O ) ? Match : NoMatch;
00637 }
00638
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00639
pid_t pid = info.pid();
00640
if( pid > 0 )
00641 {
00642
QCString hostname = get_window_hostname( w_P );
00643
if( !hostname.isEmpty()
00644 && find_pid( pid, hostname, id_O, data_O ))
00645
return Match;
00646
00647 }
00648 XClassHint hint;
00649
if( XGetClassHint( qt_xdisplay(), w_P, &hint ) != 0 )
00650 {
00651
QCString res_name = hint.res_name;
00652
QCString res_class = hint.res_class;
00653 XFree( hint.res_name );
00654 XFree( hint.res_class );
00655
if( find_wclass( res_name, res_class, id_O, data_O ))
00656
return Match;
00657 }
00658
#endif
00659
kdDebug( 172 ) <<
"check_startup:cantdetect" <<
endl;
00660
return CantDetect;
00661 }
00662
00663
bool KStartupInfo::find_id(
const QCString& id_P,
KStartupInfoId* id_O,
00664
KStartupInfoData* data_O )
00665 {
00666
if( d == NULL )
00667
return false;
00668 kdDebug( 172 ) <<
"find_id:" << id_P <<
endl;
00669
KStartupInfoId id;
00670
id.initId( id_P );
00671
if( d->startups.contains(
id ))
00672 {
00673
if( id_O != NULL )
00674 *id_O =
id;
00675
if( data_O != NULL )
00676 *data_O = d->startups[
id ];
00677 kdDebug( 172 ) <<
"check_startup_id:match" <<
endl;
00678
return true;
00679 }
00680
return false;
00681 }
00682
00683
bool KStartupInfo::find_pid( pid_t pid_P,
const QCString& hostname_P,
00684
KStartupInfoId* id_O,
KStartupInfoData* data_O )
00685 {
00686
if( d == NULL )
00687
return false;
00688 kdDebug( 172 ) <<
"find_pid:" << pid_P <<
endl;
00689
for(
QMap< KStartupInfoId, Data >::Iterator it = d->startups.begin();
00690 it != d->startups.end();
00691 ++it )
00692 {
00693
if( ( *it ).is_pid( pid_P ) && ( *it ).hostname() == hostname_P )
00694 {
00695
if( id_O != NULL )
00696 *id_O = it.key();
00697
if( data_O != NULL )
00698 *data_O = *it;
00699
00700 remove_startup_info_internal( it.key());
00701 kdDebug( 172 ) <<
"check_startup_pid:match" <<
endl;
00702
return true;
00703 }
00704 }
00705
return false;
00706 }
00707
00708
bool KStartupInfo::find_wclass(
QCString res_name,
QCString res_class,
00709
KStartupInfoId* id_O,
KStartupInfoData* data_O )
00710 {
00711
if( d == NULL )
00712
return false;
00713 res_name = res_name.lower();
00714 res_class = res_class.lower();
00715 kdDebug( 172 ) <<
"find_wclass:" << res_name <<
":" << res_class <<
endl;
00716
for(
QMap< KStartupInfoId, Data >::Iterator it = d->startups.begin();
00717 it != d->startups.end();
00718 ++it )
00719 {
00720
const QCString wmclass = ( *it ).findWMClass();
00721
if( wmclass.lower() == res_name || wmclass.lower() == res_class )
00722 {
00723
if( id_O != NULL )
00724 *id_O = it.key();
00725
if( data_O != NULL )
00726 *data_O = *it;
00727
00728 remove_startup_info_internal( it.key());
00729 kdDebug( 172 ) <<
"check_startup_wclass:match" <<
endl;
00730
return true;
00731 }
00732 }
00733
return false;
00734 }
00735
00736
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00737
static Atom net_startup_atom = None;
00738
00739
static QCString read_startup_id_property( WId w_P )
00740 {
00741
QCString ret;
00742
unsigned char *name_ret;
00743 Atom type_ret;
00744
int format_ret;
00745
unsigned long nitems_ret = 0, after_ret = 0;
00746
if( XGetWindowProperty( qt_xdisplay(), w_P, net_startup_atom, 0l, 4096,
00747 False, utf8_string_atom, &type_ret, &format_ret, &nitems_ret, &after_ret, &name_ret )
00748 == Success )
00749 {
00750
if( type_ret == utf8_string_atom && format_ret == 8 && name_ret != NULL )
00751 ret = reinterpret_cast< char* >( name_ret );
00752
if ( name_ret != NULL )
00753 XFree( name_ret );
00754 }
00755
return ret;
00756 }
00757
00758
#endif
00759
00760 QCString KStartupInfo::windowStartupId( WId w_P )
00761 {
00762
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00763
if( net_startup_atom == None )
00764 net_startup_atom = XInternAtom( qt_xdisplay(), NET_STARTUP_WINDOW, False );
00765
if( utf8_string_atom == None )
00766 utf8_string_atom = XInternAtom( qt_xdisplay(),
"UTF8_STRING", False );
00767
QCString ret = read_startup_id_property( w_P );
00768
if( ret.isEmpty())
00769 {
00770 XWMHints* hints = XGetWMHints( qt_xdisplay(), w_P );
00771
if( hints && ( hints->flags & WindowGroupHint ) != 0 )
00772 ret = read_startup_id_property( hints->window_group );
00773
if( hints )
00774 XFree( hints );
00775 }
00776
return ret;
00777
#else
00778
return QCString();
00779
#endif
00780
}
00781
00782 void KStartupInfo::setWindowStartupId( WId w_P,
const QCString& id_P )
00783 {
00784
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00785
if( id_P.isNull())
00786
return;
00787
if( net_startup_atom == None )
00788 net_startup_atom = XInternAtom( qt_xdisplay(), NET_STARTUP_WINDOW, False );
00789
if( utf8_string_atom == None )
00790 utf8_string_atom = XInternAtom( qt_xdisplay(),
"UTF8_STRING", False );
00791 XChangeProperty( qt_xdisplay(), w_P, net_startup_atom, utf8_string_atom, 8,
00792 PropModeReplace, reinterpret_cast< unsigned char* >( id_P.data()), id_P.length());
00793
#endif
00794
}
00795
00796
QCString KStartupInfo::get_window_hostname( WId w_P )
00797 {
00798
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00799
XTextProperty tp;
00800
char** hh;
00801
int cnt;
00802
if( XGetWMClientMachine( qt_xdisplay(), w_P, &tp ) != 0
00803 && XTextPropertyToStringList( &tp, &hh, &cnt ) != 0 )
00804 {
00805
if( cnt == 1 )
00806 {
00807
QCString hostname = hh[ 0 ];
00808 XFreeStringList( hh );
00809
return hostname;
00810 }
00811 XFreeStringList( hh );
00812 }
00813
#endif
00814
00815
return QCString();
00816 }
00817
00818 void KStartupInfo::setTimeout(
unsigned int secs_P )
00819 {
00820 timeout = secs_P;
00821
00822 QTimer::singleShot( 0,
this, SLOT( startups_cleanup_no_age()));
00823 }
00824
00825
void KStartupInfo::startups_cleanup_no_age()
00826 {
00827 startups_cleanup_internal(
false );
00828 }
00829
00830
void KStartupInfo::startups_cleanup()
00831 {
00832
if( d == NULL )
00833
return;
00834
if( d->startups.count() == 0 && d->silent_startups.count() == 0
00835 && d->uninited_startups.count() == 0 )
00836 {
00837 d->cleanup->stop();
00838
return;
00839 }
00840 startups_cleanup_internal(
true );
00841 }
00842
00843
void KStartupInfo::startups_cleanup_internal(
bool age_P )
00844 {
00845
if( d == NULL )
00846
return;
00847
for(
QMap< KStartupInfoId, Data >::Iterator it = d->startups.begin();
00848 it != d->startups.end();
00849 )
00850 {
00851
if( age_P )
00852 ( *it ).age++;
00853
unsigned int tout = timeout;
00854
if( ( *it ).silent() == Data::Yes )
00855 tout *= 20;
00856
if( ( *it ).age >= tout )
00857 {
00858
const KStartupInfoId&
key = it.key();
00859 ++it;
00860 kdDebug( 172 ) <<
"entry timeout:" <<
key.id() <<
endl;
00861 remove_startup_info_internal( key );
00862 }
00863
else
00864 ++it;
00865 }
00866
for(
QMap< KStartupInfoId, Data >::Iterator it = d->silent_startups.begin();
00867 it != d->silent_startups.end();
00868 )
00869 {
00870
if( age_P )
00871 ( *it ).age++;
00872
unsigned int tout = timeout;
00873
if( ( *it ).silent() == Data::Yes )
00874 tout *= 20;
00875
if( ( *it ).age >= tout )
00876 {
00877
const KStartupInfoId&
key = it.key();
00878 ++it;
00879 kdDebug( 172 ) <<
"entry timeout:" <<
key.id() <<
endl;
00880 remove_startup_info_internal( key );
00881 }
00882
else
00883 ++it;
00884 }
00885
for(
QMap< KStartupInfoId, Data >::Iterator it = d->uninited_startups.begin();
00886 it != d->uninited_startups.end();
00887 )
00888 {
00889
if( age_P )
00890 ( *it ).age++;
00891
unsigned int tout = timeout;
00892
if( ( *it ).silent() == Data::Yes )
00893 tout *= 20;
00894
if( ( *it ).age >= tout )
00895 {
00896
const KStartupInfoId&
key = it.key();
00897 ++it;
00898 kdDebug( 172 ) <<
"entry timeout:" <<
key.id() <<
endl;
00899 remove_startup_info_internal( key );
00900 }
00901
else
00902 ++it;
00903 }
00904 }
00905
00906
void KStartupInfo::clean_all_noncompliant()
00907 {
00908
if( d == NULL )
00909
return;
00910
for(
QMap< KStartupInfoId, Data >::Iterator it = d->startups.begin();
00911 it != d->startups.end();
00912 )
00913 {
00914
if( ( *it ).WMClass() !=
"0" )
00915 {
00916 ++it;
00917
continue;
00918 }
00919
const KStartupInfoId&
key = it.key();
00920 ++it;
00921 kdDebug( 172 ) <<
"entry cleaning:" <<
key.id() <<
endl;
00922 remove_startup_info_internal( key );
00923 }
00924 }
00925
00926 QCString KStartupInfo::createNewStartupId()
00927 {
00928
00929
00930
struct timeval tm;
00931 gettimeofday( &tm, NULL );
00932
char hostname[ 256 ];
00933 hostname[ 0 ] =
'\0';
00934
if (!gethostname( hostname, 255 ))
00935 hostname[
sizeof(hostname)-1] =
'\0';
00936
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00937
extern Time qt_x_user_time;
00938
#else
00939
long qt_x_user_time = 0;
00940
#endif
00941
QCString id =
QString(
"%1;%2;%3;%4_TIME%5" ).arg( hostname ).arg( tm.tv_sec )
00942 .arg( tm.tv_usec ).arg( getpid()).arg( qt_x_user_time ).utf8();
00943 kdDebug( 172 ) <<
"creating: " <<
id <<
":" << qAppName() <<
endl;
00944
return id;
00945 }
00946
00947
00948
struct KStartupInfoIdPrivate
00949 {
00950 KStartupInfoIdPrivate() : id(
"" ) {};
00951
QCString id;
00952 };
00953
00954 const QCString&
KStartupInfoId::id()
const
00955
{
00956
return d->id;
00957 }
00958
00959
00960
QString KStartupInfoId::to_text()
const
00961
{
00962
return QString::fromLatin1(
" ID=\"%1\" " ).arg( escape_str(
id()));
00963 }
00964
00965
KStartupInfoId::KStartupInfoId(
const QString& txt_P )
00966 {
00967 d =
new KStartupInfoIdPrivate;
00968
QStringList items = get_fields( txt_P );
00969
const QString id_str = QString::fromLatin1(
"ID=" );
00970
for( QStringList::Iterator it = items.begin();
00971 it != items.end();
00972 ++it )
00973 {
00974
if( ( *it ).startsWith( id_str ))
00975 d->id = get_cstr( *it );
00976 }
00977 }
00978
00979 void KStartupInfoId::initId(
const QCString& id_P )
00980 {
00981
if( !id_P.isEmpty())
00982 {
00983 d->id = id_P;
00984
#ifdef KSTARTUPINFO_ALL_DEBUG
00985
kdDebug( 172 ) <<
"using: " << d->id <<
endl;
00986
#endif
00987
return;
00988 }
00989
const char* startup_env = getenv( NET_STARTUP_ENV );
00990
if( startup_env != NULL && *startup_env !=
'\0' )
00991 {
00992 d->id = startup_env;
00993
#ifdef KSTARTUPINFO_ALL_DEBUG
00994
kdDebug( 172 ) <<
"reusing: " << d->id <<
endl;
00995
#endif
00996
return;
00997 }
00998 d->id =
KStartupInfo::createNewStartupId();
00999 }
01000
01001 bool KStartupInfoId::setupStartupEnv()
const
01002
{
01003
if(
id().isEmpty())
01004 {
01005 unsetenv( NET_STARTUP_ENV );
01006
return false;
01007 }
01008
return setenv( NET_STARTUP_ENV,
id(),
true ) == 0;
01009 }
01010
01011 KStartupInfoId KStartupInfo::currentStartupIdEnv()
01012 {
01013
const char* startup_env = getenv( NET_STARTUP_ENV );
01014
KStartupInfoId id;
01015
if( startup_env != NULL && *startup_env !=
'\0' )
01016
id.d->id = startup_env;
01017
else
01018
id.d->id =
"0";
01019
return id;
01020 }
01021
01022 void KStartupInfo::resetStartupEnv()
01023 {
01024 unsetenv( NET_STARTUP_ENV );
01025 }
01026
01027 KStartupInfoId::KStartupInfoId()
01028 {
01029 d =
new KStartupInfoIdPrivate;
01030 }
01031
01032 KStartupInfoId::~KStartupInfoId()
01033 {
01034
delete d;
01035 }
01036
01037 KStartupInfoId::KStartupInfoId(
const KStartupInfoId& id_P )
01038 {
01039 d =
new KStartupInfoIdPrivate( *id_P.
d );
01040 }
01041
01042
KStartupInfoId& KStartupInfoId::operator=(
const KStartupInfoId& id_P )
01043 {
01044
if( &id_P ==
this )
01045
return *
this;
01046
delete d;
01047 d =
new KStartupInfoIdPrivate( *id_P.
d );
01048
return *
this;
01049 }
01050
01051 bool KStartupInfoId::operator==(
const KStartupInfoId& id_P )
const
01052
{
01053
return id() == id_P.
id();
01054 }
01055
01056 bool KStartupInfoId::operator!=(
const KStartupInfoId& id_P )
const
01057
{
01058
return !(*
this == id_P );
01059 }
01060
01061
01062
bool KStartupInfoId::operator<(
const KStartupInfoId& id_P )
const
01063
{
01064
return id() < id_P.
id();
01065 }
01066
01067 bool KStartupInfoId::none()
const
01068
{
01069
return d->id.isEmpty() || d->id ==
"0";
01070 }
01071
01072 unsigned long KStartupInfoId::timestamp()
const
01073
{
01074
if(
none())
01075
return 0;
01076
int pos = d->id.findRev(
"_TIME" );
01077
if( pos >= 0 )
01078 {
01079
bool ok;
01080
long time = d->id.mid( pos + 5 ).toLong( &ok );
01081
if( ok )
01082
return time;
01083 }
01084
01085
01086
01087
01088
int pos1 = d->id.findRev(
'/' );
01089
if( pos1 > 0 )
01090 {
01091
int pos2 = d->id.findRev(
'/', pos1 - 1 );
01092
if( pos2 >= 0 )
01093 {
01094
bool ok;
01095
long time = d->id.mid( pos2 + 1, pos1 - pos2 - 1 ).toLong( &ok );
01096
if( ok )
01097
return time;
01098 }
01099 }
01100
01101
return 0;
01102 }
01103
01104
struct KStartupInfoDataPrivate
01105 {
01106 KStartupInfoDataPrivate() : desktop( 0 ), wmclass(
"" ), hostname(
"" ),
01107 silent(
KStartupInfoData::Unknown ), timestamp( -1U ), screen( -1 ) {};
01108
QString bin;
01109
QString name;
01110
QString description;
01111
QString icon;
01112
int desktop;
01113
QValueList< pid_t > pids;
01114
QCString wmclass;
01115
QCString hostname;
01116 KStartupInfoData::TriState silent;
01117
unsigned long timestamp;
01118
int screen;
01119 };
01120
01121
QString KStartupInfoData::to_text()
const
01122
{
01123
QString ret =
"";
01124
if( !d->bin.isEmpty())
01125 ret += QString::fromLatin1(
" BIN=\"%1\"" ).arg( escape_str( d->bin ));
01126
if( !d->name.isEmpty())
01127 ret += QString::fromLatin1(
" NAME=\"%1\"" ).arg( escape_str( d->name ));
01128
if( !d->description.isEmpty())
01129 ret += QString::fromLatin1(
" DESCRIPTION=\"%1\"" ).arg( escape_str( d->description ));
01130
if( !d->icon.isEmpty())
01131 ret += QString::fromLatin1(
" ICON=%1" ).arg( d->icon );
01132
if( d->desktop != 0 )
01133 ret += QString::fromLatin1(
" DESKTOP=%1" )
01134 .arg( d->desktop == NET::OnAllDesktops ? NET::OnAllDesktops : d->desktop - 1 );
01135
if( !d->wmclass.isEmpty())
01136 ret += QString::fromLatin1(
" WMCLASS=%1" ).arg( d->wmclass );
01137
if( !d->hostname.isEmpty())
01138 ret += QString::fromLatin1(
" HOSTNAME=%1" ).arg( d->hostname );
01139
for(
QValueList< pid_t >::ConstIterator it = d->pids.begin();
01140 it != d->pids.end();
01141 ++it )
01142 ret += QString::fromLatin1(
" PID=%1" ).arg( *it );
01143
if( d->silent != Unknown )
01144 ret += QString::fromLatin1(
" SILENT=%1" ).arg( d->silent == Yes ? 1 : 0 );
01145
if( d->timestamp != -1U )
01146 ret += QString::fromLatin1(
" TIMESTAMP=%1" ).arg( d->timestamp );
01147
if( d->screen != -1 )
01148 ret += QString::fromLatin1(
" SCREEN=%1" ).arg( d->screen );
01149
return ret;
01150 }
01151
01152
KStartupInfoData::KStartupInfoData(
const QString& txt_P )
01153 {
01154 d =
new KStartupInfoDataPrivate;
01155
QStringList items = get_fields( txt_P );
01156
const QString bin_str = QString::fromLatin1(
"BIN=" );
01157
const QString name_str = QString::fromLatin1(
"NAME=" );
01158
const QString description_str = QString::fromLatin1(
"DESCRIPTION=" );
01159
const QString icon_str = QString::fromLatin1(
"ICON=" );
01160
const QString desktop_str = QString::fromLatin1(
"DESKTOP=" );
01161
const QString wmclass_str = QString::fromLatin1(
"WMCLASS=" );
01162
const QString hostname_str = QString::fromLatin1(
"HOSTNAME=" );
01163
const QString pid_str = QString::fromLatin1(
"PID=" );
01164
const QString silent_str = QString::fromLatin1(
"SILENT=" );
01165
const QString timestamp_str = QString::fromLatin1(
"TIMESTAMP=" );
01166
const QString screen_str = QString::fromLatin1(
"SCREEN=" );
01167
for( QStringList::Iterator it = items.begin();
01168 it != items.end();
01169 ++it )
01170 {
01171
if( ( *it ).startsWith( bin_str ))
01172 d->bin = get_str( *it );
01173
else if( ( *it ).startsWith( name_str ))
01174 d->name = get_str( *it );
01175
else if( ( *it ).startsWith( description_str ))
01176 d->description = get_str( *it );
01177
else if( ( *it ).startsWith( icon_str ))
01178 d->icon = get_str( *it );
01179
else if( ( *it ).startsWith( desktop_str ))
01180 {
01181 d->desktop = get_num( *it );
01182
if( d->desktop != NET::OnAllDesktops )
01183 ++d->desktop;
01184 }
01185
else if( ( *it ).startsWith( wmclass_str ))
01186 d->wmclass = get_cstr( *it );
01187
else if( ( *it ).startsWith( hostname_str ))
01188 d->hostname = get_cstr( *it );
01189
else if( ( *it ).startsWith( pid_str ))
01190
addPid( get_num( *it ));
01191
else if( ( *it ).startsWith( silent_str ))
01192 d->silent = get_num( *it ) != 0 ? Yes : No;
01193
else if( ( *it ).startsWith( timestamp_str ))
01194 d->timestamp = get_unum( *it );
01195
else if( ( *it ).startsWith( screen_str ))
01196 d->screen = get_num( *it );
01197 }
01198 }
01199
01200 KStartupInfoData::KStartupInfoData(
const KStartupInfoData& data )
01201 {
01202 d =
new KStartupInfoDataPrivate( *data.
d );
01203 }
01204
01205
KStartupInfoData& KStartupInfoData::operator=(
const KStartupInfoData& data )
01206 {
01207
if( &data ==
this )
01208
return *
this;
01209
delete d;
01210 d =
new KStartupInfoDataPrivate( *data.
d );
01211
return *
this;
01212 }
01213
01214 void KStartupInfoData::update(
const KStartupInfoData& data_P )
01215 {
01216
if( !data_P.
bin().isEmpty())
01217 d->bin = data_P.
bin();
01218
if( !data_P.
name().isEmpty() &&
name().isEmpty())
01219 d->name = data_P.
name();
01220
if( !data_P.
description().isEmpty() &&
description().isEmpty())
01221 d->description = data_P.
description();
01222
if( !data_P.
icon().isEmpty() &&
icon().isEmpty())
01223 d->icon = data_P.
icon();
01224
if( data_P.
desktop() != 0 &&
desktop() == 0 )
01225 d->desktop = data_P.
desktop();
01226
if( !data_P.
d->wmclass.isEmpty())
01227 d->wmclass = data_P.
d->wmclass;
01228
if( !data_P.
d->hostname.isEmpty())
01229 d->hostname = data_P.
d->hostname;
01230
for(
QValueList< pid_t >::ConstIterator it = data_P.
d->pids.begin();
01231 it != data_P.
d->pids.end();
01232 ++it )
01233
addPid( *it );
01234
if( data_P.
silent() != Unknown )
01235 d->silent = data_P.
silent();
01236
if( data_P.
timestamp() != -1U &&
timestamp() == -1U )
01237 d->timestamp = data_P.
timestamp();
01238
if( data_P.
screen() != -1 )
01239 d->screen = data_P.
screen();
01240 }
01241
01242 KStartupInfoData::KStartupInfoData()
01243 {
01244 d =
new KStartupInfoDataPrivate;
01245 }
01246
01247 KStartupInfoData::~KStartupInfoData()
01248 {
01249
delete d;
01250 }
01251
01252 void KStartupInfoData::setBin(
const QString& bin_P )
01253 {
01254 d->bin = bin_P;
01255 }
01256
01257 const QString&
KStartupInfoData::bin()
const
01258
{
01259
return d->bin;
01260 }
01261
01262 void KStartupInfoData::setName(
const QString& name_P )
01263 {
01264 d->name = name_P;
01265 }
01266
01267 const QString&
KStartupInfoData::name()
const
01268
{
01269
return d->name;
01270 }
01271
01272 const QString&
KStartupInfoData::findName()
const
01273
{
01274
if( !
name().isEmpty())
01275
return name();
01276
return bin();
01277 }
01278
01279 void KStartupInfoData::setDescription(
const QString& desc_P )
01280 {
01281 d->description = desc_P;
01282 }
01283
01284 const QString&
KStartupInfoData::description()
const
01285
{
01286
return d->description;
01287 }
01288
01289 const QString&
KStartupInfoData::findDescription()
const
01290
{
01291
if( !
description().isEmpty())
01292
return description();
01293
return name();
01294 }
01295
01296 void KStartupInfoData::setIcon(
const QString& icon_P )
01297 {
01298 d->icon = icon_P;
01299 }
01300
01301 const QString&
KStartupInfoData::findIcon()
const
01302
{
01303
if( !
icon().isEmpty())
01304
return icon();
01305
return bin();
01306 }
01307
01308 const QString&
KStartupInfoData::icon()
const
01309
{
01310
return d->icon;
01311 }
01312
01313 void KStartupInfoData::setDesktop(
int desktop_P )
01314 {
01315 d->desktop = desktop_P;
01316 }
01317
01318 int KStartupInfoData::desktop()
const
01319
{
01320
return d->desktop;
01321 }
01322
01323 void KStartupInfoData::setWMClass(
const QCString& wmclass_P )
01324 {
01325 d->wmclass = wmclass_P;
01326 }
01327
01328 const QCString KStartupInfoData::findWMClass()
const
01329
{
01330
if( !
WMClass().isEmpty() &&
WMClass() !=
"0" )
01331
return WMClass();
01332
return bin().utf8();
01333 }
01334
01335 const QCString&
KStartupInfoData::WMClass()
const
01336
{
01337
return d->wmclass;
01338 }
01339
01340 void KStartupInfoData::setHostname(
const QCString& hostname_P )
01341 {
01342
if( !hostname_P.isNull())
01343 d->hostname = hostname_P;
01344
else
01345 {
01346
char tmp[ 256 ];
01347 tmp[ 0 ] =
'\0';
01348
if (!gethostname( tmp, 255 ))
01349 tmp[
sizeof(tmp)-1] =
'\0';
01350 d->hostname = tmp;
01351 }
01352 }
01353
01354 const QCString&
KStartupInfoData::hostname()
const
01355
{
01356
return d->hostname;
01357 }
01358
01359 void KStartupInfoData::addPid( pid_t pid_P )
01360 {
01361
if( !d->pids.contains( pid_P ))
01362 d->pids.append( pid_P );
01363 }
01364
01365
void KStartupInfoData::remove_pid( pid_t pid_P )
01366 {
01367 d->pids.remove( pid_P );
01368 }
01369
01370 const QValueList< pid_t >&
KStartupInfoData::pids()
const
01371
{
01372
return d->pids;
01373 }
01374
01375 bool KStartupInfoData::is_pid( pid_t pid_P )
const
01376
{
01377
return d->pids.contains( pid_P );
01378 }
01379
01380 void KStartupInfoData::setSilent( TriState state_P )
01381 {
01382 d->silent = state_P;
01383 }
01384
01385 KStartupInfoData::TriState
KStartupInfoData::silent()
const
01386
{
01387
return d->silent;
01388 }
01389
01390 void KStartupInfoData::setTimestamp(
unsigned long time )
01391 {
01392 d->timestamp = time;
01393 }
01394
01395 unsigned long KStartupInfoData::timestamp()
const
01396
{
01397
return d->timestamp;
01398 }
01399
01400 void KStartupInfoData::setScreen(
int screen )
01401 {
01402 d->screen = screen;
01403 }
01404
01405 int KStartupInfoData::screen()
const
01406
{
01407
return d->screen;
01408 }
01409
01410
static
01411
long get_num(
const QString& item_P )
01412 {
01413
unsigned int pos = item_P.find(
'=' );
01414
return item_P.mid( pos + 1 ).toLong();
01415 }
01416
01417
static
01418
unsigned long get_unum(
const QString& item_P )
01419 {
01420
unsigned int pos = item_P.find(
'=' );
01421
return item_P.mid( pos + 1 ).toULong();
01422 }
01423
01424
static
01425
QString get_str(
const QString& item_P )
01426 {
01427
unsigned int pos = item_P.find(
'=' );
01428
if( item_P.length() > pos + 2 && item_P[ pos + 1 ] ==
'\"' )
01429 {
01430
int pos2 = item_P.left( pos + 2 ).find(
'\"' );
01431
if( pos2 < 0 )
01432
return QString::null;
01433
return item_P.mid( pos + 2, pos2 - 2 - pos );
01434 }
01435
return item_P.mid( pos + 1 );
01436 }
01437
01438
static
01439
QCString get_cstr(
const QString& item_P )
01440 {
01441
return get_str( item_P ).utf8();
01442 }
01443
01444
static
01445
QStringList get_fields(
const QString& txt_P )
01446 {
01447
QString txt = txt_P.simplifyWhiteSpace();
01448
QStringList ret;
01449
QString item =
"";
01450
bool in =
false;
01451
bool escape =
false;
01452
for(
unsigned int pos = 0;
01453 pos < txt.length();
01454 ++pos )
01455 {
01456
if( escape )
01457 {
01458 item += txt[ pos ];
01459 escape =
false;
01460 }
01461
else if( txt[ pos ] ==
'\\' )
01462 escape =
true;
01463
else if( txt[ pos ] ==
'\"' )
01464 in = !in;
01465
else if( txt[ pos ] ==
' ' && !in )
01466 {
01467 ret.append( item );
01468 item =
"";
01469 }
01470
else
01471 item += txt[ pos ];
01472 }
01473 ret.append( item );
01474
return ret;
01475 }
01476
01477
static QString escape_str(
const QString& str_P )
01478 {
01479
QString ret =
"";
01480
for(
unsigned int pos = 0;
01481 pos < str_P.length();
01482 ++pos )
01483 {
01484
if( str_P[ pos ] ==
'\\'
01485 || str_P[ pos ] ==
'"' )
01486 ret +=
'\\';
01487 ret += str_P[ pos ];
01488 }
01489
return ret;
01490 }
01491
01492
#include "kstartupinfo.moc"
01493
#endif