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