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
#ifdef Q_WS_X11
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
#ifdef Q_WS_X11
00055
#include <netwm.h>
00056
#endif
00057
#include <kdebug.h>
00058
#include <kapplication.h>
00059
#include <signal.h>
00060
#ifdef Q_WS_X11
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
#ifdef Q_WS_X11
00101
KWinModule* wm_module;
00102
KXMessages msgs;
00103
#endif
00104
QTimer* cleanup;
00105
int flags;
00106 KStartupInfoPrivate(
int flags_P )
00107 :
00108 #ifdef Q_WS_X11
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
#ifdef Q_WS_X11
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
#ifdef Q_WS_X11
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
00599
00600
00601
00602
00603
00604
00605 kdDebug( 172 ) <<
"check_startup" <<
endl;
00606
QCString id = windowStartupId( w_P );
00607
if( !
id.isNull())
00608 {
00609
if(
id.isEmpty() ||
id ==
"0" )
00610 {
00611 kdDebug( 172 ) <<
"ignore" <<
endl;
00612
return NoMatch;
00613 }
00614
return find_id(
id, id_O, data_O ) ? Match : NoMatch;
00615 }
00616
#ifdef Q_WS_X11
00617
NETWinInfo info( qt_xdisplay(), w_P, qt_xrootwin(),
00618 NET::WMWindowType | NET::WMPid | NET::WMState );
00619 pid_t pid = info.
pid();
00620
if( pid > 0 )
00621 {
00622
QCString hostname = get_window_hostname( w_P );
00623
if( !hostname.
isEmpty()
00624 && find_pid( pid, hostname, id_O, data_O ))
00625
return Match;
00626
00627 }
00628 XClassHint hint;
00629
if( XGetClassHint( qt_xdisplay(), w_P, &hint ) != 0 )
00630 {
00631
QCString res_name = hint.res_name;
00632
QCString res_class = hint.res_class;
00633 XFree( hint.res_name );
00634 XFree( hint.res_class );
00635
if( find_wclass( res_name, res_class, id_O, data_O ))
00636
return Match;
00637 }
00638
00639
NET::WindowType type = info.
windowType( NET::NormalMask | NET::DesktopMask
00640 | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
00641 | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
00642
if( type != NET::Normal
00643 && type != NET::Override
00644 && type != NET::Unknown
00645 && type != NET::Dialog
00646 && type !=
NET::Utility )
00647
00648
return NoMatch;
00649
00650 Window transient_for;
00651
if( XGetTransientForHint( qt_xdisplay(), static_cast< Window >( w_P ), &transient_for )
00652 && static_cast< WId >( transient_for ) != qt_xrootwin()
00653 && transient_for != None )
00654
return NoMatch;
00655
#endif
00656
kdDebug( 172 ) <<
"check_startup:cantdetect" <<
endl;
00657
return CantDetect;
00658 }
00659
00660
bool KStartupInfo::find_id(
const QCString& id_P,
KStartupInfoId* id_O,
00661
KStartupInfoData* data_O )
00662 {
00663
if( d == NULL )
00664
return false;
00665 kdDebug( 172 ) <<
"find_id:" << id_P <<
endl;
00666
KStartupInfoId id;
00667
id.initId( id_P );
00668
if( d->startups.contains(
id ))
00669 {
00670
if( id_O != NULL )
00671 *id_O =
id;
00672
if( data_O != NULL )
00673 *data_O = d->startups[
id ];
00674 kdDebug( 172 ) <<
"check_startup_id:match" <<
endl;
00675
return true;
00676 }
00677
return false;
00678 }
00679
00680
bool KStartupInfo::find_pid( pid_t pid_P,
const QCString& hostname_P,
00681
KStartupInfoId* id_O,
KStartupInfoData* data_O )
00682 {
00683
if( d == NULL )
00684
return false;
00685 kdDebug( 172 ) <<
"find_pid:" << pid_P <<
endl;
00686
for(
QMap< KStartupInfoId, Data >::Iterator it = d->startups.begin();
00687 it != d->startups.end();
00688 ++it )
00689 {
00690
if( ( *it ).is_pid( pid_P ) && ( *it ).hostname() == hostname_P )
00691 {
00692
if( id_O != NULL )
00693 *id_O = it.key();
00694
if( data_O != NULL )
00695 *data_O = *it;
00696
00697 remove_startup_info_internal( it.key());
00698 kdDebug( 172 ) <<
"check_startup_pid:match" <<
endl;
00699
return true;
00700 }
00701 }
00702
return false;
00703 }
00704
00705
bool KStartupInfo::find_wclass(
QCString res_name,
QCString res_class,
00706
KStartupInfoId* id_O,
KStartupInfoData* data_O )
00707 {
00708
if( d == NULL )
00709
return false;
00710 res_name = res_name.
lower();
00711 res_class = res_class.
lower();
00712 kdDebug( 172 ) <<
"find_wclass:" << res_name <<
":" << res_class <<
endl;
00713
for(
QMap< KStartupInfoId, Data >::Iterator it = d->startups.begin();
00714 it != d->startups.end();
00715 ++it )
00716 {
00717
const QCString wmclass = ( *it ).findWMClass();
00718
if( wmclass.
lower() == res_name || wmclass.
lower() == res_class )
00719 {
00720
if( id_O != NULL )
00721 *id_O = it.key();
00722
if( data_O != NULL )
00723 *data_O = *it;
00724
00725 remove_startup_info_internal( it.key());
00726 kdDebug( 172 ) <<
"check_startup_wclass:match" <<
endl;
00727
return true;
00728 }
00729 }
00730
return false;
00731 }
00732
00733
#ifdef Q_WS_X11
00734
static Atom net_startup_atom = None;
00735
00736
static QCString read_startup_id_property( WId w_P )
00737 {
00738
QCString ret;
00739
unsigned char *name_ret;
00740 Atom type_ret;
00741
int format_ret;
00742
unsigned long nitems_ret = 0, after_ret = 0;
00743
if( XGetWindowProperty( qt_xdisplay(), w_P, net_startup_atom, 0l, 4096,
00744 False, utf8_string_atom, &type_ret, &format_ret, &nitems_ret, &after_ret, &name_ret )
00745 == Success )
00746 {
00747
if( type_ret == utf8_string_atom && format_ret == 8 && name_ret != NULL )
00748 ret = reinterpret_cast< char* >( name_ret );
00749
if ( name_ret != NULL )
00750 XFree( name_ret );
00751 }
00752
return ret;
00753 }
00754
00755
#endif
00756
00757 QCString KStartupInfo::windowStartupId( WId w_P )
00758 {
00759
#ifdef Q_WS_X11
00760
if( net_startup_atom == None )
00761 net_startup_atom = XInternAtom( qt_xdisplay(), NET_STARTUP_WINDOW, False );
00762
if( utf8_string_atom == None )
00763 utf8_string_atom = XInternAtom( qt_xdisplay(),
"UTF8_STRING", False );
00764
QCString ret = read_startup_id_property( w_P );
00765
if( ret.
isEmpty())
00766 {
00767 XWMHints* hints = XGetWMHints( qt_xdisplay(), w_P );
00768
if( hints && ( hints->flags & WindowGroupHint ) != 0 )
00769 ret = read_startup_id_property( hints->window_group );
00770
if( hints )
00771 XFree( hints );
00772 }
00773
return ret;
00774
#else
00775
return QCString();
00776
#endif
00777
}
00778
00779 void KStartupInfo::setWindowStartupId( WId w_P,
const QCString& id_P )
00780 {
00781
#ifdef Q_WS_X11
00782
if( id_P.
isNull())
00783
return;
00784
if( net_startup_atom == None )
00785 net_startup_atom = XInternAtom( qt_xdisplay(), NET_STARTUP_WINDOW, False );
00786
if( utf8_string_atom == None )
00787 utf8_string_atom = XInternAtom( qt_xdisplay(),
"UTF8_STRING", False );
00788 XChangeProperty( qt_xdisplay(), w_P, net_startup_atom, utf8_string_atom, 8,
00789 PropModeReplace, reinterpret_cast< unsigned char* >( id_P.data()), id_P.
length());
00790
#endif
00791
}
00792
00793
QCString KStartupInfo::get_window_hostname( WId w_P )
00794 {
00795
#ifdef Q_WS_X11
00796
XTextProperty tp;
00797
char** hh;
00798
int cnt;
00799
if( XGetWMClientMachine( qt_xdisplay(), w_P, &tp ) != 0
00800 && XTextPropertyToStringList( &tp, &hh, &cnt ) != 0 )
00801 {
00802
if( cnt == 1 )
00803 {
00804
QCString hostname = hh[ 0 ];
00805 XFreeStringList( hh );
00806
return hostname;
00807 }
00808 XFreeStringList( hh );
00809 }
00810
#endif
00811
00812
return QCString();
00813 }
00814
00815 void KStartupInfo::setTimeout(
unsigned int secs_P )
00816 {
00817 timeout = secs_P;
00818
00819 QTimer::singleShot( 0,
this, SLOT( startups_cleanup_no_age()));
00820 }
00821
00822
void KStartupInfo::startups_cleanup_no_age()
00823 {
00824 startups_cleanup_internal(
false );
00825 }
00826
00827
void KStartupInfo::startups_cleanup()
00828 {
00829
if( d == NULL )
00830
return;
00831
if( d->startups.count() == 0 && d->silent_startups.count() == 0
00832 && d->uninited_startups.count() == 0 )
00833 {
00834 d->cleanup->stop();
00835
return;
00836 }
00837 startups_cleanup_internal(
true );
00838 }
00839
00840
void KStartupInfo::startups_cleanup_internal(
bool age_P )
00841 {
00842
if( d == NULL )
00843
return;
00844
for(
QMap< KStartupInfoId, Data >::Iterator it = d->startups.begin();
00845 it != d->startups.end();
00846 )
00847 {
00848
if( age_P )
00849 ( *it ).age++;
00850
unsigned int tout = timeout;
00851
if( ( *it ).silent() == Data::Yes )
00852 tout *= 20;
00853
if( ( *it ).age >= tout )
00854 {
00855
const KStartupInfoId&
key = it.key();
00856 ++it;
00857 kdDebug( 172 ) <<
"entry timeout:" <<
key.id() <<
endl;
00858 remove_startup_info_internal( key );
00859 }
00860
else
00861 ++it;
00862 }
00863
for(
QMap< KStartupInfoId, Data >::Iterator it = d->silent_startups.begin();
00864 it != d->silent_startups.end();
00865 )
00866 {
00867
if( age_P )
00868 ( *it ).age++;
00869
unsigned int tout = timeout;
00870
if( ( *it ).silent() == Data::Yes )
00871 tout *= 20;
00872
if( ( *it ).age >= tout )
00873 {
00874
const KStartupInfoId&
key = it.key();
00875 ++it;
00876 kdDebug( 172 ) <<
"entry timeout:" <<
key.id() <<
endl;
00877 remove_startup_info_internal( key );
00878 }
00879
else
00880 ++it;
00881 }
00882
for(
QMap< KStartupInfoId, Data >::Iterator it = d->uninited_startups.begin();
00883 it != d->uninited_startups.end();
00884 )
00885 {
00886
if( age_P )
00887 ( *it ).age++;
00888
unsigned int tout = timeout;
00889
if( ( *it ).silent() == Data::Yes )
00890 tout *= 20;
00891
if( ( *it ).age >= tout )
00892 {
00893
const KStartupInfoId&
key = it.key();
00894 ++it;
00895 kdDebug( 172 ) <<
"entry timeout:" <<
key.id() <<
endl;
00896 remove_startup_info_internal( key );
00897 }
00898
else
00899 ++it;
00900 }
00901 }
00902
00903
void KStartupInfo::clean_all_noncompliant()
00904 {
00905
if( d == NULL )
00906
return;
00907
for(
QMap< KStartupInfoId, Data >::Iterator it = d->startups.begin();
00908 it != d->startups.end();
00909 )
00910 {
00911
if( ( *it ).WMClass() !=
"0" )
00912 {
00913 ++it;
00914
continue;
00915 }
00916
const KStartupInfoId&
key = it.key();
00917 ++it;
00918 kdDebug( 172 ) <<
"entry cleaning:" <<
key.id() <<
endl;
00919 remove_startup_info_internal( key );
00920 }
00921 }
00922
00923 QCString KStartupInfo::createNewStartupId()
00924 {
00925
00926
00927
struct timeval tm;
00928 gettimeofday( &tm, NULL );
00929
char hostname[ 256 ];
00930 hostname[ 0 ] =
'\0';
00931
if (!gethostname( hostname, 255 ))
00932 hostname[
sizeof(hostname)-1] =
'\0';
00933
#ifdef Q_WS_X11
00934
extern Time qt_x_user_time;
00935
#else
00936
long qt_x_user_time = 0;
00937
#endif
00938
QCString id =
QString(
"%1;%2;%3;%4_TIME%5" ).arg( hostname ).arg( tm.tv_sec )
00939 .arg( tm.tv_usec ).arg( getpid()).arg( qt_x_user_time ).utf8();
00940 kdDebug( 172 ) <<
"creating: " <<
id <<
":" << qAppName() <<
endl;
00941
return id;
00942 }
00943
00944
00945
struct KStartupInfoIdPrivate
00946 {
00947 KStartupInfoIdPrivate() : id( "" ) {};
00948
QCString id;
00949 };
00950
00951 const QCString&
KStartupInfoId::id()
const
00952
{
00953
return d->id;
00954 }
00955
00956
00957
QString KStartupInfoId::to_text()
const
00958
{
00959
return QString::fromLatin1(
" ID=\"%1\" " ).arg( escape_str(
id()));
00960 }
00961
00962
KStartupInfoId::KStartupInfoId(
const QString& txt_P )
00963 {
00964 d =
new KStartupInfoIdPrivate;
00965
QStringList items = get_fields( txt_P );
00966
const QString id_str =
QString::fromLatin1(
"ID=" );
00967
for( QStringList::Iterator it = items.begin();
00968 it != items.end();
00969 ++it )
00970 {
00971
if( ( *it ).startsWith( id_str ))
00972 d->id = get_cstr( *it );
00973 }
00974 }
00975
00976 void KStartupInfoId::initId(
const QCString& id_P )
00977 {
00978
if( !id_P.
isEmpty())
00979 {
00980 d->id = id_P;
00981
#ifdef KSTARTUPINFO_ALL_DEBUG
00982
kdDebug( 172 ) <<
"using: " << d->id <<
endl;
00983
#endif
00984
return;
00985 }
00986
const char* startup_env = getenv( NET_STARTUP_ENV );
00987
if( startup_env != NULL && *startup_env !=
'\0' )
00988 {
00989 d->id = startup_env;
00990
#ifdef KSTARTUPINFO_ALL_DEBUG
00991
kdDebug( 172 ) <<
"reusing: " << d->id <<
endl;
00992
#endif
00993
return;
00994 }
00995 d->id =
KStartupInfo::createNewStartupId();
00996 }
00997
00998 bool KStartupInfoId::setupStartupEnv()
const
00999
{
01000
if(
id().
isEmpty())
01001 {
01002 unsetenv( NET_STARTUP_ENV );
01003
return false;
01004 }
01005
return setenv( NET_STARTUP_ENV,
id(),
true ) == 0;
01006 }
01007
01008 KStartupInfoId KStartupInfo::currentStartupIdEnv()
01009 {
01010
const char* startup_env = getenv( NET_STARTUP_ENV );
01011
KStartupInfoId id;
01012
if( startup_env != NULL && *startup_env !=
'\0' )
01013
id.d->id = startup_env;
01014
else
01015
id.d->id =
"0";
01016
return id;
01017 }
01018
01019 void KStartupInfo::resetStartupEnv()
01020 {
01021 unsetenv( NET_STARTUP_ENV );
01022 }
01023
01024 KStartupInfoId::KStartupInfoId()
01025 {
01026 d =
new KStartupInfoIdPrivate;
01027 }
01028
01029 KStartupInfoId::~KStartupInfoId()
01030 {
01031
delete d;
01032 }
01033
01034 KStartupInfoId::KStartupInfoId(
const KStartupInfoId& id_P )
01035 {
01036 d =
new KStartupInfoIdPrivate( *id_P.
d );
01037 }
01038
01039
KStartupInfoId& KStartupInfoId::operator=(
const KStartupInfoId& id_P )
01040 {
01041
if( &id_P ==
this )
01042
return *
this;
01043
delete d;
01044 d =
new KStartupInfoIdPrivate( *id_P.
d );
01045
return *
this;
01046 }
01047
01048 bool KStartupInfoId::operator==(
const KStartupInfoId& id_P )
const
01049
{
01050
return id() == id_P.
id();
01051 }
01052
01053 bool KStartupInfoId::operator!=(
const KStartupInfoId& id_P )
const
01054
{
01055
return !(*
this == id_P );
01056 }
01057
01058
01059
bool KStartupInfoId::operator<(
const KStartupInfoId& id_P )
const
01060
{
01061
return id() < id_P.
id();
01062 }
01063
01064 bool KStartupInfoId::none()
const
01065
{
01066
return d->id.isEmpty() || d->id ==
"0";
01067 }
01068
01069 unsigned long KStartupInfoId::timestamp()
const
01070
{
01071
if(
none())
01072
return 0;
01073
int pos = d->id.findRev(
"_TIME" );
01074
if( pos >= 0 )
01075 {
01076
bool ok;
01077
long time = d->id.mid( pos + 5 ).toLong( &ok );
01078
if( ok )
01079
return time;
01080 }
01081
01082
01083
01084
01085
int pos1 = d->id.findRev(
'/' );
01086
if( pos1 > 0 )
01087 {
01088
int pos2 = d->id.findRev(
'/', pos1 - 1 );
01089
if( pos2 >= 0 )
01090 {
01091
bool ok;
01092
long time = d->id.mid( pos2 + 1, pos1 - pos2 - 1 ).toLong( &ok );
01093
if( ok )
01094
return time;
01095 }
01096 }
01097
01098
return 0;
01099 }
01100
01101
struct KStartupInfoDataPrivate
01102 {
01103 KStartupInfoDataPrivate() : desktop( 0 ), wmclass( "" ), hostname( "" ),
01104 silent(
KStartupInfoData::Unknown ), timestamp( -1U ), screen( -1 ) {};
01105
QString bin;
01106
QString name;
01107
QString description;
01108
QString icon;
01109
int desktop;
01110
QValueList< pid_t > pids;
01111
QCString wmclass;
01112
QCString hostname;
01113 KStartupInfoData::TriState silent;
01114
unsigned long timestamp;
01115
int screen;
01116 };
01117
01118
QString KStartupInfoData::to_text()
const
01119
{
01120
QString ret =
"";
01121
if( !d->bin.isEmpty())
01122 ret +=
QString::fromLatin1(
" BIN=\"%1\"" ).arg( escape_str( d->bin ));
01123
if( !d->name.isEmpty())
01124 ret +=
QString::fromLatin1(
" NAME=\"%1\"" ).arg( escape_str( d->name ));
01125
if( !d->description.isEmpty())
01126 ret +=
QString::fromLatin1(
" DESCRIPTION=\"%1\"" ).arg( escape_str( d->description ));
01127
if( !d->icon.isEmpty())
01128 ret +=
QString::fromLatin1(
" ICON=%1" ).arg( d->icon );
01129
if( d->desktop != 0 )
01130 ret +=
QString::fromLatin1(
" DESKTOP=%1" )
01131 .arg( d->desktop == NET::OnAllDesktops ? NET::OnAllDesktops : d->desktop - 1 );
01132
if( !d->wmclass.isEmpty())
01133 ret +=
QString::fromLatin1(
" WMCLASS=%1" ).arg( d->wmclass );
01134
if( !d->hostname.isEmpty())
01135 ret +=
QString::fromLatin1(
" HOSTNAME=%1" ).arg( d->hostname );
01136
for(
QValueList< pid_t >::ConstIterator it = d->pids.begin();
01137 it != d->pids.end();
01138 ++it )
01139 ret +=
QString::fromLatin1(
" PID=%1" ).arg( *it );
01140
if( d->silent != Unknown )
01141 ret +=
QString::fromLatin1(
" SILENT=%1" ).arg( d->silent == Yes ? 1 : 0 );
01142
if( d->timestamp != -1U )
01143 ret +=
QString::fromLatin1(
" TIMESTAMP=%1" ).arg( d->timestamp );
01144
if( d->screen != -1 )
01145 ret +=
QString::fromLatin1(
" SCREEN=%1" ).arg( d->screen );
01146
return ret;
01147 }
01148
01149
KStartupInfoData::KStartupInfoData(
const QString& txt_P )
01150 {
01151 d =
new KStartupInfoDataPrivate;
01152
QStringList items = get_fields( txt_P );
01153
const QString bin_str =
QString::fromLatin1(
"BIN=" );
01154
const QString name_str =
QString::fromLatin1(
"NAME=" );
01155
const QString description_str =
QString::fromLatin1(
"DESCRIPTION=" );
01156
const QString icon_str =
QString::fromLatin1(
"ICON=" );
01157
const QString desktop_str =
QString::fromLatin1(
"DESKTOP=" );
01158
const QString wmclass_str =
QString::fromLatin1(
"WMCLASS=" );
01159
const QString hostname_str =
QString::fromLatin1(
"HOSTNAME=" );
01160
const QString pid_str =
QString::fromLatin1(
"PID=" );
01161
const QString silent_str =
QString::fromLatin1(
"SILENT=" );
01162
const QString timestamp_str =
QString::fromLatin1(
"TIMESTAMP=" );
01163
const QString screen_str =
QString::fromLatin1(
"SCREEN=" );
01164
for( QStringList::Iterator it = items.begin();
01165 it != items.end();
01166 ++it )
01167 {
01168
if( ( *it ).startsWith( bin_str ))
01169 d->bin = get_str( *it );
01170
else if( ( *it ).startsWith( name_str ))
01171 d->name = get_str( *it );
01172
else if( ( *it ).startsWith( description_str ))
01173 d->description = get_str( *it );
01174
else if( ( *it ).startsWith( icon_str ))
01175 d->icon = get_str( *it );
01176
else if( ( *it ).startsWith( desktop_str ))
01177 {
01178 d->desktop = get_num( *it );
01179
if( d->desktop != NET::OnAllDesktops )
01180 ++d->desktop;
01181 }
01182
else if( ( *it ).startsWith( wmclass_str ))
01183 d->wmclass = get_cstr( *it );
01184
else if( ( *it ).startsWith( hostname_str ))
01185 d->hostname = get_cstr( *it );
01186
else if( ( *it ).startsWith( pid_str ))
01187
addPid( get_num( *it ));
01188
else if( ( *it ).startsWith( silent_str ))
01189 d->silent = get_num( *it ) != 0 ? Yes : No;
01190
else if( ( *it ).startsWith( timestamp_str ))
01191 d->timestamp = get_unum( *it );
01192
else if( ( *it ).startsWith( screen_str ))
01193 d->screen = get_num( *it );
01194 }
01195 }
01196
01197 KStartupInfoData::KStartupInfoData(
const KStartupInfoData& data )
01198 {
01199 d =
new KStartupInfoDataPrivate( *data.
d );
01200 }
01201
01202
KStartupInfoData& KStartupInfoData::operator=(
const KStartupInfoData& data )
01203 {
01204
if( &data ==
this )
01205
return *
this;
01206
delete d;
01207 d =
new KStartupInfoDataPrivate( *data.
d );
01208
return *
this;
01209 }
01210
01211 void KStartupInfoData::update(
const KStartupInfoData& data_P )
01212 {
01213
if( !data_P.
bin().
isEmpty())
01214 d->bin = data_P.
bin();
01215
if( !data_P.
name().
isEmpty() &&
name().
isEmpty())
01216 d->name = data_P.
name();
01217
if( !data_P.
description().
isEmpty() &&
description().
isEmpty())
01218 d->description = data_P.
description();
01219
if( !data_P.
icon().
isEmpty() &&
icon().
isEmpty())
01220 d->icon = data_P.
icon();
01221
if( data_P.
desktop() != 0 &&
desktop() == 0 )
01222 d->desktop = data_P.
desktop();
01223
if( !data_P.
d->wmclass.isEmpty())
01224 d->wmclass = data_P.
d->wmclass;
01225
if( !data_P.
d->hostname.isEmpty())
01226 d->hostname = data_P.
d->hostname;
01227
for(
QValueList< pid_t >::ConstIterator it = data_P.
d->pids.begin();
01228 it != data_P.
d->pids.end();
01229 ++it )
01230
addPid( *it );
01231
if( data_P.
silent() != Unknown )
01232 d->silent = data_P.
silent();
01233
if( data_P.
timestamp() != -1U &&
timestamp() == -1U )
01234 d->timestamp = data_P.
timestamp();
01235
if( data_P.
screen() != -1 )
01236 d->screen = data_P.
screen();
01237 }
01238
01239 KStartupInfoData::KStartupInfoData()
01240 {
01241 d =
new KStartupInfoDataPrivate;
01242 }
01243
01244 KStartupInfoData::~KStartupInfoData()
01245 {
01246
delete d;
01247 }
01248
01249 void KStartupInfoData::setBin(
const QString& bin_P )
01250 {
01251 d->bin = bin_P;
01252 }
01253
01254 const QString&
KStartupInfoData::bin()
const
01255
{
01256
return d->bin;
01257 }
01258
01259 void KStartupInfoData::setName(
const QString& name_P )
01260 {
01261 d->name = name_P;
01262 }
01263
01264 const QString&
KStartupInfoData::name()
const
01265
{
01266
return d->name;
01267 }
01268
01269 const QString&
KStartupInfoData::findName()
const
01270
{
01271
if( !
name().
isEmpty())
01272
return name();
01273
return bin();
01274 }
01275
01276 void KStartupInfoData::setDescription(
const QString& desc_P )
01277 {
01278 d->description = desc_P;
01279 }
01280
01281 const QString&
KStartupInfoData::description()
const
01282
{
01283
return d->description;
01284 }
01285
01286 const QString&
KStartupInfoData::findDescription()
const
01287
{
01288
if( !
description().
isEmpty())
01289
return description();
01290
return name();
01291 }
01292
01293 void KStartupInfoData::setIcon(
const QString& icon_P )
01294 {
01295 d->icon = icon_P;
01296 }
01297
01298 const QString&
KStartupInfoData::findIcon()
const
01299
{
01300
if( !
icon().
isEmpty())
01301
return icon();
01302
return bin();
01303 }
01304
01305 const QString&
KStartupInfoData::icon()
const
01306
{
01307
return d->icon;
01308 }
01309
01310 void KStartupInfoData::setDesktop(
int desktop_P )
01311 {
01312 d->desktop = desktop_P;
01313 }
01314
01315 int KStartupInfoData::desktop()
const
01316
{
01317
return d->desktop;
01318 }
01319
01320 void KStartupInfoData::setWMClass(
const QCString& wmclass_P )
01321 {
01322 d->wmclass = wmclass_P;
01323 }
01324
01325 const QCString KStartupInfoData::findWMClass()
const
01326
{
01327
if( !
WMClass().
isEmpty() &&
WMClass() !=
"0" )
01328
return WMClass();
01329
return bin().
utf8();
01330 }
01331
01332 const QCString&
KStartupInfoData::WMClass()
const
01333
{
01334
return d->wmclass;
01335 }
01336
01337 void KStartupInfoData::setHostname(
const QCString& hostname_P )
01338 {
01339
if( !hostname_P.
isNull())
01340 d->hostname = hostname_P;
01341
else
01342 {
01343
char tmp[ 256 ];
01344 tmp[ 0 ] =
'\0';
01345
if (!gethostname( tmp, 255 ))
01346 tmp[
sizeof(tmp)-1] =
'\0';
01347 d->hostname = tmp;
01348 }
01349 }
01350
01351 const QCString&
KStartupInfoData::hostname()
const
01352
{
01353
return d->hostname;
01354 }
01355
01356 void KStartupInfoData::addPid( pid_t pid_P )
01357 {
01358
if( !d->pids.contains( pid_P ))
01359 d->pids.append( pid_P );
01360 }
01361
01362
void KStartupInfoData::remove_pid( pid_t pid_P )
01363 {
01364 d->pids.remove( pid_P );
01365 }
01366
01367 const QValueList< pid_t >&
KStartupInfoData::pids()
const
01368
{
01369
return d->pids;
01370 }
01371
01372 bool KStartupInfoData::is_pid( pid_t pid_P )
const
01373
{
01374
return d->pids.contains( pid_P );
01375 }
01376
01377 void KStartupInfoData::setSilent( TriState state_P )
01378 {
01379 d->silent = state_P;
01380 }
01381
01382 KStartupInfoData::TriState
KStartupInfoData::silent()
const
01383
{
01384
return d->silent;
01385 }
01386
01387 void KStartupInfoData::setTimestamp(
unsigned long time )
01388 {
01389 d->timestamp = time;
01390 }
01391
01392 unsigned long KStartupInfoData::timestamp()
const
01393
{
01394
return d->timestamp;
01395 }
01396
01397 void KStartupInfoData::setScreen(
int screen )
01398 {
01399 d->screen = screen;
01400 }
01401
01402 int KStartupInfoData::screen()
const
01403
{
01404
return d->screen;
01405 }
01406
01407
static
01408
long get_num(
const QString& item_P )
01409 {
01410
unsigned int pos = item_P.
find(
'=' );
01411
return item_P.
mid( pos + 1 ).toLong();
01412 }
01413
01414
static
01415
unsigned long get_unum(
const QString& item_P )
01416 {
01417
unsigned int pos = item_P.
find(
'=' );
01418
return item_P.
mid( pos + 1 ).toULong();
01419 }
01420
01421
static
01422
QString get_str(
const QString& item_P )
01423 {
01424
unsigned int pos = item_P.
find(
'=' );
01425
if( item_P.
length() > pos + 2 && item_P[ pos + 1 ] ==
'\"' )
01426 {
01427
int pos2 = item_P.left( pos + 2 ).find(
'\"' );
01428
if( pos2 < 0 )
01429
return QString::null;
01430
return item_P.mid( pos + 2, pos2 - 2 - pos );
01431 }
01432
return item_P.mid( pos + 1 );
01433 }
01434
01435
static
01436
QCString get_cstr(
const QString& item_P )
01437 {
01438
return get_str( item_P ).
utf8();
01439 }
01440
01441
static
01442
QStringList get_fields(
const QString& txt_P )
01443 {
01444
QString txt = txt_P.
simplifyWhiteSpace();
01445
QStringList ret;
01446
QString item =
"";
01447
bool in =
false;
01448
bool escape =
false;
01449
for(
unsigned int pos = 0;
01450 pos < txt.
length();
01451 ++pos )
01452 {
01453
if( escape )
01454 {
01455 item += txt[ pos ];
01456 escape =
false;
01457 }
01458
else if( txt[ pos ] ==
'\\' )
01459 escape =
true;
01460
else if( txt[ pos ] ==
'\"' )
01461 in = !in;
01462
else if( txt[ pos ] ==
' ' && !in )
01463 {
01464 ret.append( item );
01465 item =
"";
01466 }
01467
else
01468 item += txt[ pos ];
01469 }
01470 ret.append( item );
01471
return ret;
01472 }
01473
01474
static QString escape_str(
const QString& str_P )
01475 {
01476
QString ret =
"";
01477
for(
unsigned int pos = 0;
01478 pos < str_P.
length();
01479 ++pos )
01480 {
01481
if( str_P[ pos ] ==
'\\'
01482 || str_P[ pos ] ==
'"' )
01483 ret +=
'\\';
01484 ret += str_P[ pos ];
01485 }
01486
return ret;
01487 }
01488
01489
#include "kstartupinfo.moc"
01490
#endif