/***************************************************************************
irkick . cpp - Implementation of the main window
- - - - - - - - - - - - - - - - - - -
copyright : ( C ) 2002 by Gav Wood
email : gav @ kde . org
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// This program is free software.
# include <tqwidget.h>
# include <tqdialog.h>
# include <tqtooltip.h>
# include <tqregexp.h>
# include <tqtimer.h>
# include <tqevent.h>
# include <tdeversion.h>
# include <tdeapplication.h>
# include <tdeaction.h>
# if !(TDE_VERSION_MINOR<=1 && TDE_VERSION_RELEASE<=5)
# include <tdeactioncollection.h>
# endif
# include <ksimpleconfig.h>
# include <ksystemtray.h>
# include <kiconloader.h>
# include <kpassivepopup.h>
# include <tdemessagebox.h>
# include <tdepopupmenu.h>
# include <kdebug.h>
# include <tdelocale.h>
# include <tdeaboutdialog.h>
# include <tdeabouttde.h>
# include <twinmodule.h>
# include <twin.h>
# include <khelpmenu.h>
# include <tdeglobal.h>
# include <kstdguiitem.h>
# include <dcopclient.h>
# include <dcopref.h>
# include "profileserver.h"
# include "irkick.h"
void IRKTrayIcon : : mousePressEvent ( TQMouseEvent * e )
{
KSystemTray : : mousePressEvent ( new TQMouseEvent ( TQEvent : : MouseButtonPress , e - > pos ( ) , e - > globalPos ( ) , e - > button ( ) = = TQt : : LeftButton ? TQt : : RightButton : e - > button ( ) , e - > state ( ) ) ) ;
}
IRKick : : IRKick ( const TQCString & obj ) : TQObject ( ) , DCOPObject ( obj ) , npApp ( TQString ( ) )
{
kapp - > dcopClient ( ) - > setDefaultObject ( obj ) ;
theClient = new KLircClient ( ) ;
theTrayIcon = new IRKTrayIcon ( ) ;
if ( theClient - > isConnected ( ) )
{ theTrayIcon - > setPixmap ( SmallIcon ( " irkick " ) ) ;
TQToolTip : : add ( theTrayIcon , i18n ( " TDE Lirc Server: Ready. " ) ) ;
}
else
{ theTrayIcon - > setPixmap ( SmallIcon ( " irkickoff " ) ) ;
TQToolTip : : add ( theTrayIcon , i18n ( " TDE Lirc Server: No infra-red remote controls found. " ) ) ;
TQTimer : : singleShot ( 10000 , this , TQ_SLOT ( checkLirc ( ) ) ) ;
}
theFlashOff = new TQTimer ( theTrayIcon ) ;
connect ( theFlashOff , TQ_SIGNAL ( timeout ( ) ) , TQ_SLOT ( flashOff ( ) ) ) ;
theResetCount = 0 ;
slotReloadConfiguration ( ) ;
connect ( theClient , TQ_SIGNAL ( connectionClosed ( ) ) , this , TQ_SLOT ( slotClosed ( ) ) ) ;
connect ( theClient , TQ_SIGNAL ( remotesRead ( ) ) , this , TQ_SLOT ( resetModes ( ) ) ) ;
connect ( theClient , TQ_SIGNAL ( commandReceived ( const TQString & , const TQString & , int ) ) , this , TQ_SLOT ( gotMessage ( const TQString & , const TQString & , int ) ) ) ;
theTrayIcon - > contextMenu ( ) - > changeTitle ( 0 , " IRKick " ) ;
theTrayIcon - > contextMenu ( ) - > insertItem ( SmallIcon ( " configure " ) , i18n ( " &Configure... " ) , this , TQ_SLOT ( slotConfigure ( ) ) ) ;
theTrayIcon - > contextMenu ( ) - > insertSeparator ( ) ;
theTrayIcon - > contextMenu ( ) - > insertItem ( SmallIcon ( " help " ) , KStdGuiItem : : help ( ) . text ( ) , ( new KHelpMenu ( theTrayIcon , TDEGlobal : : instance ( ) - > aboutData ( ) ) ) - > menu ( ) ) ;
theTrayIcon - > actionCollection ( ) - > action ( " file_quit " ) - > disconnect ( TQ_SIGNAL ( activated ( ) ) ) ;
connect ( theTrayIcon - > actionCollection ( ) - > action ( " file_quit " ) , TQ_SIGNAL ( activated ( ) ) , TQ_SLOT ( doQuit ( ) ) ) ;
theTrayIcon - > show ( ) ;
}
IRKick : : ~ IRKick ( )
{
delete theTrayIcon ;
for ( TQMap < TQString , IRKTrayIcon * > : : iterator i = currentModeIcons . begin ( ) ; i ! = currentModeIcons . end ( ) ; + + i )
if ( * i ) delete * i ;
}
void IRKick : : slotClosed ( )
{
theTrayIcon - > setPixmap ( SmallIcon ( " irkickoff " ) ) ;
KPassivePopup : : message ( " IRKick " , i18n ( " The infrared system has severed its connection. Remote controls are no longer available. " ) , SmallIcon ( " irkick " ) , theTrayIcon ) ;
TQTimer : : singleShot ( 1000 , this , TQ_SLOT ( checkLirc ( ) ) ) ;
}
void IRKick : : checkLirc ( )
{
if ( ! theClient - > isConnected ( ) )
if ( theClient - > connectToLirc ( ) )
{ KPassivePopup : : message ( " IRKick " , i18n ( " A connection to the infrared system has been made. Remote controls may now be available. " ) , SmallIcon ( " irkick " ) , theTrayIcon ) ;
theTrayIcon - > setPixmap ( SmallIcon ( " irkick " ) ) ;
}
else
TQTimer : : singleShot ( 10000 , this , TQ_SLOT ( checkLirc ( ) ) ) ;
}
void IRKick : : flashOff ( )
{
theTrayIcon - > setPixmap ( SmallIcon ( " irkick " ) ) ;
}
void IRKick : : doQuit ( )
{
KSimpleConfig theConfig ( " irkickrc " ) ;
theConfig . setGroup ( " General " ) ;
switch ( KMessageBox : : questionYesNoCancel ( 0 , i18n ( " Should the Infrared Remote Control server start automatically when you begin TDE? " ) , i18n ( " Automatically Start? " ) , i18n ( " Start Automatically " ) , i18n ( " Do Not Start " ) ) )
{ case KMessageBox : : No : theConfig . writeEntry ( " AutoStart " , false ) ; break ;
case KMessageBox : : Yes : theConfig . writeEntry ( " AutoStart " , true ) ; break ;
case KMessageBox : : Cancel : return ;
}
TDEApplication : : kApplication ( ) - > quit ( ) ;
}
void IRKick : : resetModes ( )
{
if ( theResetCount > 1 )
KPassivePopup : : message ( " IRKick " , i18n ( " Resetting all modes. " ) , SmallIcon ( " irkick " ) , theTrayIcon ) ;
if ( ! theResetCount )
allModes . generateNulls ( theClient - > remotes ( ) ) ;
TQStringList remotes = theClient - > remotes ( ) ;
for ( TQStringList : : iterator i = remotes . begin ( ) ; i ! = remotes . end ( ) ; + + i )
{ currentModes [ * i ] = allModes . getDefault ( * i ) . name ( ) ;
if ( theResetCount & & currentModeIcons [ * i ] ) delete currentModeIcons [ * i ] ;
currentModeIcons [ * i ] = 0 ;
}
updateModeIcons ( ) ;
theResetCount + + ;
}
void IRKick : : slotReloadConfiguration ( )
{
// load configuration from config file
KSimpleConfig theConfig ( " irkickrc " ) ;
allActions . loadFromConfig ( theConfig ) ;
allModes . loadFromConfig ( theConfig ) ;
if ( currentModes . count ( ) & & theResetCount )
resetModes ( ) ;
}
void IRKick : : slotConfigure ( )
{
TDEApplication : : startServiceByDesktopName ( " kcmlirc " ) ;
}
void IRKick : : updateModeIcons ( )
{
for ( TQMap < TQString , TQString > : : iterator i = currentModes . begin ( ) ; i ! = currentModes . end ( ) ; + + i )
{ Mode mode = allModes . getMode ( i . key ( ) , i . data ( ) ) ;
if ( mode . iconFile ( ) . isNull ( ) | | mode . iconFile ( ) . isEmpty ( ) )
{ if ( currentModeIcons [ i . key ( ) ] )
{ delete currentModeIcons [ i . key ( ) ] ;
currentModeIcons [ i . key ( ) ] = 0 ;
}
}
else
{ if ( ! currentModeIcons [ i . key ( ) ] )
{ currentModeIcons [ i . key ( ) ] = new IRKTrayIcon ( ) ;
currentModeIcons [ i . key ( ) ] - > show ( ) ;
currentModeIcons [ i . key ( ) ] - > contextMenu ( ) - > changeTitle ( 0 , mode . remoteName ( ) ) ;
currentModeIcons [ i . key ( ) ] - > actionCollection ( ) - > action ( " file_quit " ) - > setEnabled ( false ) ;
}
currentModeIcons [ i . key ( ) ] - > setPixmap ( TDEIconLoader ( ) . loadIcon ( mode . iconFile ( ) , TDEIcon : : Panel ) ) ;
TQToolTip : : add ( currentModeIcons [ i . key ( ) ] , mode . remoteName ( ) + " : <b> " + mode . name ( ) + " </b> " ) ;
}
}
}
bool IRKick : : getPrograms ( const IRAction & action , TQStringList & programs )
{
DCOPClient * theDC = TDEApplication : : dcopClient ( ) ;
programs . clear ( ) ;
if ( action . unique ( ) )
{ if ( theDC - > isApplicationRegistered ( action . program ( ) . utf8 ( ) ) )
programs + = action . program ( ) ;
}
else
{
TQRegExp r = TQRegExp ( " ^ " + action . program ( ) + " -( \\ d+)$ " ) ;
// find all instances...
QCStringList buf = theDC - > registeredApplications ( ) ;
for ( QCStringList : : iterator i = buf . begin ( ) ; i ! = buf . end ( ) ; + + i )
{
TQString program = TQString : : fromUtf8 ( * i ) ;
if ( program . contains ( r ) )
programs + = program ;
}
if ( programs . size ( ) > 1 & & action . ifMulti ( ) = = IM_DONTSEND )
return false ;
else if ( programs . size ( ) > 1 & & action . ifMulti ( ) = = IM_SENDTOTOP )
{ TQValueList < WId > s = KWinModule ( ) . stackingOrder ( ) ;
// go through all the (ordered) window pids
for ( TQValueList < WId > : : iterator i = s . fromLast ( ) ; i ! = s . end ( ) ; i - - )
{ int p = KWin : : info ( * i ) . pid ;
TQString id = action . program ( ) + " - " + TQString ( ) . setNum ( p ) ;
if ( programs . contains ( id ) )
{ programs . clear ( ) ;
programs + = id ;
break ;
}
}
while ( programs . size ( ) > 1 ) programs . remove ( programs . begin ( ) ) ;
}
else if ( programs . size ( ) > 1 & & action . ifMulti ( ) = = IM_SENDTOBOTTOM )
{ TQValueList < WId > s = KWinModule ( ) . stackingOrder ( ) ;
// go through all the (ordered) window pids
for ( TQValueList < WId > : : iterator i = s . begin ( ) ; i ! = s . end ( ) ; + + i )
{ int p = KWin : : info ( * i ) . pid ;
TQString id = action . program ( ) + " - " + TQString ( ) . setNum ( p ) ;
if ( programs . contains ( id ) )
{ programs . clear ( ) ;
programs + = id ;
break ;
}
}
while ( programs . size ( ) > 1 ) programs . remove ( programs . begin ( ) ) ;
}
}
return true ;
}
void IRKick : : executeAction ( const IRAction & action )
{
DCOPClient * theDC = TDEApplication : : dcopClient ( ) ;
TQStringList programs ;
if ( ! getPrograms ( action , programs ) ) return ;
// if programs.size()==0 here, then the app is definately not running.
if ( action . autoStart ( ) & & ! programs . size ( ) )
{ TQString sname = ProfileServer : : profileServer ( ) - > getServiceName ( action . program ( ) ) ;
if ( ! sname . isNull ( ) )
{
KPassivePopup : : message ( " IRKick " , i18n ( " Starting <b>%1</b>... " ) . arg ( action . application ( ) ) , SmallIcon ( " irkick " ) , theTrayIcon ) ;
TDEApplication : : startServiceByDesktopName ( sname ) ;
}
}
if ( action . isJustStart ( ) ) return ;
if ( ! getPrograms ( action , programs ) ) return ;
for ( TQStringList : : iterator i = programs . begin ( ) ; i ! = programs . end ( ) ; + + i )
{ const TQString & program = * i ;
if ( theDC - > isApplicationRegistered ( program . utf8 ( ) ) )
{ TQByteArray data ; TQDataStream arg ( data , IO_WriteOnly ) ;
kdDebug ( ) < < " Sending data ( " < < program < < " , " < < action . object ( ) < < " , " < < action . method ( ) . prototypeNR ( ) < < endl ;
for ( Arguments : : const_iterator j = action . arguments ( ) . begin ( ) ; j ! = action . arguments ( ) . end ( ) ; + + j )
{ kdDebug ( ) < < " Got argument... " < < endl ;
switch ( ( * j ) . type ( ) )
{ case TQVariant : : Int : arg < < ( * j ) . toInt ( ) ; break ;
case TQVariant : : CString : arg < < ( * j ) . toCString ( ) ; break ;
case TQVariant : : StringList : arg < < ( * j ) . toStringList ( ) ; break ;
case TQVariant : : UInt : arg < < ( * j ) . toUInt ( ) ; break ;
case TQVariant : : Bool : arg < < ( * j ) . toBool ( ) ; break ;
case TQVariant : : Double : arg < < ( * j ) . toDouble ( ) ; break ;
default : arg < < ( * j ) . toString ( ) ; break ;
}
}
theDC - > send ( program . utf8 ( ) , action . object ( ) . utf8 ( ) , action . method ( ) . prototypeNR ( ) . utf8 ( ) , data ) ;
}
}
}
void IRKick : : gotMessage ( const TQString & theRemote , const TQString & theButton , int theRepeatCounter )
{
kdDebug ( ) < < " Got message: " < < theRemote < < " : " < < theButton < < " ( " < < theRepeatCounter < < " ) " < < endl ;
theTrayIcon - > setPixmap ( SmallIcon ( " irkickflash " ) ) ;
theFlashOff - > start ( 200 , true ) ;
if ( ! npApp . isNull ( ) )
{
TQString theApp = npApp ;
npApp = TQString ( ) ;
// send notifier by DCOP to npApp/npModule/npMethod(theRemote, theButton);
TQByteArray data ; TQDataStream arg ( data , IO_WriteOnly ) ;
arg < < theRemote < < theButton ;
TDEApplication : : dcopClient ( ) - > send ( theApp . utf8 ( ) , npModule . utf8 ( ) , npMethod . utf8 ( ) , data ) ;
}
else
{
if ( currentModes [ theRemote ] . isNull ( ) ) currentModes [ theRemote ] = " " ;
IRAItList l = allActions . findByModeButton ( Mode ( theRemote , currentModes [ theRemote ] ) , theButton ) ;
if ( ! currentModes [ theRemote ] . isEmpty ( ) )
l + = allActions . findByModeButton ( Mode ( theRemote , " " ) , theButton ) ;
bool doBefore = true , doAfter = false ;
for ( IRAItList : : const_iterator i = l . begin ( ) ; i ! = l . end ( ) ; + + i )
if ( ( * * i ) . isModeChange ( ) & & ! theRepeatCounter )
{ // mode switch
currentModes [ theRemote ] = ( * * i ) . modeChange ( ) ;
Mode mode = allModes . getMode ( theRemote , ( * * i ) . modeChange ( ) ) ;
updateModeIcons ( ) ;
doBefore = ( * * i ) . doBefore ( ) ;
doAfter = ( * * i ) . doAfter ( ) ;
break ;
}
for ( int after = 0 ; after < 2 ; after + + )
{ if ( doBefore & & ! after | | doAfter & & after )
for ( IRAItList : : const_iterator i = l . begin ( ) ; i ! = l . end ( ) ; + + i )
if ( ! ( * * i ) . isModeChange ( ) & & ( ( * * i ) . repeat ( ) | | ! theRepeatCounter ) )
{ executeAction ( * * i ) ;
}
if ( ! after & & doAfter )
{ l = allActions . findByModeButton ( Mode ( theRemote , currentModes [ theRemote ] ) , theButton ) ;
if ( ! currentModes [ theRemote ] . isEmpty ( ) )
l + = allActions . findByModeButton ( Mode ( theRemote , " " ) , theButton ) ;
}
}
}
}
void IRKick : : stealNextPress ( TQString app , TQString module , TQString method )
{
npApp = app ;
npModule = module ;
npMethod = method ;
}
void IRKick : : dontStealNextPress ( )
{
npApp = TQString ( ) ;
}
# include "irkick.moc"