# include <unistd.h>
# include <sys/stat.h>
# include <tqtooltip.h>
# include <tqtimer.h>
# include <tqfile.h>
# include <kaboutdata.h>
# include <kcmdlineargs.h>
# include <kdebug.h>
# include <kglobal.h>
# include <kglobalaccel.h>
# include <klocale.h>
# include <kmessagebox.h>
# include <kiconloader.h>
# include <kaboutapplication.h>
# include <kaction.h>
# include <kpopupmenu.h>
# include <kconfig.h>
# include <kpassivepopup.h>
# include <kiconloader.h>
# include <apt-front/init.h>
# include <apt-front/cache/cache.h>
# include <apt-front/cache/component/packages.h>
# include <apt-front/predicate/factory.h>
# include <adept/utils.h>
# include "app.h"
using namespace aptFront ;
using namespace cache ;
using namespace utils ;
using namespace adept ;
TrayWindow : : TrayWindow ( TQWidget * parent , const char * name )
: KSystemTray ( parent , name ) , m_updates ( 0 )
{
setAvailableUpdates ( m_updates ) ;
// actionCollection()->remove( actionCollection()->action( "quit" ) );
m_quit = KStdAction : : quit ( TQT_TQOBJECT ( this ) , TQT_SIGNAL ( quitSelected ( ) ) , actionCollection ( ) ) ;
m_about = KStdAction : : aboutApp ( TQT_TQOBJECT ( this ) , TQT_SIGNAL ( aboutSelected ( ) ) , actionCollection ( ) ) ;
// setPixmap( loadIcon( u8( "adept_notifier_warning" ) ) );
}
void TrayWindow : : contextMenuAboutToShow ( KPopupMenu * r ) {
kdDebug ( ) < < " TrayWindow::contextMenu() " < < endl ;
r - > clear ( ) ;
m_about - > plug ( r ) ;
m_quit - > plug ( r ) ;
}
void TrayWindow : : resizeEvent ( TQResizeEvent * )
{
// Honor Free Desktop specifications that allow for arbitrary system tray icon sizes
setPixmap ( m_updates = = 0 ?
loadSizedIcon ( u8 ( " adept_notifier_ok " ) , width ( ) ) :
loadSizedIcon ( u8 ( " adept_notifier_warning " ) , width ( ) ) ) ;
if ( m_updates = = 0 )
hide ( ) ;
else
show ( ) ;
}
void TrayWindow : : setAvailableUpdates ( int n )
{
m_updates = n ;
kdDebug ( ) < < " TrayWindow obtained " < < n < < endl ;
setPixmap ( m_updates = = 0 ?
loadSizedIcon ( u8 ( " adept_notifier_ok " ) , width ( ) ) :
loadSizedIcon ( u8 ( " adept_notifier_warning " ) , width ( ) ) ) ;
if ( m_updates = = 0 )
hide ( ) ;
else
show ( ) ;
TQToolTip : : remove ( this ) ;
TQToolTip : : add ( this , n = = 0 ? i18n ( " No updates needed. " )
: i18n ( " There is %n updated package available " ,
" There are %n updated packages available " , n ) ) ;
}
void TrayWindow : : mouseReleaseEvent ( TQMouseEvent * ev )
{
if ( ev - > button ( ) = = Qt : : LeftButton )
emit clicked ( ) ;
KSystemTray : : mouseReleaseEvent ( ev ) ;
}
void ApportTrayWindow : : mousePressEvent ( TQMouseEvent * ev )
{
emit clicked ( ) ;
hide ( ) ;
}
void ApportTrayWindow : : resizeEvent ( TQResizeEvent * )
{
// Honor Free Desktop specifications that allow for arbitrary system tray icon sizes
setPixmap ( loadSizedIcon ( u8 ( " apport " ) , width ( ) ) ) ;
}
void RebootTrayWindow : : mousePressEvent ( TQMouseEvent * ev )
{
emit clicked ( ) ;
}
void RebootTrayWindow : : resizeEvent ( TQResizeEvent * )
{
// Honor Free Desktop specifications that allow for arbitrary system tray icon sizes
setPixmap ( loadSizedIcon ( u8 ( " reload " ) , width ( ) ) ) ;
}
NotifierApp : : NotifierApp ( bool allowStyles , bool GUIenabled )
: KUniqueApplication ( allowStyles , GUIenabled ) ,
m_tray ( 0 )
{
sharedConfig ( ) - > setGroup ( " General " ) ;
m_okAutostart = sharedConfig ( ) - > readBoolEntry ( " Autostart " , true ) ;
m_timer = new TQTimer ( this ) ;
m_tray = new TrayWindow ( 0 , 0 ) ;
m_tray - > show ( ) ;
m_rebootRequired = false ;
m_rebootShown = false ;
aptFront : : init ( ) ;
fileUpdated ( " /var/cache/apt/pkglist.bin " , m_updateStamp ) ;
// fileUpdated( "/var/lib/apt/periodic/update-stamp", m_updateStamp );
fileUpdated ( " /var/lib/dpkg/status " , m_statusStamp ) ;
m_tray - > setAvailableUpdates ( upgradable ( ) ) ;
connect ( m_tray , TQT_SIGNAL ( clicked ( ) ) , this , TQT_SLOT ( clicked ( ) ) ) ;
// connect( m_tray, TQT_SIGNAL( quitSelected() ), this, TQT_SLOT( quit() ) );
connect ( m_tray , TQT_SIGNAL ( quitSelected ( ) ) , this , TQT_SLOT ( askQuit ( ) ) ) ;
connect ( m_tray , TQT_SIGNAL ( aboutSelected ( ) ) , this , TQT_SLOT ( about ( ) ) ) ;
connect ( m_timer , TQT_SIGNAL ( timeout ( ) ) , this , TQT_SLOT ( checkUpdates ( ) ) ) ;
m_timer - > start ( 1000 * 5 ) ; // 5 secs now, used to be 60
if ( ! m_okAutostart ) {
int r = KMessageBox : : questionYesNo (
m_tray , i18n ( " You disabled automatic startup of Adept Notifier last time "
" you quit the application. "
" Do you want to start Adept Notifier next time you log in? " ) ,
i18n ( " Automatic Startup " ) ,
KGuiItem ( i18n ( " Start " ) ) , KGuiItem ( i18n ( " Don't Start " ) ) ,
u8 ( " enableAutostart " ) ) ;
if ( r = = KMessageBox : : Yes ) {
sharedConfig ( ) - > setGroup ( " General " ) ;
sharedConfig ( ) - > writeEntry ( " Autostart " , true ) ;
m_okAutostart = true ;
}
}
// if apport crash handler it installed, watch for crash reports appearing and run
// the apport frontend when they do
bool runApport = sharedConfig ( ) - > readBoolEntry ( " Apport " , true ) ;
if ( TQFile : : exists ( TQString ( " /usr/share/apport/apport-qt " ) ) & & runApport ) {
m_dirWatch = new KDirWatch ( TQT_TQOBJECT ( this ) ) ;
m_dirWatch - > addDir ( TQString ( " /var/crash " ) ) ;
connect ( m_dirWatch , TQT_SIGNAL ( dirty ( const TQString & ) ) , this , TQT_SLOT ( crashWatcher ( ) ) ) ;
KProcess * proc = new KProcess ;
* proc < < " /usr/share/apport/apport-checkreports " ;
connect ( proc , TQT_SIGNAL ( processExited ( KProcess * ) ) , this , TQT_SLOT ( apportCheckExited ( KProcess * ) ) ) ;
proc - > start ( KProcess : : Block ) ;
if ( m_crashes ) {
ApportTrayWindow * crashApplet = new ApportTrayWindow ;
crashApplet - > setPixmap ( crashApplet - > loadSizedIcon ( u8 ( " apport " ) , crashApplet - > width ( ) ) ) ;
TQString crashMessage = i18n ( " An application has crashed on your "
" system (now or in the past). \n "
" Click to "
" display details. "
) ;
TQToolTip : : add ( crashApplet , crashMessage ) ;
connect ( crashApplet , TQT_SIGNAL ( clicked ( ) ) , this , TQT_SLOT ( crashWatcher ( ) ) ) ;
crashApplet - > show ( ) ;
TQPixmap icon = BarIcon ( u8 ( " apport " ) ) ;
KPassivePopup : : message ( i18n ( " Crash Handler " ) , crashMessage , icon , crashApplet ) ;
}
}
// if reboot-required is installed watch for reboot-required and dpkg-run-stamp
if ( TQFile : : exists ( TQString ( " /usr/share/update-notifier/notify-reboot-required " ) ) ) {
m_rebootDirWatch = new KDirWatch ( TQT_TQOBJECT ( this ) ) ;
m_rebootDirWatch - > addFile ( TQString ( " /var/run/reboot-required " ) ) ;
m_rebootDirWatch - > addFile ( TQString ( " /var/lib/update-notifier/dpkg-run-stamp " ) ) ;
connect ( m_rebootDirWatch , TQT_SIGNAL ( dirty ( const TQString & ) ) , this , TQT_SLOT ( rebootWatcher ( const TQString & ) ) ) ;
}
}
void NotifierApp : : crashWatcher ( ) {
// find out if there are system crash reports first, if there are run it as root
KProcess * proc = new KProcess ;
* proc < < " /usr/share/apport/apport-checkreports " ;
* proc < < " --system " ;
connect ( proc , TQT_SIGNAL ( processExited ( KProcess * ) ) , this , TQT_SLOT ( apportCheckExited ( KProcess * ) ) ) ;
proc - > start ( KProcess : : Block ) ;
if ( m_crashes ) {
KProcess * proc2 = new KProcess ;
* proc2 < < " tdesu " < < " /usr/share/apport/apport-qt " ;
proc2 - > start ( KProcess : : DontCare ) ;
} else {
KShellProcess * proc2 = new KShellProcess ;
* proc2 < < " sleep 1; /usr/share/apport/apport-qt " ; //needs a seconds delay else we're too fast for apport
proc2 - > start ( KProcess : : DontCare ) ;
}
}
void NotifierApp : : apportCheckExited ( KProcess * proc ) {
if ( proc - > exitStatus ( ) = = 0 ) {
m_crashes = true ;
} else {
m_crashes = false ;
}
}
void NotifierApp : : rebootWatcher ( const TQString & path ) {
kdDebug ( ) < < " NotifierApp::rebootWatcher: " < < path < < endl ;
if ( path = = TQString ( " /var/run/reboot-required " ) ) {
m_rebootRequired = true ;
}
if ( path = = TQString ( " /var/lib/update-notifier/dpkg-run-stamp " ) & & m_rebootRequired & & ! m_rebootShown ) {
RebootTrayWindow * rebootApplet = new RebootTrayWindow ;
rebootApplet - > setPixmap ( rebootApplet - > loadSizedIcon ( u8 ( " reload " ) , rebootApplet - > width ( ) ) ) ;
TQString rebootMessage = i18n ( " In order to complete the update your system needs to be restarted. " ) ;
TQToolTip : : add ( rebootApplet , rebootMessage ) ;
connect ( rebootApplet , TQT_SIGNAL ( clicked ( ) ) , this , TQT_SLOT ( rebootClicked ( ) ) ) ;
rebootApplet - > show ( ) ;
TQPixmap icon = BarIcon ( u8 ( " reload " ) ) ;
KPassivePopup : : message ( i18n ( " Reboot Required " ) , rebootMessage , icon , rebootApplet ) ;
m_rebootShown = true ;
}
}
void NotifierApp : : rebootClicked ( ) {
kdDebug ( ) < < " NotifierApp::rebootClicked " < < endl ;
if ( KMessageBox : : questionYesNo ( 0 , TQString ( " In order to complete the update your system needs to be restarted. " ) , TQString ( " Restart Require " ) ) = = KMessageBox : : Yes ) {
kdDebug ( ) < < " NotifierApp::rebootClicked yes! " < < endl ;
KProcess * proc = new KProcess ;
* proc < < " /usr/bin/dcop " ;
* proc < < " ksmserver " < < " ksmserver " < < " logout " < < " 0 " < < " 1 " < < " 2 " ; // 0 1 2 == ShutdownConfirmNo ShutdownTypeReboot ShutdownModeForceNow
proc - > start ( ) ;
}
}
void NotifierApp : : askQuit ( ) {
if ( m_okAutostart ) {
int r = KMessageBox : : questionYesNoCancel (
m_tray , i18n ( " Do you want to start Adept Notifier next time you log in? " ) ,
i18n ( " Automatic Startup " ) ,
KGuiItem ( i18n ( " Start " ) ) , KGuiItem ( i18n ( " Don't Start " ) ) ) ;
if ( r = = KMessageBox : : Cancel )
return ;
if ( r = = KMessageBox : : No ) {
sharedConfig ( ) - > setGroup ( " General " ) ;
sharedConfig ( ) - > writeEntry ( " Autostart " , false ) ;
}
}
exit ( 0 ) ;
}
bool NotifierApp : : fileUpdated ( const char * f , time_t & stamp ) {
time_t old = stamp ;
struct stat s ;
: : stat ( f , & s ) ;
stamp = s . st_mtime ;
if ( stamp > old )
return true ;
return false ;
}
int NotifierApp : : upgradable ( ) {
try {
kdDebug ( ) < < " checking cache for upgradable packages... " < < endl ;
cache : : Cache & c = cache : : Global : : get ( ) ;
c . open ( Cache : : OpenReadOnly
| Cache : : OpenPackages
| Cache : : OpenState ) ;
kdDebug ( ) < < " cache opened, listing... " < < endl ;
Range < entity : : Package > r = range ( c . packages ( ) . packagesBegin ( ) ,
c . packages ( ) . packagesEnd ( ) ) ;
kdDebug ( ) < < " looking for upgradable packages... " < < endl ;
Range < entity : : Package > fr = filteredRange (
r , predicate : : Package : : member ( & entity : : Package : : isUpgradable ) ) ;
VectorRange < entity : : Package > vr = VectorRange < entity : : Package > ( ) ;
fr . output ( vr ) ;
kdDebug ( ) < < " found " < < vr . size ( ) < < " upgradable package(s) " < < endl ;
int ret = vr . size ( ) ;
c . close ( ) ;
return ret ;
} catch ( exception : : Error e ) {
kdDebug ( ) < < " error checking cache for upgradable packages... " < < endl ;
kdDebug ( ) < < " what: " < < e . message ( ) < < endl ;
} catch ( std : : exception e ) {
kdDebug ( ) < < " exception checking cache for upgradable packages... " < < endl ;
kdDebug ( ) < < " what: " < < e . what ( ) < < endl ;
// XXX error handling
}
return true ; // we don't know, so assume true (safe)
}
void NotifierApp : : checkUpdates ( ) {
// kdDebug() << "checking updates status" << endl;
if ( // fileUpdated( "/var/lib/apt/periodic/update-stamp", m_updateStamp )
fileUpdated ( " /var/cache/apt/pkgcache.bin " , m_updateStamp )
| | fileUpdated ( " /var/lib/dpkg/status " , m_statusStamp ) )
m_tray - > setAvailableUpdates ( upgradable ( ) ) ;
}
void NotifierApp : : about ( ) {
KAboutApplication * a = new KAboutApplication ( m_tray , " " , true ) ;
a - > exec ( ) ;
delete a ;
}
NotifierApp : : ~ NotifierApp ( )
{
delete m_tray ;
}
void NotifierApp : : clicked ( )
{
if ( m_tray - > updates ( ) = = 0 )
return KMessageBox : : information (
0 , i18n ( " There are no known updates available. " ) ,
i18n ( " Nothing to do " ) ) ;
startServiceByDesktopName ( u8 ( " adept_updater " ) ) ;
}
/* void NotifierApp::menuActivated(int id)
{
// implement help
} */
const char * DESCRIPTION =
I18N_NOOP ( " Adept update notifier utility " ) ;
/* extern "C" KDE_EXPORT */
int main ( int argc , char * argv [ ] )
{
KAboutData about ( " adept_notifier " , I18N_NOOP ( " Adept Notifier " ) ,
" 2.1 Cruiser " ,
DESCRIPTION , KAboutData : : License_BSD ,
" Copyright (C) 2005, 2006 Peter Rockai " ) ;
KCmdLineArgs : : init ( argc , argv , & about ) ;
NotifierApp : : addCmdLineOptions ( ) ;
if ( ! NotifierApp : : start ( ) )
return 0 ;
NotifierApp app ;
app . disableSessionManagement ( ) ;
app . exec ( ) ;
return 0 ;
}