diff options
Diffstat (limited to 'kio/kfile/knotifydialog.cpp')
-rw-r--r-- | kio/kfile/knotifydialog.cpp | 1191 |
1 files changed, 1191 insertions, 0 deletions
diff --git a/kio/kfile/knotifydialog.cpp b/kio/kfile/knotifydialog.cpp new file mode 100644 index 000000000..6543344e2 --- /dev/null +++ b/kio/kfile/knotifydialog.cpp @@ -0,0 +1,1191 @@ +/* + Copyright (C) 2000,2002 Carsten Pfeiffer <pfeiffer@kde.org> + Copyright (C) 2002 Neil Stevens <neil@qualityassistant.com> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation; + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library, If not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <dcopclient.h> + +#include <kaboutdata.h> +#include <kapplication.h> +#include <kaudioplayer.h> +#include <kcombobox.h> +#include <kconfig.h> +#include <kcursor.h> +#include <kdebug.h> +#include <kfiledialog.h> +#include <kiconloader.h> +#include <kicontheme.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <knotifyclient.h> +#include <knotifydialog.h> +#include <kstandarddirs.h> +#include <kurlrequester.h> +#include <kio/netaccess.h> + +#include <qcheckbox.h> +#include <qgroupbox.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlistview.h> +#include <qlayout.h> +#include <qptrlist.h> +#include <qpushbutton.h> +#include <qstring.h> +#include <qtooltip.h> +#include <qtimer.h> +#include <qvbox.h> +#include <qwhatsthis.h> + +using namespace KNotify; + +enum +{ + COL_EXECUTE = 0, + COL_STDERR = 1, + COL_MESSAGE = 2, + COL_LOGFILE = 3, + COL_SOUND = 4, + COL_TASKBAR = 5, + COL_EVENT = 6 +}; + +// +// I don't feel like subclassing KComboBox and find ways to insert that into +// the .ui file... +// +namespace KNotify +{ + class SelectionCombo + { + public: + // + // Mind the order in fill() and type() + // + static void fill( KComboBox *combo ) + { + combo->insertItem( i18n("Sounds") ); + combo->insertItem( i18n("Logging") ); + combo->insertItem( i18n("Program Execution") ); + combo->insertItem( i18n("Message Windows") ); + combo->insertItem( i18n("Passive Windows") ); + combo->insertItem( i18n("Standard Error Output") ); + combo->insertItem( i18n("Taskbar") ); + } + + static int type( KComboBox *combo ) + { + switch( combo->currentItem() ) + { + case 0: + return KNotifyClient::Sound; + case 1: + return KNotifyClient::Logfile; + case 2: + return KNotifyClient::Execute; + case 3: + return KNotifyClient::Messagebox; + case 4: + return KNotifyClient::PassivePopup; + case 5: + return KNotifyClient::Stderr; + case 6: + return KNotifyClient::Taskbar; + } + + return KNotifyClient::None; + } + }; + + // Needed for displaying tooltips in the listview's QHeader + class KNotifyToolTip : public QToolTip + { + public: + KNotifyToolTip( QHeader *header ) + : QToolTip( header ) + { + m_tips[COL_EXECUTE] = i18n("Execute a program"); + m_tips[COL_STDERR] = i18n("Print to Standard error output"); + m_tips[COL_MESSAGE] = i18n("Display a messagebox"); + m_tips[COL_LOGFILE] = i18n("Log to a file"); + m_tips[COL_SOUND] = i18n("Play a sound"); + m_tips[COL_TASKBAR] = i18n("Flash the taskbar entry"); + } + virtual ~KNotifyToolTip() {} + + protected: + virtual void maybeTip ( const QPoint& p ) + { + QHeader *header = static_cast<QHeader*>( parentWidget() ); + int section = 0; + + if ( header->orientation() == Horizontal ) + section= header->sectionAt( p.x() ); + else + section= header->sectionAt( p.y() ); + + if ( ( section < 0 ) || ( static_cast<uint>( section ) >= (sizeof(m_tips) / sizeof(QString)) ) ) + return; + + tip( header->sectionRect( section ), m_tips[section] ); + } + + private: + QString m_tips[6]; + }; + +} + + +int KNotifyDialog::configure( QWidget *parent, const char *name, + const KAboutData *aboutData ) +{ + KNotifyDialog dialog( parent, name, true, aboutData ); + return dialog.exec(); +} + +KNotifyDialog::KNotifyDialog( QWidget *parent, const char *name, bool modal, + const KAboutData *aboutData ) + : KDialogBase(parent, name, modal, i18n("Notification Settings"), + Ok | Apply | Cancel | Default, Ok, true ) +{ + QVBox *box = makeVBoxMainWidget(); + + m_notifyWidget = new KNotifyWidget( box, "knotify widget" ); + + if ( aboutData ) + addApplicationEvents( aboutData->appName() ); + + connect( this, SIGNAL( okClicked() ), m_notifyWidget, SLOT( save() )); + connect( this, SIGNAL( applyClicked() ), m_notifyWidget, SLOT( save() )); +} + +KNotifyDialog::~KNotifyDialog() +{ +} + +void KNotifyDialog::addApplicationEvents( const char *appName ) +{ + addApplicationEvents( QString::fromUtf8( appName ) + + QString::fromLatin1( "/eventsrc" ) ); +} + +void KNotifyDialog::addApplicationEvents( const QString& path ) +{ + Application *app = m_notifyWidget->addApplicationEvents( path ); + if ( app ) + { + m_notifyWidget->addVisibleApp( app ); + m_notifyWidget->sort(); + } +} + +void KNotifyDialog::clearApplicationEvents() +{ + m_notifyWidget->clear(); +} + +void KNotifyDialog::slotDefault() +{ + m_notifyWidget->resetDefaults( true ); // ask user +} + + +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// + + +class KNotifyWidget::Private +{ +public: + QPixmap pixmaps[6]; + KNotifyToolTip *toolTip; +}; + +// simple access to all knotify-handled applications +KNotifyWidget::KNotifyWidget( QWidget *parent, const char *name, + bool handleAllApps ) + : KNotifyWidgetBase( parent, name ? name : "KNotifyWidget" ) +{ + d = new Private; + + m_allApps.setAutoDelete( true ); + + if ( !handleAllApps ) + { + m_affectAllApps->hide(); + m_playerButton->hide(); + } + + SelectionCombo::fill( m_comboEnable ); + SelectionCombo::fill( m_comboDisable ); + + m_listview->setFullWidth( true ); + m_listview->setAllColumnsShowFocus( true ); + + QPixmap pexec = SmallIcon("exec"); + QPixmap pstderr = SmallIcon("terminal"); + QPixmap pmessage = SmallIcon("info"); + QPixmap plogfile = SmallIcon("log"); + QPixmap psound = SmallIcon("sound"); + QPixmap ptaskbar = SmallIcon("kicker"); + + d->pixmaps[COL_EXECUTE] = pexec; + d->pixmaps[COL_STDERR] = pstderr; + d->pixmaps[COL_MESSAGE] = pmessage; + d->pixmaps[COL_LOGFILE] = plogfile; + d->pixmaps[COL_SOUND] = psound; + d->pixmaps[COL_TASKBAR] = ptaskbar; + + int w = KIcon::SizeSmall + 6; + + QHeader *header = m_listview->header(); + header->setLabel( COL_EXECUTE, pexec, QString::null, w ); + header->setLabel( COL_STDERR, pstderr, QString::null, w ); + header->setLabel( COL_MESSAGE, pmessage, QString::null, w ); + header->setLabel( COL_LOGFILE, plogfile, QString::null, w ); + header->setLabel( COL_SOUND, psound, QString::null, w ); + header->setLabel( COL_TASKBAR, ptaskbar, QString::null, w ); + + d->toolTip = new KNotifyToolTip( header ); + + m_playButton->setIconSet( SmallIconSet( "player_play" ) ); + connect( m_playButton, SIGNAL( clicked() ), SLOT( playSound() )); + + connect( m_listview, SIGNAL( currentChanged( QListViewItem * ) ), + SLOT( slotEventChanged( QListViewItem * ) )); + connect( m_listview, SIGNAL(clicked( QListViewItem *, const QPoint&, int)), + SLOT( slotItemClicked( QListViewItem *, const QPoint&, int ))); + + connect( m_playSound, SIGNAL( toggled( bool )), + SLOT( soundToggled( bool )) ); + connect( m_logToFile, SIGNAL( toggled( bool )), + SLOT( loggingToggled( bool )) ); + connect( m_execute, SIGNAL( toggled( bool )), + SLOT( executeToggled( bool )) ); + connect( m_messageBox, SIGNAL( toggled( bool )), + SLOT( messageBoxChanged() ) ); + connect( m_passivePopup, SIGNAL( toggled( bool )), + SLOT( messageBoxChanged() ) ); + connect( m_stderr, SIGNAL( toggled( bool )), + SLOT( stderrToggled( bool ) ) ); + connect( m_taskbar, SIGNAL( toggled( bool )), + SLOT( taskbarToggled( bool ) ) ); + + connect( m_soundPath, SIGNAL( textChanged( const QString& )), + SLOT( soundFileChanged( const QString& ))); + connect( m_logfilePath, SIGNAL( textChanged( const QString& )), + SLOT( logfileChanged( const QString& ) )); + connect( m_executePath, SIGNAL( textChanged( const QString& )), + SLOT( commandlineChanged( const QString& ) )); + + connect( m_soundPath, SIGNAL( openFileDialog( KURLRequester * )), + SLOT( openSoundDialog( KURLRequester * ))); + connect( m_logfilePath, SIGNAL( openFileDialog( KURLRequester * )), + SLOT( openLogDialog( KURLRequester * ))); + connect( m_executePath, SIGNAL( openFileDialog( KURLRequester * )), + SLOT( openExecDialog( KURLRequester * ))); + + connect( m_extension, SIGNAL( clicked() ), + SLOT( toggleAdvanced()) ); + + connect( m_buttonEnable, SIGNAL( clicked() ), SLOT( enableAll() )); + connect( m_buttonDisable, SIGNAL( clicked() ), SLOT( enableAll() )); + + QString whatsThis = i18n("<qt>You may use the following macros<br>" + "in the commandline:<br>" + "<b>%e</b>: for the event name,<br>" + "<b>%a</b>: for the name of the application that sent the event,<br>" + "<b>%s</b>: for the notification message,<br>" + "<b>%w</b>: for the numeric window ID where the event originated,<br>" + "<b>%i</b>: for the numeric event ID."); + QWhatsThis::add( m_execute, whatsThis ); + QWhatsThis::add( m_executePath, whatsThis ); + + showAdvanced( false ); + + slotEventChanged( 0L ); // disable widgets by default +} + +KNotifyWidget::~KNotifyWidget() +{ + delete d->toolTip; + delete d; +} + +void KNotifyWidget::toggleAdvanced() +{ + showAdvanced( m_logToFile->isHidden() ); +} + +void KNotifyWidget::showAdvanced( bool show ) +{ + if ( show ) + { + m_extension->setText( i18n("Advanced <<") ); + QToolTip::add( m_extension, i18n("Hide advanced options") ); + + m_logToFile->show(); + m_logfilePath->show(); + m_execute->show(); + m_executePath->show(); + m_messageBox->show(); + m_passivePopup->show(); + m_stderr->show(); + m_taskbar->show(); + + m_passivePopup->setEnabled( m_messageBox->isChecked() ); + m_actionsBoxLayout->setSpacing( KDialog::spacingHint() ); + } + else + { + m_extension->setText( i18n("Advanced >>") ); + QToolTip::add( m_extension, i18n("Show advanced options") ); + + m_logToFile->hide(); + m_logfilePath->hide(); + m_execute->hide(); + m_executePath->hide(); + m_messageBox->hide(); + m_passivePopup->hide(); + m_stderr->hide(); + m_taskbar->hide(); + + m_actionsBoxLayout->setSpacing( 0 ); + } +} + +Application * KNotifyWidget::addApplicationEvents( const QString& path ) +{ + kdDebug() << "**** knotify: adding path: " << path << endl; + QString relativePath = path; + + if ( path.at(0) == '/' && KStandardDirs::exists( path ) ) + relativePath = makeRelative( path ); + + if ( !relativePath.isEmpty() ) + { + Application *app = new Application( relativePath ); + m_allApps.append( app ); + return app; + } + + return 0L; +} + +void KNotifyWidget::clear() +{ + clearVisible(); + m_allApps.clear(); +} + +void KNotifyWidget::clearVisible() +{ + m_visibleApps.clear(); + m_listview->clear(); + slotEventChanged( 0L ); // disable widgets +} + +void KNotifyWidget::showEvent( QShowEvent *e ) +{ + selectItem( m_listview->firstChild() ); + KNotifyWidgetBase::showEvent( e ); +} + +void KNotifyWidget::slotEventChanged( QListViewItem *item ) +{ + bool on = (item != 0L); + + m_actionsBox->setEnabled( on ); + m_controlsBox->setEnabled( on ); + + if ( !on ) + return; + + ListViewItem *lit = static_cast<ListViewItem*>( item ); + updateWidgets( lit ); +} + +void KNotifyWidget::updateWidgets( ListViewItem *item ) +{ + bool enable; + bool checked; + + blockSignals( true ); // don't emit changed() signals + + const Event& event = item->event(); + + // sound settings + m_playButton->setEnabled( !event.soundfile.isEmpty() ); + m_soundPath->setURL( event.soundfile ); + enable = (event.dontShow & KNotifyClient::Sound) == 0; + checked = enable && !event.soundfile.isEmpty() && + (event.presentation & KNotifyClient::Sound); + m_playSound->setEnabled( enable ); + m_playSound->setChecked( checked ); + m_soundPath->setEnabled( checked ); + + + // logfile settings + m_logfilePath->setURL( event.logfile ); + enable = (event.dontShow & KNotifyClient::Logfile) == 0; + checked = enable && !event.logfile.isEmpty() && + (event.presentation & KNotifyClient::Logfile); + m_logToFile->setEnabled( enable ); + m_logToFile->setChecked( checked ); + m_logfilePath->setEnabled( checked ); + + + // execute program settings + m_executePath->setURL( event.commandline ); + enable = (event.dontShow & KNotifyClient::Execute) == 0; + checked = enable && !event.commandline.isEmpty() && + (event.presentation & KNotifyClient::Execute); + m_execute->setEnabled( enable ); + m_execute->setChecked( checked ); + m_executePath->setEnabled( checked ); + + + // other settings + m_messageBox->setChecked(event.presentation & (KNotifyClient::Messagebox | KNotifyClient::PassivePopup)); + enable = (event.dontShow & KNotifyClient::Messagebox) == 0; + m_messageBox->setEnabled( enable ); + + m_passivePopup->setChecked(event.presentation & KNotifyClient::PassivePopup); + enable = (event.dontShow & KNotifyClient::PassivePopup) == 0; + m_passivePopup->setEnabled( enable ); + + m_stderr->setChecked( event.presentation & KNotifyClient::Stderr ); + enable = (event.dontShow & KNotifyClient::Stderr) == 0; + m_stderr->setEnabled( enable ); + + m_taskbar->setChecked(event.presentation & KNotifyClient::Taskbar); + enable = (event.dontShow & KNotifyClient::Taskbar) == 0; + m_taskbar->setEnabled( enable ); + + updatePixmaps( item ); + + blockSignals( false ); +} + +void KNotifyWidget::updatePixmaps( ListViewItem *item ) +{ + QPixmap emptyPix; + Event &event = item->event(); + + bool doIt = (event.presentation & KNotifyClient::Execute) && + !event.commandline.isEmpty(); + item->setPixmap( COL_EXECUTE, doIt ? d->pixmaps[COL_EXECUTE] : emptyPix ); + + doIt = (event.presentation & KNotifyClient::Sound) && + !event.soundfile.isEmpty(); + item->setPixmap( COL_SOUND, doIt ? d->pixmaps[COL_SOUND] : emptyPix ); + + doIt = (event.presentation & KNotifyClient::Logfile) && + !event.logfile.isEmpty(); + item->setPixmap( COL_LOGFILE, doIt ? d->pixmaps[COL_LOGFILE] : emptyPix ); + + item->setPixmap( COL_MESSAGE, + (event.presentation & + (KNotifyClient::Messagebox | KNotifyClient::PassivePopup)) ? + d->pixmaps[COL_MESSAGE] : emptyPix ); + + item->setPixmap( COL_STDERR, + (event.presentation & KNotifyClient::Stderr) ? + d->pixmaps[COL_STDERR] : emptyPix ); + item->setPixmap( COL_TASKBAR, + (event.presentation & KNotifyClient::Taskbar) ? + d->pixmaps[COL_TASKBAR] : emptyPix ); +} + +void KNotifyWidget::addVisibleApp( Application *app ) +{ + if ( !app || (m_visibleApps.findRef( app ) != -1) ) + return; + + m_visibleApps.append( app ); + addToView( app->eventList() ); + + QListViewItem *item = m_listview->selectedItem(); + if ( !item ) + item = m_listview->firstChild(); + + selectItem( item ); +} + +void KNotifyWidget::addToView( const EventList& events ) +{ + ListViewItem *item = 0L; + + EventListIterator it( events ); + + for ( ; it.current(); ++it ) + { + Event *event = it.current(); + item = new ListViewItem( m_listview, event ); + + if ( (event->presentation & KNotifyClient::Execute) && + !event->commandline.isEmpty() ) + item->setPixmap( COL_EXECUTE, d->pixmaps[COL_EXECUTE] ); + if ( (event->presentation & KNotifyClient::Sound) && + !event->soundfile.isEmpty() ) + item->setPixmap( COL_SOUND, d->pixmaps[COL_SOUND] ); + if ( (event->presentation & KNotifyClient::Logfile) && + !event->logfile.isEmpty() ) + item->setPixmap( COL_LOGFILE, d->pixmaps[COL_LOGFILE] ); + if ( event->presentation & (KNotifyClient::Messagebox|KNotifyClient::PassivePopup) ) + item->setPixmap( COL_MESSAGE, d->pixmaps[COL_MESSAGE] ); + if ( event->presentation & KNotifyClient::Stderr ) + item->setPixmap( COL_STDERR, d->pixmaps[COL_STDERR] ); + if ( event->presentation & KNotifyClient::Taskbar ) + item->setPixmap( COL_TASKBAR, d->pixmaps[COL_TASKBAR] ); + } +} + +void KNotifyWidget::widgetChanged( QListViewItem *item, + int what, bool on, QWidget *buddy ) +{ + if ( signalsBlocked() ) + return; + + if ( buddy ) + buddy->setEnabled( on ); + + Event &e = static_cast<ListViewItem*>( item )->event(); + if ( on ) + { + e.presentation |= what; + if ( buddy ) + buddy->setFocus(); + } + else + e.presentation &= ~what; + + emit changed( true ); +} + +void KNotifyWidget::soundToggled( bool on ) +{ + QListViewItem *item = m_listview->currentItem(); + if ( !item ) + return; + bool doIcon = on && !m_soundPath->url().isEmpty(); + item->setPixmap( COL_SOUND, doIcon ? d->pixmaps[COL_SOUND] : QPixmap() ); + widgetChanged( item, KNotifyClient::Sound, on, m_soundPath ); +} + +void KNotifyWidget::loggingToggled( bool on ) +{ + QListViewItem *item = m_listview->currentItem(); + if ( !item ) + return; + bool doIcon = on && !m_logfilePath->url().isEmpty(); + item->setPixmap(COL_LOGFILE, doIcon ? d->pixmaps[COL_LOGFILE] : QPixmap()); + widgetChanged( item, KNotifyClient::Logfile, on, m_logfilePath ); +} + +void KNotifyWidget::executeToggled( bool on ) +{ + QListViewItem *item = m_listview->currentItem(); + if ( !item ) + return; + bool doIcon = on && !m_executePath->url().isEmpty(); + item->setPixmap(COL_EXECUTE, doIcon ? d->pixmaps[COL_EXECUTE] : QPixmap()); + widgetChanged( item, KNotifyClient::Execute, on, m_executePath ); +} + +void KNotifyWidget::messageBoxChanged() +{ + if ( signalsBlocked() ) + return; + + m_passivePopup->setEnabled( m_messageBox->isChecked() ); + + QListViewItem *item = m_listview->currentItem(); + if ( !item ) + return; + + bool on = m_passivePopup->isEnabled(); + item->setPixmap( COL_MESSAGE, on ? d->pixmaps[COL_MESSAGE] : QPixmap() ); + + Event &e = static_cast<ListViewItem*>( item )->event(); + + if ( m_messageBox->isChecked() ) { + if ( m_passivePopup->isChecked() ) { + e.presentation |= KNotifyClient::PassivePopup; + e.presentation &= ~KNotifyClient::Messagebox; + } + else { + e.presentation &= ~KNotifyClient::PassivePopup; + e.presentation |= KNotifyClient::Messagebox; + } + } + else { + e.presentation &= ~KNotifyClient::Messagebox; + e.presentation &= ~KNotifyClient::PassivePopup; + } + + emit changed( true ); +} + +void KNotifyWidget::stderrToggled( bool on ) +{ + QListViewItem *item = m_listview->currentItem(); + if ( !item ) + return; + item->setPixmap( COL_STDERR, on ? d->pixmaps[COL_STDERR] : QPixmap() ); + widgetChanged( item, KNotifyClient::Stderr, on ); +} + +void KNotifyWidget::taskbarToggled( bool on ) +{ + QListViewItem *item = m_listview->currentItem(); + if ( !item ) + return; + item->setPixmap( COL_TASKBAR, on ? d->pixmaps[COL_TASKBAR] : QPixmap() ); + widgetChanged( item, KNotifyClient::Taskbar, on ); +} + +void KNotifyWidget::soundFileChanged( const QString& text ) +{ + if ( signalsBlocked() ) + return; + + QListViewItem *item = m_listview->currentItem(); + if ( !item ) + return; + + m_playButton->setEnabled( !text.isEmpty() ); + + currentEvent()->soundfile = text; + bool ok = !text.isEmpty() && m_playSound->isChecked(); + item->setPixmap( COL_SOUND, ok ? d->pixmaps[COL_SOUND] : QPixmap() ); + + emit changed( true ); +} + +void KNotifyWidget::logfileChanged( const QString& text ) +{ + if ( signalsBlocked() ) + return; + + QListViewItem *item = m_listview->currentItem(); + if ( !item ) + return; + + currentEvent()->logfile = text; + bool ok = !text.isEmpty() && m_logToFile->isChecked(); + item->setPixmap( COL_LOGFILE, ok ? d->pixmaps[COL_LOGFILE] : QPixmap() ); + + emit changed( true ); +} + +void KNotifyWidget::commandlineChanged( const QString& text ) +{ + if ( signalsBlocked() ) + return; + + QListViewItem *item = m_listview->currentItem(); + if ( !item ) + return; + + currentEvent()->commandline = text; + bool ok = !text.isEmpty() && m_execute->isChecked(); + item->setPixmap( COL_EXECUTE, ok ? d->pixmaps[COL_EXECUTE] : QPixmap() ); + + emit changed( true ); +} + +void KNotifyWidget::slotItemClicked( QListViewItem *item, const QPoint&, + int col ) +{ + if ( !item || !item->isSelected() ) + return; + + Event *event = currentEvent(); + if ( !event ) + return; // very unlikely, but safety first + + bool doShowAdvanced = false; + + switch( col ) + { + case COL_EXECUTE: + m_execute->toggle(); + m_executePath->setFocus(); + doShowAdvanced = true; + break; + case COL_STDERR: + m_stderr->toggle(); + break; + case COL_TASKBAR: + m_taskbar->toggle(); + break; + case COL_MESSAGE: + m_passivePopup->setChecked( true ); // default to passive popups + m_messageBox->toggle(); + break; + case COL_LOGFILE: + m_logToFile->toggle(); + m_logfilePath->setFocus(); + doShowAdvanced = true; + break; + case COL_SOUND: + m_playSound->toggle(); + break; + default: // do nothing + break; + } + + if ( doShowAdvanced && !m_logToFile->isVisible() ) + { + showAdvanced( true ); + m_listview->ensureItemVisible( m_listview->currentItem() ); + } +} + +void KNotifyWidget::sort( bool ascending ) +{ + m_listview->setSorting( COL_EVENT, ascending ); + m_listview->sort(); +} + +void KNotifyWidget::selectItem( QListViewItem *item ) +{ + if ( item ) + { + m_listview->setCurrentItem( item ); + item->setSelected( true ); + slotEventChanged( item ); + } +} + +void KNotifyWidget::resetDefaults( bool ask ) +{ + if ( ask ) + { + if ( KMessageBox::warningContinueCancel(this, + i18n("This will cause the notifications " + "to be reset to their defaults."), + i18n("Are You Sure?"), + i18n("&Reset")) + != KMessageBox::Continue) + return; + } + + reload( true ); // defaults + emit changed( true ); +} + +void KNotifyWidget::reload( bool revertToDefaults ) +{ + m_listview->clear(); + ApplicationListIterator it( m_visibleApps ); + for ( ; it.current(); ++it ) + { + it.current()->reloadEvents( revertToDefaults ); + addToView( it.current()->eventList() ); + } + + m_listview->sort(); + selectItem( m_listview->firstChild() ); +} + +void KNotifyWidget::save() +{ + kdDebug() << "save\n"; + + ApplicationListIterator it( m_allApps ); + while ( it.current() ) + { + (*it)->save(); + ++it; + } + + if ( kapp ) + { + if ( !kapp->dcopClient()->isAttached() ) + kapp->dcopClient()->attach(); + kapp->dcopClient()->send("knotify", "", "reconfigure()", ""); + } + + emit changed( false ); +} + +// returns e.g. "kwin/eventsrc" from a given path +// "/opt/kde3/share/apps/kwin/eventsrc" +QString KNotifyWidget::makeRelative( const QString& fullPath ) +{ + int slash = fullPath.findRev( '/' ) - 1; + slash = fullPath.findRev( '/', slash ); + + if ( slash < 0 ) + return QString::null; + + return fullPath.mid( slash+1 ); +} + +Event * KNotifyWidget::currentEvent() +{ + QListViewItem *current = m_listview->currentItem(); + if ( !current ) + return 0L; + + return &static_cast<ListViewItem*>( current )->event(); +} + +void KNotifyWidget::openSoundDialog( KURLRequester *requester ) +{ + // only need to init this once + requester->disconnect( SIGNAL( openFileDialog( KURLRequester * )), + this, SLOT( openSoundDialog( KURLRequester * ))); + + KFileDialog *fileDialog = requester->fileDialog(); + fileDialog->setCaption( i18n("Select Sound File") ); + QStringList filters; + filters << "audio/x-wav" << "audio/x-mp3" << "application/ogg" + << "audio/x-adpcm"; + fileDialog->setMimeFilter( filters ); + + // find the first "sound"-resource that contains files + const Application *app = currentEvent()->application(); + QStringList soundDirs = + KGlobal::dirs()->findDirs("data", app->appName() + "/sounds"); + soundDirs += KGlobal::dirs()->resourceDirs( "sound" ); + + if ( !soundDirs.isEmpty() ) { + KURL soundURL; + QDir dir; + dir.setFilter( QDir::Files | QDir::Readable ); + QStringList::ConstIterator it = soundDirs.begin(); + while ( it != soundDirs.end() ) { + dir = *it; + if ( dir.isReadable() && dir.count() > 2 ) { + soundURL.setPath( *it ); + fileDialog->setURL( soundURL ); + break; + } + ++it; + } + } +} + +void KNotifyWidget::openLogDialog( KURLRequester *requester ) +{ + // only need to init this once + requester->disconnect( SIGNAL( openFileDialog( KURLRequester * )), + this, SLOT( openLogDialog( KURLRequester * ))); + + KFileDialog *fileDialog = requester->fileDialog(); + fileDialog->setCaption( i18n("Select Log File") ); + QStringList filters; + filters << "text/x-log" << "text/plain"; + fileDialog->setMimeFilter( filters ); +} + +void KNotifyWidget::openExecDialog( KURLRequester *requester ) +{ + // only need to init this once + requester->disconnect( SIGNAL( openFileDialog( KURLRequester * )), + this, SLOT( openExecDialog( KURLRequester * ))); + + + KFileDialog *fileDialog = requester->fileDialog(); + fileDialog->setCaption( i18n("Select File to Execute") ); + QStringList filters; + filters << "application/x-executable" << "application/x-shellscript" + << "application/x-perl" << "application/x-python"; + fileDialog->setMimeFilter( filters ); +} + +void KNotifyWidget::playSound() +{ + QString soundPath = m_soundPath->url(); + if (!KIO::NetAccess::exists( m_soundPath->url(), true, 0 )) { + bool foundSound=false; + + // find the first "sound"-resource that contains files + const Application *app = currentEvent()->application(); + QStringList soundDirs = KGlobal::dirs()->findDirs("data", app->appName() + "/sounds"); + soundDirs += KGlobal::dirs()->resourceDirs( "sound" ); + + if ( !soundDirs.isEmpty() ) { + QDir dir; + dir.setFilter( QDir::Files | QDir::Readable ); + QStringList::ConstIterator it = soundDirs.begin(); + while ( it != soundDirs.end() ) { + dir = *it; + if ( dir.isReadable() && dir.count() > 2 && + KIO::NetAccess::exists( *it + m_soundPath->url(), true, 0 )) { + foundSound=true; + soundPath = *it + m_soundPath->url(); + break; + } + ++it; + } + } + if ( !foundSound ) { + KMessageBox::sorry(this, i18n("The specified file does not exist." )); + return; + } + } + KAudioPlayer::play( soundPath ); +} + +void KNotifyWidget::enableAll() +{ + bool enable = (sender() == m_buttonEnable); + enableAll( SelectionCombo::type(enable ? m_comboEnable : m_comboDisable), + enable ); +} + +void KNotifyWidget::enableAll( int what, bool enable ) +{ + if ( m_listview->childCount() == 0 ) + return; + + bool affectAll = m_affectAllApps->isChecked(); // multi-apps mode + + ApplicationListIterator appIt( affectAll ? m_allApps : m_visibleApps ); + for ( ; appIt.current(); ++appIt ) + { + const EventList& events = appIt.current()->eventList(); + EventListIterator it( events ); + for ( ; it.current(); ++it ) + { + if ( enable ) + it.current()->presentation |= what; + else + it.current()->presentation &= ~what; + } + } + + // now make the listview reflect the changes + QListViewItemIterator it( m_listview->firstChild() ); + for ( ; it.current(); ++it ) + { + ListViewItem *item = static_cast<ListViewItem*>( it.current() ); + updatePixmaps( item ); + } + + QListViewItem *item = m_listview->currentItem(); + if ( !item ) + item = m_listview->firstChild(); + selectItem( item ); + + emit changed( true ); +} + + +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// + + +// +// path must be "appname/eventsrc", i.e. a relative path +// +Application::Application( const QString &path ) +{ + QString config_file = path; + config_file[config_file.find('/')] = '.'; + m_events = 0L; + config = new KConfig(config_file, false, false); + kc = new KConfig(path, true, false, "data"); + kc->setGroup( QString::fromLatin1("!Global!") ); + m_icon = kc->readEntry(QString::fromLatin1("IconName"), + QString::fromLatin1("misc")); + m_description = kc->readEntry( QString::fromLatin1("Comment"), + i18n("No description available") ); + + int index = path.find( '/' ); + if ( index >= 0 ) + m_appname = path.left( index ); + else + kdDebug() << "Cannot determine application name from path: " << path << endl; +} + +Application::~Application() +{ + delete config; + delete kc; + delete m_events; +} + + +const EventList& Application::eventList() +{ + if ( !m_events ) { + m_events = new EventList; + m_events->setAutoDelete( true ); + reloadEvents(); + } + + return *m_events; +} + + +void Application::save() +{ + if ( !m_events ) + return; + + EventListIterator it( *m_events ); + Event *e; + while ( (e = it.current()) ) { + config->setGroup( e->configGroup ); + config->writeEntry( "presentation", e->presentation ); + config->writePathEntry( "soundfile", e->soundfile ); + config->writePathEntry( "logfile", e->logfile ); + config->writePathEntry( "commandline", e->commandline ); + + ++it; + } + config->sync(); +} + + +void Application::reloadEvents( bool revertToDefaults ) +{ + if ( m_events ) + m_events->clear(); + else + { + m_events = new EventList; + m_events->setAutoDelete( true ); + } + + Event *e = 0L; + + QString global = QString::fromLatin1("!Global!"); + QString default_group = QString::fromLatin1("<default>"); + QString name = QString::fromLatin1("Name"); + QString comment = QString::fromLatin1("Comment"); + + QStringList conflist = kc->groupList(); + QStringList::ConstIterator it = conflist.begin(); + + while ( it != conflist.end() ) { + if ( (*it) != global && (*it) != default_group ) { // event group + kc->setGroup( *it ); + + e = new Event( this ); + e->name = kc->readEntry( name ); + e->description = kc->readEntry( comment ); + e->dontShow = kc->readNumEntry("nopresentation", 0 ); + e->configGroup = *it; + if ( e->name.isEmpty() && e->description.isEmpty() ) + delete e; + else { // load the event + if( !e->name.isEmpty() && e->description.isEmpty() ) + e->description = e->name; + // default to passive popups over plain messageboxes + int default_rep = kc->readNumEntry("default_presentation", + 0 | KNotifyClient::PassivePopup); + QString default_logfile = kc->readPathEntry("default_logfile"); + QString default_soundfile = kc->readPathEntry("default_sound"); + QString default_commandline = kc->readPathEntry("default_commandline"); + + config->setGroup(*it); + + if ( revertToDefaults ) + { + e->presentation = default_rep; + e->logfile = default_logfile; + e->soundfile = default_soundfile; + e->commandline = default_commandline; + } + + else + { + e->presentation = config->readNumEntry("presentation", + default_rep); + e->logfile = config->readPathEntry("logfile", + default_logfile); + e->soundfile = config->readPathEntry("soundfile", + default_soundfile); + e->commandline = config->readPathEntry("commandline", + default_commandline); + } + + m_events->append( e ); + } + } + + ++it; + } + + return; +} + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + +ListViewItem::ListViewItem( QListView *view, Event *event ) + : QListViewItem( view ), + m_event( event ) +{ + setText( COL_EVENT, event->text() ); +} + +int ListViewItem::compare ( QListViewItem * i, int col, bool ascending ) const +{ + ListViewItem *item = static_cast<ListViewItem*>( i ); + int myPres = m_event->presentation; + int otherPres = item->event().presentation; + + int action = 0; + + switch ( col ) + { + case COL_EVENT: // use default sorting + return QListViewItem::compare( i, col, ascending ); + + case COL_EXECUTE: + action = KNotifyClient::Execute; + break; + case COL_LOGFILE: + action = KNotifyClient::Logfile; + break; + case COL_MESSAGE: + action = (KNotifyClient::Messagebox | KNotifyClient::PassivePopup); + break; + case COL_SOUND: + action = KNotifyClient::Sound; + break; + case COL_STDERR: + action = KNotifyClient::Stderr; + break; + case COL_TASKBAR: + action = KNotifyClient::Taskbar; + break; + } + + if ( (myPres & action) == (otherPres & action) ) + { + // default sorting by event + return QListViewItem::compare( i, COL_EVENT, true ); + } + + if ( myPres & action ) + return -1; + if ( otherPres & action ) + return 1; + + return 0; +} + +#include "knotifydialog.moc" |