kio Library API Documentation

knotifydialog.cpp

00001 /*
00002   Copyright (C) 2000,2002 Carsten Pfeiffer <pfeiffer@kde.org>
00003   Copyright (C) 2002 Neil Stevens <neil@qualityassistant.com>
00004 
00005   This program is free software; you can redistribute it and/or
00006   modify it under the terms of the GNU Library General Public
00007   License version 2 as published by the Free Software Foundation;
00008 
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012   General Public License for more details.
00013 
00014   You should have received a copy of the GNU Library General Public License
00015   along with this library,  If not, write to the Free Software Foundation,
00016   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 #include <dcopclient.h>
00020 
00021 #include <kaboutdata.h>
00022 #include <kapplication.h>
00023 #include <kaudioplayer.h>
00024 #include <kcombobox.h>
00025 #include <kconfig.h>
00026 #include <kcursor.h>
00027 #include <kdebug.h>
00028 #include <kfiledialog.h>
00029 #include <kiconloader.h>
00030 #include <kicontheme.h>
00031 #include <klineedit.h>
00032 #include <klocale.h>
00033 #include <kmessagebox.h>
00034 #include <knotifyclient.h>
00035 #include <knotifydialog.h>
00036 #include <kstandarddirs.h>
00037 #include <kurlrequester.h>
00038 
00039 #include <qcheckbox.h>
00040 #include <qgroupbox.h>
00041 #include <qheader.h>
00042 #include <qlabel.h>
00043 #include <qlistview.h>
00044 #include <qlayout.h>
00045 #include <qptrlist.h>
00046 #include <qpushbutton.h>
00047 #include <qstring.h>
00048 #include <qtooltip.h>
00049 #include <qtimer.h>
00050 #include <qvbox.h>
00051 #include <qwhatsthis.h>
00052 
00053 using namespace KNotify;
00054 
00055 enum
00056 {
00057     COL_EXECUTE = 0,
00058     COL_STDERR  = 1,
00059     COL_MESSAGE = 2,
00060     COL_LOGFILE = 3,
00061     COL_SOUND   = 4,
00062     COL_TASKBAR = 5,
00063     COL_EVENT   = 6
00064 };
00065 
00066 //
00067 // I don't feel like subclassing KComboBox and find ways to insert that into
00068 // the .ui file...
00069 //
00070 namespace KNotify
00071 {
00072     class SelectionCombo
00073     {
00074     public:
00075         //
00076         // Mind the order in fill() and type()
00077         //
00078         static void fill( KComboBox *combo )
00079         {
00080             combo->insertItem( i18n("Sounds") );
00081             combo->insertItem( i18n("Logging") );
00082             combo->insertItem( i18n("Program Execution") );
00083             combo->insertItem( i18n("Message Windows") );
00084             combo->insertItem( i18n("Passive Windows") );
00085             combo->insertItem( i18n("Standard Error Output") );
00086             combo->insertItem( i18n("Taskbar") );
00087         }
00088 
00089         static int type( KComboBox *combo )
00090         {
00091             switch( combo->currentItem() )
00092             {
00093                 case 0:
00094                     return KNotifyClient::Sound;
00095                 case 1:
00096                     return KNotifyClient::Logfile;
00097                 case 2:
00098                     return KNotifyClient::Execute;
00099                 case 3:
00100                     return KNotifyClient::Messagebox;
00101                 case 4:
00102                     return KNotifyClient::PassivePopup;
00103                 case 5:
00104                     return KNotifyClient::Stderr;
00105                 case 6:
00106                     return KNotifyClient::Taskbar;
00107             }
00108 
00109             return KNotifyClient::None;
00110         }
00111     };
00112 
00113     // Needed for displaying tooltips in the listview's QHeader
00114     class KNotifyToolTip : public QToolTip
00115     {
00116     public:
00117         KNotifyToolTip( QHeader *header )
00118             : QToolTip( header )
00119         {
00120             m_tips[COL_EXECUTE] = i18n("Execute a program");
00121             m_tips[COL_STDERR]  = i18n("Print to Standard error output");
00122             m_tips[COL_MESSAGE] = i18n("Display a messagebox");
00123             m_tips[COL_LOGFILE] = i18n("Log to a file");
00124             m_tips[COL_SOUND]   = i18n("Play a sound");
00125             m_tips[COL_TASKBAR] = i18n("Flash the taskbar entry");
00126         }
00127         virtual ~KNotifyToolTip() {}
00128 
00129     protected:
00130         virtual void maybeTip ( const QPoint& p )
00131         {
00132             QHeader *header = static_cast<QHeader*>( parentWidget() );
00133             int section = 0;
00134 
00135             if ( header->orientation() == Horizontal )
00136                 section= header->sectionAt( p.x() );
00137             else
00138                 section= header->sectionAt( p.y() );
00139 
00140             if ( ( section < 0 ) || ( static_cast<uint>( section ) >= (sizeof(m_tips) / sizeof(QString)) ) )
00141                 return;
00142 
00143             tip( header->sectionRect( section ), m_tips[section] );
00144         }
00145 
00146     private:
00147         QString m_tips[6];
00148     };
00149 
00150 }
00151 
00152 
00153 int KNotifyDialog::configure( QWidget *parent, const char *name,
00154                               const KAboutData *aboutData )
00155 {
00156     KNotifyDialog dialog( parent, name, true, aboutData );
00157     return dialog.exec();
00158 }
00159 
00160 KNotifyDialog::KNotifyDialog( QWidget *parent, const char *name, bool modal,
00161                               const KAboutData *aboutData )
00162     : KDialogBase(parent, name, modal, i18n("Notification Settings"),
00163                   Ok | Apply | Cancel | Default, Ok, true )
00164 {
00165     QVBox *box = makeVBoxMainWidget();
00166 
00167     m_notifyWidget = new KNotifyWidget( box, "knotify widget" );
00168 
00169     if ( aboutData )
00170         addApplicationEvents( aboutData->appName() );
00171 
00172     connect( this, SIGNAL( okClicked() ), m_notifyWidget, SLOT( save() ));
00173     connect( this, SIGNAL( applyClicked() ), m_notifyWidget, SLOT( save() ));
00174 }
00175 
00176 KNotifyDialog::~KNotifyDialog()
00177 {
00178 }
00179 
00180 void KNotifyDialog::addApplicationEvents( const char *appName )
00181 {
00182     addApplicationEvents( QString::fromUtf8( appName ) +
00183                           QString::fromLatin1( "/eventsrc" ) );
00184 }
00185 
00186 void KNotifyDialog::addApplicationEvents( const QString& path )
00187 {
00188     Application *app = m_notifyWidget->addApplicationEvents( path );
00189     if ( app )
00190     {
00191         m_notifyWidget->addVisibleApp( app );
00192         m_notifyWidget->sort();
00193     }
00194 }
00195 
00196 void KNotifyDialog::clearApplicationEvents()
00197 {
00198     m_notifyWidget->clear();
00199 }
00200 
00201 void KNotifyDialog::slotDefault()
00202 {
00203     m_notifyWidget->resetDefaults( true ); // ask user
00204 }
00205 
00206 
00209 
00210 
00211 class KNotifyWidget::Private
00212 {
00213 public:
00214     QPixmap pixmaps[6];
00215     KNotifyToolTip *toolTip;
00216 };
00217 
00218 // simple access to all knotify-handled applications
00219 KNotifyWidget::KNotifyWidget( QWidget *parent, const char *name,
00220                               bool handleAllApps )
00221     : KNotifyWidgetBase( parent, name ? name : "KNotifyWidget" )
00222 {
00223     d = new Private;
00224 
00225     m_allApps.setAutoDelete( true );
00226 
00227     if ( !handleAllApps )
00228     {
00229         m_affectAllApps->hide();
00230         m_playerButton->hide();
00231     }
00232 
00233     SelectionCombo::fill( m_comboEnable );
00234     SelectionCombo::fill( m_comboDisable );
00235 
00236     m_listview->setFullWidth( true );
00237     m_listview->setAllColumnsShowFocus( true );
00238 
00239     QPixmap pexec = SmallIcon("exec");
00240     QPixmap pstderr = SmallIcon("terminal");
00241     QPixmap pmessage = SmallIcon("info");
00242     QPixmap plogfile = SmallIcon("log");
00243     QPixmap psound = SmallIcon("sound");
00244     QPixmap ptaskbar = SmallIcon("kicker");
00245 
00246     d->pixmaps[COL_EXECUTE] = pexec;
00247     d->pixmaps[COL_STDERR]  = pstderr;
00248     d->pixmaps[COL_MESSAGE] = pmessage;
00249     d->pixmaps[COL_LOGFILE] = plogfile;
00250     d->pixmaps[COL_SOUND]   = psound;
00251     d->pixmaps[COL_TASKBAR] = ptaskbar;
00252 
00253     int w = KIcon::SizeSmall + 6;
00254 
00255     QHeader *header = m_listview->header();
00256     header->setLabel( COL_EXECUTE, pexec,    QString::null, w );
00257     header->setLabel( COL_STDERR,  pstderr,  QString::null, w );
00258     header->setLabel( COL_MESSAGE, pmessage, QString::null, w );
00259     header->setLabel( COL_LOGFILE, plogfile, QString::null, w );
00260     header->setLabel( COL_SOUND,   psound,   QString::null, w );
00261     header->setLabel( COL_TASKBAR, ptaskbar, QString::null, w );
00262 
00263     d->toolTip = new KNotifyToolTip( header );
00264 
00265     m_playButton->setPixmap( SmallIcon( "player_play" ) );
00266     connect( m_playButton, SIGNAL( clicked() ), SLOT( playSound() ));
00267 
00268     connect( m_listview, SIGNAL( currentChanged( QListViewItem * ) ),
00269              SLOT( slotEventChanged( QListViewItem * ) ));
00270     connect( m_listview, SIGNAL(clicked( QListViewItem *, const QPoint&, int)),
00271              SLOT( slotItemClicked( QListViewItem *, const QPoint&, int )));
00272 
00273     connect( m_playSound, SIGNAL( toggled( bool )),
00274              SLOT( soundToggled( bool )) );
00275     connect( m_logToFile, SIGNAL( toggled( bool )),
00276              SLOT( loggingToggled( bool )) );
00277     connect( m_execute, SIGNAL( toggled( bool )),
00278              SLOT( executeToggled( bool )) );
00279     connect( m_messageBox, SIGNAL( toggled( bool )),
00280              SLOT( messageBoxChanged() ) );
00281     connect( m_passivePopup, SIGNAL( toggled( bool )),
00282              SLOT( messageBoxChanged() ) );
00283     connect( m_stderr, SIGNAL( toggled( bool )),
00284              SLOT( stderrToggled( bool ) ) );
00285     connect( m_taskbar, SIGNAL( toggled( bool )),
00286              SLOT( taskbarToggled( bool ) ) );
00287 
00288     connect( m_soundPath, SIGNAL( textChanged( const QString& )),
00289              SLOT( soundFileChanged( const QString& )));
00290     connect( m_logfilePath, SIGNAL( textChanged( const QString& )),
00291              SLOT( logfileChanged( const QString& ) ));
00292     connect( m_executePath, SIGNAL( textChanged( const QString& )),
00293              SLOT( commandlineChanged( const QString& ) ));
00294 
00295     connect( m_soundPath, SIGNAL( openFileDialog( KURLRequester * )),
00296              SLOT( openSoundDialog( KURLRequester * )));
00297     connect( m_logfilePath, SIGNAL( openFileDialog( KURLRequester * )),
00298              SLOT( openLogDialog( KURLRequester * )));
00299     connect( m_executePath, SIGNAL( openFileDialog( KURLRequester * )),
00300              SLOT( openExecDialog( KURLRequester * )));
00301 
00302     connect( m_extension, SIGNAL( clicked() ),
00303              SLOT( toggleAdvanced()) );
00304 
00305     connect( m_buttonEnable, SIGNAL( clicked() ), SLOT( enableAll() ));
00306     connect( m_buttonDisable, SIGNAL( clicked() ), SLOT( enableAll() ));
00307 
00308     QString whatsThis = i18n("<qt>You may use the following macros<br>"
00309         "in the commandline:<br>"
00310         "<b>%e</b>: for the event name,<br>"
00311         "<b>%a</b>: for the name of the application that sent the event,<br>"
00312         "<b>%s</b>: for the notification message,<br>"
00313         "<b>%w</b>: for the numeric window ID where the event originated,<br>"
00314         "<b>%i</b>: for the numeric event ID.");
00315     QWhatsThis::add( m_execute, whatsThis );
00316     QWhatsThis::add( m_executePath, whatsThis );
00317     
00318     showAdvanced( false );
00319 
00320     slotEventChanged( 0L ); // disable widgets by default
00321 }
00322 
00323 KNotifyWidget::~KNotifyWidget()
00324 {
00325     delete d->toolTip;
00326     delete d;
00327 }
00328 
00329 void KNotifyWidget::toggleAdvanced()
00330 {
00331     showAdvanced( m_logToFile->isHidden() );
00332 }
00333 
00334 void KNotifyWidget::showAdvanced( bool show )
00335 {
00336     if ( show )
00337     {
00338         m_extension->setText( i18n("Fewer Op&tions") );
00339         QToolTip::add( m_extension, i18n("Hide advanced options") );
00340 
00341         m_logToFile->show();
00342         m_logfilePath->show();
00343         m_execute->show();
00344         m_executePath->show();
00345         m_messageBox->show();
00346         m_passivePopup->show();
00347         m_stderr->show();
00348         m_taskbar->show();
00349 
00350         m_actionsBoxLayout->setSpacing( KDialog::spacingHint() );
00351     }
00352     else
00353     {
00354         m_extension->setText( i18n("More Op&tions") );
00355         QToolTip::add( m_extension, i18n("Show advanced options") );
00356 
00357         m_logToFile->hide();
00358         m_logfilePath->hide();
00359         m_execute->hide();
00360         m_executePath->hide();
00361         m_messageBox->hide();
00362         m_passivePopup->hide();
00363         m_stderr->hide();
00364         m_taskbar->hide();
00365 
00366         m_actionsBoxLayout->setSpacing( 0 );
00367     }
00368 }
00369 
00370 Application * KNotifyWidget::addApplicationEvents( const QString& path )
00371 {
00372     kdDebug() << "**** knotify: adding path: " << path << endl;
00373     QString relativePath = path;
00374 
00375     if ( path.at(0) == '/' && KStandardDirs::exists( path ) )
00376         relativePath = makeRelative( path );
00377 
00378     if ( !relativePath.isEmpty() )
00379     {
00380         Application *app = new Application( relativePath );
00381         m_allApps.append( app );
00382         return app;
00383     }
00384 
00385     return 0L;
00386 }
00387 
00388 void KNotifyWidget::clear()
00389 {
00390     clearVisible();
00391     m_allApps.clear();
00392 }
00393 
00394 void KNotifyWidget::clearVisible()
00395 {
00396     m_visibleApps.clear();
00397     m_listview->clear();
00398     slotEventChanged( 0L ); // disable widgets
00399 }
00400 
00401 void KNotifyWidget::showEvent( QShowEvent *e )
00402 {
00403     selectItem( m_listview->firstChild() );
00404     KNotifyWidgetBase::showEvent( e );
00405 }
00406 
00407 void KNotifyWidget::slotEventChanged( QListViewItem *item )
00408 {
00409     bool on = (item != 0L);
00410 
00411     m_actionsBox->setEnabled( on );
00412     m_controlsBox->setEnabled( on );
00413 
00414     if ( !on )
00415         return;
00416 
00417     ListViewItem *lit = static_cast<ListViewItem*>( item );
00418     updateWidgets( lit );
00419 }
00420 
00421 void KNotifyWidget::updateWidgets( ListViewItem *item )
00422 {
00423     bool enable;
00424     bool checked;
00425 
00426     blockSignals( true ); // don't emit changed() signals
00427 
00428     const Event& event = item->event();
00429 
00430     // sound settings
00431     m_playButton->setEnabled( !event.soundfile.isEmpty() );
00432     m_soundPath->setURL( event.soundfile );
00433     enable = (event.dontShow & KNotifyClient::Sound) == 0;
00434     checked = enable && !event.soundfile.isEmpty() &&
00435               (event.presentation & KNotifyClient::Sound);
00436     m_playSound->setEnabled( enable );
00437     m_playSound->setChecked( checked );
00438     m_soundPath->setEnabled( checked );
00439 
00440 
00441     // logfile settings
00442     m_logfilePath->setURL( event.logfile );
00443     enable = (event.dontShow & KNotifyClient::Logfile) == 0;
00444     checked = enable && !event.logfile.isEmpty()  &&
00445               (event.presentation & KNotifyClient::Logfile);
00446     m_logToFile->setEnabled( enable );
00447     m_logToFile->setChecked( checked );
00448     m_logfilePath->setEnabled( checked );
00449 
00450 
00451     // execute program settings
00452     m_executePath->setURL( event.commandline );
00453     enable = (event.dontShow & KNotifyClient::Execute) == 0;
00454     checked = enable && !event.commandline.isEmpty() &&
00455               (event.presentation & KNotifyClient::Execute);
00456     m_execute->setEnabled( enable );
00457     m_execute->setChecked( checked );
00458     m_executePath->setEnabled( checked );
00459 
00460 
00461     // other settings
00462     m_messageBox->setChecked(event.presentation & (KNotifyClient::Messagebox | KNotifyClient::PassivePopup));
00463     enable = (event.dontShow & KNotifyClient::Messagebox) == 0;
00464     m_messageBox->setEnabled( enable );
00465 
00466     m_passivePopup->setChecked(event.presentation & KNotifyClient::PassivePopup);
00467     enable = (event.dontShow & KNotifyClient::PassivePopup) == 0;
00468     m_passivePopup->setEnabled( enable );
00469 
00470     m_stderr->setChecked( event.presentation & KNotifyClient::Stderr );
00471     enable = (event.dontShow & KNotifyClient::Stderr) == 0;
00472     m_stderr->setEnabled( enable );
00473 
00474     m_taskbar->setChecked(event.presentation & KNotifyClient::Taskbar);
00475     enable = (event.dontShow & KNotifyClient::Taskbar) == 0;
00476     m_taskbar->setEnabled( enable );
00477 
00478     updatePixmaps( item );
00479 
00480     blockSignals( false );
00481 }
00482 
00483 void KNotifyWidget::updatePixmaps( ListViewItem *item )
00484 {
00485     QPixmap emptyPix;
00486     Event &event = item->event();
00487 
00488     bool doIt = (event.presentation & KNotifyClient::Execute) &&
00489                 !event.commandline.isEmpty();
00490     item->setPixmap( COL_EXECUTE, doIt ? d->pixmaps[COL_EXECUTE] : emptyPix );
00491 
00492     doIt = (event.presentation & KNotifyClient::Sound) &&
00493            !event.soundfile.isEmpty();
00494     item->setPixmap( COL_SOUND, doIt ? d->pixmaps[COL_SOUND] : emptyPix );
00495 
00496     doIt = (event.presentation & KNotifyClient::Logfile) &&
00497            !event.logfile.isEmpty();
00498     item->setPixmap( COL_LOGFILE, doIt ? d->pixmaps[COL_LOGFILE] : emptyPix );
00499 
00500     item->setPixmap( COL_MESSAGE,
00501                      (event.presentation &
00502                       (KNotifyClient::Messagebox | KNotifyClient::PassivePopup)) ?
00503                      d->pixmaps[COL_MESSAGE] : emptyPix );
00504 
00505     item->setPixmap( COL_STDERR,
00506                      (event.presentation & KNotifyClient::Stderr) ?
00507                      d->pixmaps[COL_STDERR] : emptyPix );
00508     item->setPixmap( COL_TASKBAR,
00509                      (event.presentation & KNotifyClient::Taskbar) ?
00510                      d->pixmaps[COL_TASKBAR] : emptyPix );
00511 }
00512 
00513 void KNotifyWidget::addVisibleApp( Application *app )
00514 {
00515     if ( !app || (m_visibleApps.findRef( app ) != -1) )
00516         return;
00517 
00518     m_visibleApps.append( app );
00519     addToView( app->eventList() );
00520 
00521     QListViewItem *item = m_listview->selectedItem();
00522     if ( !item )
00523         item = m_listview->firstChild();
00524 
00525     selectItem( item );
00526 }
00527 
00528 void KNotifyWidget::addToView( const EventList& events )
00529 {
00530     ListViewItem *item = 0L;
00531 
00532     EventListIterator it( events );
00533 
00534     for ( ; it.current(); ++it )
00535     {
00536         Event *event = it.current();
00537         item = new ListViewItem( m_listview, event );
00538 
00539         if ( (event->presentation & KNotifyClient::Execute) &&
00540              !event->commandline.isEmpty() )
00541             item->setPixmap( COL_EXECUTE, d->pixmaps[COL_EXECUTE] );
00542         if ( (event->presentation & KNotifyClient::Sound) &&
00543              !event->soundfile.isEmpty() )
00544             item->setPixmap( COL_SOUND, d->pixmaps[COL_SOUND] );
00545         if ( (event->presentation & KNotifyClient::Logfile) &&
00546              !event->logfile.isEmpty() )
00547             item->setPixmap( COL_LOGFILE, d->pixmaps[COL_LOGFILE] );
00548         if ( event->presentation & (KNotifyClient::Messagebox|KNotifyClient::PassivePopup) )
00549             item->setPixmap( COL_MESSAGE, d->pixmaps[COL_MESSAGE] );
00550         if ( event->presentation & KNotifyClient::Stderr )
00551             item->setPixmap( COL_STDERR, d->pixmaps[COL_STDERR] );
00552         if ( event->presentation & KNotifyClient::Taskbar )
00553             item->setPixmap( COL_TASKBAR, d->pixmaps[COL_TASKBAR] );
00554     }
00555 }
00556 
00557 void KNotifyWidget::widgetChanged( QListViewItem *item,
00558                                    int what, bool on, QWidget *buddy )
00559 {
00560     if ( signalsBlocked() )
00561         return;
00562 
00563     if ( buddy )
00564         buddy->setEnabled( on );
00565 
00566     Event &e = static_cast<ListViewItem*>( item )->event();
00567     if ( on )
00568     {
00569         e.presentation |= what;
00570         if ( buddy )
00571             buddy->setFocus();
00572     }
00573     else
00574         e.presentation &= ~what;
00575 
00576     emit changed( true );
00577 }
00578 
00579 void KNotifyWidget::soundToggled( bool on )
00580 {
00581     QListViewItem *item = m_listview->currentItem();
00582     if ( !item )
00583         return;
00584     bool doIcon = on && !m_soundPath->url().isEmpty();
00585     item->setPixmap( COL_SOUND, doIcon ? d->pixmaps[COL_SOUND] : QPixmap() );
00586     widgetChanged( item, KNotifyClient::Sound, on, m_soundPath );
00587 }
00588 
00589 void KNotifyWidget::loggingToggled( bool on )
00590 {
00591     QListViewItem *item = m_listview->currentItem();
00592     if ( !item )
00593         return;
00594     bool doIcon = on && !m_logfilePath->url().isEmpty();
00595     item->setPixmap(COL_LOGFILE, doIcon ? d->pixmaps[COL_LOGFILE] : QPixmap());
00596     widgetChanged( item, KNotifyClient::Logfile, on, m_logfilePath );
00597 }
00598 
00599 void KNotifyWidget::executeToggled( bool on )
00600 {
00601     QListViewItem *item = m_listview->currentItem();
00602     if ( !item )
00603         return;
00604     bool doIcon = on && !m_executePath->url().isEmpty();
00605     item->setPixmap(COL_EXECUTE, doIcon ? d->pixmaps[COL_EXECUTE] : QPixmap());
00606     widgetChanged( item, KNotifyClient::Execute, on, m_executePath );
00607 }
00608 
00609 void KNotifyWidget::messageBoxChanged()
00610 {
00611     if ( signalsBlocked() )
00612         return;
00613 
00614     m_passivePopup->setEnabled( m_messageBox->isChecked() );
00615 
00616     QListViewItem *item = m_listview->currentItem();
00617     if ( !item )
00618         return;
00619 
00620     bool on = m_passivePopup->isEnabled();
00621     item->setPixmap( COL_MESSAGE, on ? d->pixmaps[COL_MESSAGE] : QPixmap() );
00622 
00623     Event &e = static_cast<ListViewItem*>( item )->event();
00624 
00625     if ( m_messageBox->isChecked() ) {
00626     if ( m_passivePopup->isChecked() ) {
00627         e.presentation |= KNotifyClient::PassivePopup;
00628         e.presentation &= ~KNotifyClient::Messagebox;
00629     }
00630     else {
00631         e.presentation &= ~KNotifyClient::PassivePopup;
00632         e.presentation |= KNotifyClient::Messagebox;
00633     }
00634     }
00635     else {
00636         e.presentation &= ~KNotifyClient::Messagebox;
00637         e.presentation &= ~KNotifyClient::PassivePopup;
00638     }
00639 
00640     emit changed( true );
00641 }
00642 
00643 void KNotifyWidget::stderrToggled( bool on )
00644 {
00645     QListViewItem *item = m_listview->currentItem();
00646     if ( !item )
00647         return;
00648     item->setPixmap( COL_STDERR, on ? d->pixmaps[COL_STDERR] : QPixmap() );
00649     widgetChanged( item, KNotifyClient::Stderr, on );
00650 }
00651 
00652 void KNotifyWidget::taskbarToggled( bool on )
00653 {
00654     QListViewItem *item = m_listview->currentItem();
00655     if ( !item )
00656         return;
00657     item->setPixmap( COL_TASKBAR, on ? d->pixmaps[COL_TASKBAR] : QPixmap() );
00658     widgetChanged( item, KNotifyClient::Taskbar, on );
00659 }
00660 
00661 void KNotifyWidget::soundFileChanged( const QString& text )
00662 {
00663     if ( signalsBlocked() )
00664         return;
00665 
00666     QListViewItem *item = m_listview->currentItem();
00667     if ( !item )
00668         return;
00669 
00670     m_playButton->setEnabled( !text.isEmpty() );
00671 
00672     currentEvent()->soundfile = text;
00673     bool ok = !text.isEmpty() && m_playSound->isChecked();
00674     item->setPixmap( COL_SOUND, ok ? d->pixmaps[COL_SOUND] : QPixmap() );
00675 
00676     emit changed( true );
00677 }
00678 
00679 void KNotifyWidget::logfileChanged( const QString& text )
00680 {
00681     if ( signalsBlocked() )
00682         return;
00683 
00684     QListViewItem *item = m_listview->currentItem();
00685     if ( !item )
00686         return;
00687 
00688     currentEvent()->logfile = text;
00689     bool ok = !text.isEmpty() && m_logToFile->isChecked();
00690     item->setPixmap( COL_LOGFILE, ok ? d->pixmaps[COL_LOGFILE] : QPixmap() );
00691 
00692     emit changed( true );
00693 }
00694 
00695 void KNotifyWidget::commandlineChanged( const QString& text )
00696 {
00697     if ( signalsBlocked() )
00698         return;
00699 
00700     QListViewItem *item = m_listview->currentItem();
00701     if ( !item )
00702         return;
00703 
00704     currentEvent()->commandline = text;
00705     bool ok = !text.isEmpty() && m_execute->isChecked();
00706     item->setPixmap( COL_EXECUTE, ok ? d->pixmaps[COL_EXECUTE] : QPixmap() );
00707 
00708     emit changed( true );
00709 }
00710 
00711 void KNotifyWidget::slotItemClicked( QListViewItem *item, const QPoint&,
00712                                      int col )
00713 {
00714     if ( !item || !item->isSelected() )
00715         return;
00716 
00717     Event *event = currentEvent();
00718     if ( !event )
00719         return; // very unlikely, but safety first
00720 
00721     bool doShowAdvanced = false;
00722 
00723     switch( col )
00724     {
00725         case COL_EXECUTE:
00726             m_execute->toggle();
00727             m_executePath->setFocus();
00728             doShowAdvanced = true;
00729             break;
00730         case COL_STDERR:
00731             m_stderr->toggle();
00732             break;
00733         case COL_TASKBAR:
00734             m_taskbar->toggle();
00735             break;
00736         case COL_MESSAGE:
00737             m_passivePopup->setChecked( true ); // default to passive popups
00738             m_messageBox->toggle();
00739             break;
00740         case COL_LOGFILE:
00741             m_logToFile->toggle();
00742             m_logfilePath->setFocus();
00743             doShowAdvanced = true;
00744             break;
00745         case COL_SOUND:
00746             m_playSound->toggle();
00747             break;
00748         default: // do nothing
00749             break;
00750     }
00751 
00752     if ( doShowAdvanced && !m_logToFile->isVisible() )
00753     {
00754         showAdvanced( true );
00755         m_listview->ensureItemVisible( m_listview->currentItem() );
00756     }
00757 }
00758 
00759 void KNotifyWidget::sort( bool ascending )
00760 {
00761     m_listview->setSorting( COL_EVENT, ascending );
00762     m_listview->sort();
00763 }
00764 
00765 void KNotifyWidget::selectItem( QListViewItem *item )
00766 {
00767     if ( item )
00768     {
00769         m_listview->setCurrentItem( item );
00770         item->setSelected( true );
00771         slotEventChanged( item );
00772     }
00773 }
00774 
00775 void KNotifyWidget::resetDefaults( bool ask )
00776 {
00777     if ( ask )
00778     {
00779         if ( KMessageBox::warningContinueCancel(this,
00780                                    i18n("This will cause the notifications "
00781                                         "to be reset to their defaults."),
00782                                                 i18n("Are You Sure?"),
00783                                                 i18n("&Reset"))
00784              != KMessageBox::Continue)
00785             return;
00786     }
00787 
00788     reload( true ); // defaults
00789     emit changed( true );
00790 }
00791 
00792 void KNotifyWidget::reload( bool revertToDefaults )
00793 {
00794     m_listview->clear();
00795     ApplicationListIterator it( m_visibleApps );
00796     for ( ; it.current(); ++it )
00797     {
00798         it.current()->reloadEvents( revertToDefaults );
00799         addToView( it.current()->eventList() );
00800     }
00801 
00802     m_listview->sort();
00803     selectItem( m_listview->firstChild()  );
00804 }
00805 
00806 void KNotifyWidget::save()
00807 {
00808     kdDebug() << "save\n";
00809 
00810     ApplicationListIterator it( m_allApps );
00811     while ( it.current() )
00812     {
00813         (*it)->save();
00814         ++it;
00815     }
00816 
00817     if ( kapp )
00818     {
00819         if ( !kapp->dcopClient()->isAttached() )
00820             kapp->dcopClient()->attach();
00821         kapp->dcopClient()->send("knotify", "", "reconfigure()", "");
00822     }
00823 
00824     emit changed( false );
00825 }
00826 
00827 // returns e.g. "kwin/eventsrc" from a given path
00828 // "/opt/kde3/share/apps/kwin/eventsrc"
00829 QString KNotifyWidget::makeRelative( const QString& fullPath )
00830 {
00831     int slash = fullPath.findRev( '/' ) - 1;
00832     slash = fullPath.findRev( '/', slash );
00833 
00834     if ( slash < 0 )
00835         return QString::null;
00836 
00837     return fullPath.mid( slash+1 );
00838 }
00839 
00840 Event * KNotifyWidget::currentEvent()
00841 {
00842     QListViewItem *current = m_listview->currentItem();
00843     if ( !current )
00844         return 0L;
00845 
00846     return &static_cast<ListViewItem*>( current )->event();
00847 }
00848 
00849 void KNotifyWidget::openSoundDialog( KURLRequester *requester )
00850 {
00851     // only need to init this once
00852     requester->disconnect( SIGNAL( openFileDialog( KURLRequester * )),
00853                            this, SLOT( openSoundDialog( KURLRequester * )));
00854 
00855     KFileDialog *fileDialog = requester->fileDialog();
00856     fileDialog->setCaption( i18n("Select Sound File") );
00857     QStringList filters;
00858     filters << "audio/x-wav" << "audio/x-mp3" << "application/ogg"
00859             << "audio/x-adpcm";
00860     fileDialog->setMimeFilter( filters );
00861 
00862     // find the first "sound"-resource that contains files
00863     const Application *app = currentEvent()->application();
00864     QStringList soundDirs =
00865         KGlobal::dirs()->findDirs("data", app->appName() + "/sounds");
00866     soundDirs += KGlobal::dirs()->resourceDirs( "sound" );
00867 
00868     if ( !soundDirs.isEmpty() ) {
00869         KURL soundURL;
00870         QDir dir;
00871         dir.setFilter( QDir::Files | QDir::Readable );
00872         QStringList::ConstIterator it = soundDirs.begin();
00873         while ( it != soundDirs.end() ) {
00874             dir = *it;
00875             if ( dir.isReadable() && dir.count() > 2 ) {
00876                 soundURL.setPath( *it );
00877                 fileDialog->setURL( soundURL );
00878                 break;
00879             }
00880             ++it;
00881         }
00882     }
00883 }
00884 
00885 void KNotifyWidget::openLogDialog( KURLRequester *requester )
00886 {
00887     // only need to init this once
00888     requester->disconnect( SIGNAL( openFileDialog( KURLRequester * )),
00889                            this, SLOT( openLogDialog( KURLRequester * )));
00890 
00891     KFileDialog *fileDialog = requester->fileDialog();
00892     fileDialog->setCaption( i18n("Select Log File") );
00893     QStringList filters;
00894     filters << "text/x-log" << "text/plain";
00895     fileDialog->setMimeFilter( filters );
00896 }
00897 
00898 void KNotifyWidget::openExecDialog( KURLRequester *requester )
00899 {
00900     // only need to init this once
00901     requester->disconnect( SIGNAL( openFileDialog( KURLRequester * )),
00902                            this, SLOT( openExecDialog( KURLRequester * )));
00903 
00904 
00905     KFileDialog *fileDialog = requester->fileDialog();
00906     fileDialog->setCaption( i18n("Select File to Execute") );
00907     QStringList filters;
00908     filters << "application/x-executable" << "application/x-shellscript"
00909             << "application/x-perl" << "application/x-python";
00910     fileDialog->setMimeFilter( filters );
00911 }
00912 
00913 void KNotifyWidget::playSound()
00914 {
00915     KAudioPlayer::play( m_soundPath->url() );
00916 }
00917 
00918 void KNotifyWidget::enableAll()
00919 {
00920     bool enable = (sender() == m_buttonEnable);
00921     enableAll( SelectionCombo::type(enable ? m_comboEnable : m_comboDisable),
00922                enable );
00923 }
00924 
00925 void KNotifyWidget::enableAll( int what, bool enable )
00926 {
00927     if ( m_listview->childCount() == 0 )
00928         return;
00929 
00930     bool affectAll = m_affectAllApps->isChecked(); // multi-apps mode
00931 
00932     ApplicationListIterator appIt( affectAll ? m_allApps : m_visibleApps );
00933     for ( ; appIt.current(); ++appIt )
00934     {
00935         const EventList& events = appIt.current()->eventList();
00936         EventListIterator it( events );
00937         for ( ; it.current(); ++it )
00938         {
00939             if ( enable )
00940                 it.current()->presentation |= what;
00941             else
00942                 it.current()->presentation &= ~what;
00943         }
00944     }
00945 
00946     // now make the listview reflect the changes
00947     QListViewItemIterator it( m_listview->firstChild() );
00948     for ( ; it.current(); ++it )
00949     {
00950         ListViewItem *item = static_cast<ListViewItem*>( it.current() );
00951         updatePixmaps( item );
00952     }
00953 
00954     QListViewItem *item = m_listview->currentItem();
00955     if ( !item )
00956         item = m_listview->firstChild();
00957     selectItem( item );
00958 
00959     emit changed( true );
00960 }
00961 
00962 
00965 
00966 
00967 //
00968 // path must be "appname/eventsrc", i.e. a relative path
00969 //
00970 Application::Application( const QString &path )
00971 {
00972     QString config_file = path;
00973     config_file[config_file.find('/')] = '.';
00974     m_events = 0L;
00975     config = new KConfig(config_file, false, false);
00976     kc = new KConfig(path, true, false, "data");
00977     kc->setGroup( QString::fromLatin1("!Global!") );
00978     m_icon = kc->readEntry(QString::fromLatin1("IconName"),
00979                            QString::fromLatin1("misc"));
00980     m_description = kc->readEntry( QString::fromLatin1("Comment"),
00981                                    i18n("No description available") );
00982 
00983     int index = path.find( '/' );
00984     if ( index >= 0 )
00985         m_appname = path.left( index );
00986     else
00987         kdDebug() << "Cannot determine application name from path: " << path << endl;
00988 }
00989 
00990 Application::~Application()
00991 {
00992     delete config;
00993     delete kc;
00994     delete m_events;
00995 }
00996 
00997 
00998 const EventList&  Application::eventList()
00999 {
01000     if ( !m_events ) {
01001         m_events = new EventList;
01002         m_events->setAutoDelete( true );
01003         reloadEvents();
01004     }
01005 
01006     return *m_events;
01007 }
01008 
01009 
01010 void Application::save()
01011 {
01012     if ( !m_events )
01013         return;
01014 
01015     EventListIterator it( *m_events );
01016     Event *e;
01017     while ( (e = it.current()) ) {
01018         config->setGroup( e->configGroup );
01019         config->writeEntry( "presentation", e->presentation );
01020         config->writePathEntry( "soundfile", e->soundfile );
01021         config->writePathEntry( "logfile", e->logfile );
01022         config->writePathEntry( "commandline", e->commandline );
01023 
01024         ++it;
01025     }
01026     config->sync();
01027 }
01028 
01029 
01030 void Application::reloadEvents( bool revertToDefaults )
01031 {
01032     if ( m_events )
01033         m_events->clear();
01034     else
01035     {
01036         m_events = new EventList;
01037         m_events->setAutoDelete( true );
01038     }
01039 
01040     Event *e = 0L;
01041 
01042     QString global = QString::fromLatin1("!Global!");
01043     QString default_group = QString::fromLatin1("<default>");
01044     QString name = QString::fromLatin1("Name");
01045     QString comment = QString::fromLatin1("Comment");
01046 
01047     QStringList conflist = kc->groupList();
01048     QStringList::ConstIterator it = conflist.begin();
01049 
01050     while ( it != conflist.end() ) {
01051         if ( (*it) != global && (*it) != default_group ) { // event group
01052             kc->setGroup( *it );
01053 
01054             e = new Event( this );
01055             e->name = kc->readEntry( name );
01056             e->description = kc->readEntry( comment );
01057             e->dontShow = kc->readNumEntry("nopresentation", 0 );
01058             e->configGroup = *it;
01059 
01060             if ( e->name.isEmpty() || e->description.isEmpty() )
01061                 delete e;
01062 
01063             else { // load the event
01064                 // default to passive popups over plain messageboxes
01065                 int default_rep = kc->readNumEntry("default_presentation",
01066                                                    0 | KNotifyClient::PassivePopup);
01067                 QString default_logfile = kc->readPathEntry("default_logfile");
01068                 QString default_soundfile = kc->readPathEntry("default_sound");
01069                 QString default_commandline = kc->readPathEntry("default_commandline");
01070 
01071                 config->setGroup(*it);
01072 
01073                 if ( revertToDefaults )
01074                 {
01075                     e->presentation = default_rep;
01076                     e->logfile = default_logfile;
01077                     e->soundfile = default_soundfile;
01078                     e->commandline = default_commandline;
01079                 }
01080 
01081                 else
01082                 {
01083                     e->presentation = config->readNumEntry("presentation",
01084                                                            default_rep);
01085                     e->logfile = config->readPathEntry("logfile",
01086                                                    default_logfile);
01087                     e->soundfile = config->readPathEntry("soundfile",
01088                                                      default_soundfile);
01089                     e->commandline = config->readPathEntry("commandline",
01090                                                        default_commandline);
01091                 }
01092 
01093                 m_events->append( e );
01094             }
01095         }
01096 
01097         ++it;
01098     }
01099 
01100     return;
01101 }
01102 
01105 
01106 ListViewItem::ListViewItem( QListView *view, Event *event )
01107     : QListViewItem( view ),
01108       m_event( event )
01109 {
01110     setText( COL_EVENT, event->text() );
01111 }
01112 
01113 int ListViewItem::compare ( QListViewItem * i, int col, bool ascending ) const
01114 {
01115     ListViewItem *item = static_cast<ListViewItem*>( i );
01116     int myPres = m_event->presentation;
01117     int otherPres = item->event().presentation;
01118 
01119     int action = 0;
01120 
01121     switch ( col )
01122     {
01123         case COL_EVENT: // use default sorting
01124             return QListViewItem::compare( i, col, ascending );
01125 
01126         case COL_EXECUTE:
01127             action = KNotifyClient::Execute;
01128             break;
01129         case COL_LOGFILE:
01130             action = KNotifyClient::Logfile;
01131             break;
01132         case COL_MESSAGE:
01133             action = (KNotifyClient::Messagebox | KNotifyClient::PassivePopup);
01134             break;
01135         case COL_SOUND:
01136             action = KNotifyClient::Sound;
01137             break;
01138         case COL_STDERR:
01139             action = KNotifyClient::Stderr;
01140             break;
01141         case COL_TASKBAR:
01142             action = KNotifyClient::Taskbar;
01143             break;
01144     }
01145 
01146     if ( (myPres & action) == (otherPres & action) )
01147     {
01148         // default sorting by event
01149         return QListViewItem::compare( i, COL_EVENT, true );
01150     }
01151 
01152     if ( myPres & action )
01153         return -1;
01154     if ( otherPres & action )
01155         return 1;
01156 
01157     return 0;
01158 }
01159 
01160 #include "knotifydialog.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Nov 27 13:45:30 2004 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003