less Q3 (remove a lot of unused Q3 headers, port small things)
[kdenetwork.git] / kopete / libkopete / knotifydialog.cpp
blobd5370d0a1d67b4498f49046209a44f8cb599a67e
1 /*
2 Copyright (C) 2000,2002 Carsten Pfeiffer <pfeiffer@kde.org>
3 Copyright (C) 2002 Neil Stevens <neil@qualityassistant.com>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation;
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library, If not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include <dcopclient.h>
21 #include <kaboutdata.h>
22 #include <kapplication.h>
23 #include <kaudioplayer.h>
24 #include <kcombobox.h>
25 #include <kconfig.h>
26 #include <kcursor.h>
27 #include <kdebug.h>
28 #include <kfiledialog.h>
29 #include <kiconloader.h>
30 #include <kicontheme.h>
31 #include <klineedit.h>
32 #include <klocale.h>
33 #include <kmessagebox.h>
34 #include <knotifyclient.h>
35 #include <knotifydialog.h>
36 #include <kstandarddirs.h>
37 #include <kurlrequester.h>
38 #include <kio/netaccess.h>
40 #include "knotification.h"
42 #include <qcheckbox.h>
43 #include <qlabel.h>
44 #include <qlayout.h>
45 #include <qpushbutton.h>
46 #include <qstring.h>
47 #include <qtooltip.h>
48 #include <qtimer.h>
49 #include <kvbox.h>
50 #include <QHelpEvent>
51 #include <QMetaEnum>
53 using namespace KNotify;
55 enum
57 COL_EXECUTE = 0,
58 COL_STDERR = 1,
59 COL_MESSAGE = 2,
60 COL_LOGFILE = 3,
61 COL_SOUND = 4,
62 COL_TASKBAR = 5,
63 COL_EVENT = 6
67 // I don't feel like subclassing KComboBox and find ways to insert that into
68 // the .ui file...
70 namespace KNotify
72 class SelectionCombo
74 public:
76 // Mind the order in fill() and type()
78 static void fill( KComboBox *combo )
80 combo->addItem( i18n("Sounds") );
81 combo->addItem( i18n("Logging") );
82 combo->addItem( i18n("Program Execution") );
83 combo->addItem( i18n("Message Windows") );
84 combo->addItem( i18n("Passive Windows") );
85 combo->addItem( i18n("Standard Error Output") );
86 combo->addItem( i18n("Taskbar") );
89 static int type( KComboBox *combo )
91 switch( combo->currentIndex() )
93 case 0:
94 return KNotifyClient::Sound;
95 case 1:
96 return KNotifyClient::Logfile;
97 case 2:
98 return KNotifyClient::Execute;
99 case 3:
100 return KNotifyClient::Messagebox;
101 case 4:
102 return KNotifyClient::PassivePopup;
103 case 5:
104 return KNotifyClient::Stderr;
105 case 6:
106 return KNotifyClient::Taskbar;
109 return KNotifyClient::None;
117 int KNotifyDialog::configure( QWidget *parent, const char *name,
118 const KAboutData *aboutData )
120 KNotifyDialog dialog( parent, name, true, aboutData );
121 return dialog.exec();
124 KNotifyDialog::KNotifyDialog( QWidget *parent, const char *name, bool modal,
125 const KAboutData *aboutData )
126 : KDialogBase(parent, name, modal, i18n("Notification Settings"),
127 Ok | Apply | Cancel | Default, Ok, true )
129 KVBox *box = makeVBoxMainWidget();
131 m_notifyWidget = new KNotifyWidget( box, "knotify widget" );
133 if ( aboutData )
134 addApplicationEvents( aboutData->appName() );
136 connect( this, SIGNAL( okClicked() ), m_notifyWidget, SLOT( save() ));
137 connect( this, SIGNAL( applyClicked() ), m_notifyWidget, SLOT( save() ));
140 KNotifyDialog::~KNotifyDialog()
144 void KNotifyDialog::addApplicationEvents( const char *appName )
146 addApplicationEvents( QString::fromUtf8( appName ) +
147 QLatin1String( "/eventsrc" ) );
150 void KNotifyDialog::addApplicationEvents( const QString& path )
152 Application *app = m_notifyWidget->addApplicationEvents( path );
153 if ( app )
155 m_notifyWidget->addVisibleApp( app );
156 m_notifyWidget->sort();
160 void KNotifyDialog::clearApplicationEvents()
162 m_notifyWidget->clear();
165 void KNotifyDialog::slotDefault()
167 m_notifyWidget->resetDefaults( true ); // ask user
171 //////////////////////////////////////////////////////////////////////
172 //////////////////////////////////////////////////////////////////////
175 class KNotifyWidget::Private
177 public:
178 QPixmap pixmaps[6];
179 QString tips [6];
180 Q3Header* header;
183 // simple access to all knotify-handled applications
184 KNotifyWidget::KNotifyWidget( QWidget *parent, const char *name,
185 bool handleAllApps )
186 : KNotifyWidgetBase( parent, name ? name : "KNotifyWidget" )
188 d = new Private;
190 m_allApps.setAutoDelete( true );
192 if ( !handleAllApps )
194 m_affectAllApps->hide();
195 m_playerButton->hide();
198 SelectionCombo::fill( m_comboEnable );
199 SelectionCombo::fill( m_comboDisable );
201 m_listview->setFullWidth( true );
202 m_listview->setAllColumnsShowFocus( true );
204 QPixmap pexec = SmallIcon("exec");
205 QPixmap pstderr = SmallIcon("terminal");
206 QPixmap pmessage = SmallIcon("info");
207 QPixmap plogfile = SmallIcon("log");
208 QPixmap psound = SmallIcon("sound");
209 QPixmap ptaskbar = SmallIcon("kicker");
211 d->pixmaps[COL_EXECUTE] = pexec;
212 d->pixmaps[COL_STDERR] = pstderr;
213 d->pixmaps[COL_MESSAGE] = pmessage;
214 d->pixmaps[COL_LOGFILE] = plogfile;
215 d->pixmaps[COL_SOUND] = psound;
216 d->pixmaps[COL_TASKBAR] = ptaskbar;
218 int w = KIcon::SizeSmall + 6;
220 Q3Header *header = m_listview->header();
221 d->header = header;
222 header->setLabel( COL_EXECUTE, pexec, QString::null, w );
223 header->setLabel( COL_STDERR, pstderr, QString::null, w );
224 header->setLabel( COL_MESSAGE, pmessage, QString::null, w );
225 header->setLabel( COL_LOGFILE, plogfile, QString::null, w );
226 header->setLabel( COL_SOUND, psound, QString::null, w );
227 header->setLabel( COL_TASKBAR, ptaskbar, QString::null, w );
229 header->installEventFilter( this );
230 d->tips[COL_EXECUTE] = i18n("Execute a program");
231 d->tips[COL_STDERR] = i18n("Print to Standard error output");
232 d->tips[COL_MESSAGE] = i18n("Display a messagebox");
233 d->tips[COL_LOGFILE] = i18n("Log to a file");
234 d->tips[COL_SOUND] = i18n("Play a sound");
235 d->tips[COL_TASKBAR] = i18n("Flash the taskbar entry");
238 m_playButton->setIcon( SmallIconSet( "player_play" ) );
239 connect( m_playButton, SIGNAL( clicked() ), SLOT( playSound() ));
241 connect( m_listview, SIGNAL( currentChanged( Q3ListViewItem * ) ),
242 SLOT( slotEventChanged( Q3ListViewItem * ) ));
243 connect( m_listview, SIGNAL(clicked( Q3ListViewItem *, const QPoint&, int)),
244 SLOT( slotItemClicked( Q3ListViewItem *, const QPoint&, int )));
246 connect( m_playSound, SIGNAL( toggled( bool )),
247 SLOT( soundToggled( bool )) );
248 connect( m_logToFile, SIGNAL( toggled( bool )),
249 SLOT( loggingToggled( bool )) );
250 connect( m_execute, SIGNAL( toggled( bool )),
251 SLOT( executeToggled( bool )) );
252 connect( m_messageBox, SIGNAL( toggled( bool )),
253 SLOT( messageBoxChanged() ) );
254 connect( m_passivePopup, SIGNAL( toggled( bool )),
255 SLOT( messageBoxChanged() ) );
256 connect( m_stderr, SIGNAL( toggled( bool )),
257 SLOT( stderrToggled( bool ) ) );
258 connect( m_taskbar, SIGNAL( toggled( bool )),
259 SLOT( taskbarToggled( bool ) ) );
261 connect( m_soundPath, SIGNAL( textChanged( const QString& )),
262 SLOT( soundFileChanged( const QString& )));
263 connect( m_logfilePath, SIGNAL( textChanged( const QString& )),
264 SLOT( logfileChanged( const QString& ) ));
265 connect( m_executePath, SIGNAL( textChanged( const QString& )),
266 SLOT( commandlineChanged( const QString& ) ));
268 connect( m_soundPath, SIGNAL( openFileDialog( KURLRequester * )),
269 SLOT( openSoundDialog( KURLRequester * )));
270 connect( m_logfilePath, SIGNAL( openFileDialog( KURLRequester * )),
271 SLOT( openLogDialog( KURLRequester * )));
272 connect( m_executePath, SIGNAL( openFileDialog( KURLRequester * )),
273 SLOT( openExecDialog( KURLRequester * )));
275 connect( m_extension, SIGNAL( clicked() ),
276 SLOT( toggleAdvanced()) );
278 connect( m_buttonEnable, SIGNAL( clicked() ), SLOT( enableAll() ));
279 connect( m_buttonDisable, SIGNAL( clicked() ), SLOT( enableAll() ));
281 QString whatsThis = i18n("<qt>You may use the following macros<br>"
282 "in the commandline:<br>"
283 "<b>%e</b>: for the event name,<br>"
284 "<b>%a</b>: for the name of the application that sent the event,<br>"
285 "<b>%s</b>: for the notification message,<br>"
286 "<b>%w</b>: for the numeric window ID where the event originated,<br>"
287 "<b>%i</b>: for the numeric event ID.");
288 m_execute->setWhatsThis(whatsThis );
289 m_executePath->setWhatsThis(whatsThis );
291 showAdvanced( false );
293 slotEventChanged( 0L ); // disable widgets by default
296 KNotifyWidget::~KNotifyWidget()
298 delete d;
301 void KNotifyWidget::toggleAdvanced()
303 showAdvanced( m_logToFile->isHidden() );
306 void KNotifyWidget::showAdvanced( bool show )
308 if ( show )
310 m_extension->setText( i18n("Advanced <<") );
311 m_extension->setToolTip( i18n("Hide advanced options") );
313 m_logToFile->show();
314 m_logfilePath->show();
315 m_execute->show();
316 m_executePath->show();
317 m_messageBox->show();
318 m_passivePopup->show();
319 m_stderr->show();
320 m_taskbar->show();
322 m_passivePopup->setEnabled( m_messageBox->isChecked() );
323 m_actionsBox->layout()->setSpacing( KDialog::spacingHint() );
325 else
327 m_extension->setText( i18n("Advanced >>") );
328 m_extension->setToolTip( i18n("Show advanced options") );
330 m_logToFile->hide();
331 m_logfilePath->hide();
332 m_execute->hide();
333 m_executePath->hide();
334 m_messageBox->hide();
335 m_passivePopup->hide();
336 m_stderr->hide();
337 m_taskbar->hide();
339 m_actionsBox->layout()->setSpacing( 0 );
343 Application * KNotifyWidget::addApplicationEvents( const QString& path )
345 kdDebug() << "**** knotify: adding path: " << path << endl;
346 QString relativePath = path;
348 if ( path.at(0) == '/' && KStandardDirs::exists( path ) )
349 relativePath = makeRelative( path );
351 if ( !relativePath.isEmpty() )
353 Application *app = new Application( relativePath );
354 m_allApps.append( app );
355 return app;
358 return 0L;
361 void KNotifyWidget::clear()
363 clearVisible();
364 m_allApps.clear();
367 void KNotifyWidget::clearVisible()
369 m_visibleApps.clear();
370 m_listview->clear();
371 slotEventChanged( 0L ); // disable widgets
374 bool KNotifyWidget::eventFilter( QObject * watched, QEvent * event )
376 if ( watched == d->header && event->type() == QEvent::ToolTip)
378 QHelpEvent* he = static_cast<QHelpEvent*>(event);
379 int section = 0;
381 if ( d->header->orientation() == Qt::Horizontal )
382 section= d->header->sectionAt( he->pos().x() );
383 else
384 section= d->header->sectionAt( he->pos().y() );
386 if ( ( section < 0 ) || ( static_cast<uint>( section ) >= (sizeof(d->tips) / sizeof(QString)) ) )
387 return true;
389 QToolTip::showText( d->header->sectionRect( section ).bottomLeft(), d->tips[section],
390 d->header );
392 return true;
395 return KNotifyWidgetBase::eventFilter(watched, event);
398 void KNotifyWidget::showEvent( QShowEvent *e )
400 selectItem( m_listview->firstChild() );
401 KNotifyWidgetBase::showEvent( e );
404 void KNotifyWidget::slotEventChanged( Q3ListViewItem *item )
406 bool on = (item != 0L);
408 m_actionsBox->setEnabled( on );
409 m_controlsBox->setEnabled( on );
411 if ( !on )
412 return;
414 ListViewItem *lit = static_cast<ListViewItem*>( item );
415 updateWidgets( lit );
418 void KNotifyWidget::updateWidgets( ListViewItem *item )
420 bool enable;
421 bool checked;
423 blockSignals( true ); // don't emit changed() signals
425 const Event& event = item->event();
427 // sound settings
428 m_playButton->setEnabled( !event.soundfile.isEmpty() );
429 m_soundPath->setURL( event.soundfile );
430 enable = (event.dontShow & KNotifyClient::Sound) == 0;
431 checked = enable && !event.soundfile.isEmpty() &&
432 (event.presentation & KNotifyClient::Sound);
433 m_playSound->setEnabled( enable );
434 m_playSound->setChecked( checked );
435 m_soundPath->setEnabled( checked );
438 // logfile settings
439 m_logfilePath->setURL( event.logfile );
440 enable = (event.dontShow & KNotifyClient::Logfile) == 0;
441 checked = enable && !event.logfile.isEmpty() &&
442 (event.presentation & KNotifyClient::Logfile);
443 m_logToFile->setEnabled( enable );
444 m_logToFile->setChecked( checked );
445 m_logfilePath->setEnabled( checked );
448 // execute program settings
449 m_executePath->setURL( event.commandline );
450 enable = (event.dontShow & KNotifyClient::Execute) == 0;
451 checked = enable && !event.commandline.isEmpty() &&
452 (event.presentation & KNotifyClient::Execute);
453 m_execute->setEnabled( enable );
454 m_execute->setChecked( checked );
455 m_executePath->setEnabled( checked );
458 // other settings
459 m_messageBox->setChecked(event.presentation & (KNotifyClient::Messagebox | KNotifyClient::PassivePopup));
460 enable = (event.dontShow & KNotifyClient::Messagebox) == 0;
461 m_messageBox->setEnabled( enable );
463 m_passivePopup->setChecked(event.presentation & KNotifyClient::PassivePopup);
464 enable = (event.dontShow & KNotifyClient::PassivePopup) == 0;
465 m_passivePopup->setEnabled( enable );
467 m_stderr->setChecked( event.presentation & KNotifyClient::Stderr );
468 enable = (event.dontShow & KNotifyClient::Stderr) == 0;
469 m_stderr->setEnabled( enable );
471 m_taskbar->setChecked(event.presentation & KNotifyClient::Taskbar);
472 enable = (event.dontShow & KNotifyClient::Taskbar) == 0;
473 m_taskbar->setEnabled( enable );
475 updatePixmaps( item );
477 blockSignals( false );
480 void KNotifyWidget::updatePixmaps( ListViewItem *item )
482 QPixmap emptyPix;
483 Event &event = item->event();
485 bool doIt = (event.presentation & KNotifyClient::Execute) &&
486 !event.commandline.isEmpty();
487 item->setPixmap( COL_EXECUTE, doIt ? d->pixmaps[COL_EXECUTE] : emptyPix );
489 doIt = (event.presentation & KNotifyClient::Sound) &&
490 !event.soundfile.isEmpty();
491 item->setPixmap( COL_SOUND, doIt ? d->pixmaps[COL_SOUND] : emptyPix );
493 doIt = (event.presentation & KNotifyClient::Logfile) &&
494 !event.logfile.isEmpty();
495 item->setPixmap( COL_LOGFILE, doIt ? d->pixmaps[COL_LOGFILE] : emptyPix );
497 item->setPixmap( COL_MESSAGE,
498 (event.presentation &
499 (KNotifyClient::Messagebox | KNotifyClient::PassivePopup)) ?
500 d->pixmaps[COL_MESSAGE] : emptyPix );
502 item->setPixmap( COL_STDERR,
503 (event.presentation & KNotifyClient::Stderr) ?
504 d->pixmaps[COL_STDERR] : emptyPix );
505 item->setPixmap( COL_TASKBAR,
506 (event.presentation & KNotifyClient::Taskbar) ?
507 d->pixmaps[COL_TASKBAR] : emptyPix );
510 void KNotifyWidget::addVisibleApp( Application *app )
512 if ( !app || (m_visibleApps.findRef( app ) != -1) )
513 return;
515 m_visibleApps.append( app );
516 addToView( app->eventList() );
518 Q3ListViewItem *item = m_listview->selectedItem();
519 if ( !item )
520 item = m_listview->firstChild();
522 selectItem( item );
525 void KNotifyWidget::addToView( const EventList& events )
527 ListViewItem *item = 0L;
529 EventListIterator it( events );
531 for ( ; it.current(); ++it )
533 Event *event = it.current();
534 item = new ListViewItem( m_listview, event );
536 if ( (event->presentation & KNotifyClient::Execute) &&
537 !event->commandline.isEmpty() )
538 item->setPixmap( COL_EXECUTE, d->pixmaps[COL_EXECUTE] );
539 if ( (event->presentation & KNotifyClient::Sound) &&
540 !event->soundfile.isEmpty() )
541 item->setPixmap( COL_SOUND, d->pixmaps[COL_SOUND] );
542 if ( (event->presentation & KNotifyClient::Logfile) &&
543 !event->logfile.isEmpty() )
544 item->setPixmap( COL_LOGFILE, d->pixmaps[COL_LOGFILE] );
545 if ( event->presentation & (KNotifyClient::Messagebox|KNotifyClient::PassivePopup) )
546 item->setPixmap( COL_MESSAGE, d->pixmaps[COL_MESSAGE] );
547 if ( event->presentation & KNotifyClient::Stderr )
548 item->setPixmap( COL_STDERR, d->pixmaps[COL_STDERR] );
549 if ( event->presentation & KNotifyClient::Taskbar )
550 item->setPixmap( COL_TASKBAR, d->pixmaps[COL_TASKBAR] );
554 void KNotifyWidget::widgetChanged( Q3ListViewItem *item,
555 int what, bool on, QWidget *buddy )
557 if ( signalsBlocked() )
558 return;
560 if ( buddy )
561 buddy->setEnabled( on );
563 Event &e = static_cast<ListViewItem*>( item )->event();
564 if ( on )
566 e.presentation |= what;
567 if ( buddy )
568 buddy->setFocus();
570 else
571 e.presentation &= ~what;
573 emit changed( true );
576 void KNotifyWidget::soundToggled( bool on )
578 Q3ListViewItem *item = m_listview->currentItem();
579 if ( !item )
580 return;
581 bool doIcon = on && !m_soundPath->url().isEmpty();
582 item->setPixmap( COL_SOUND, doIcon ? d->pixmaps[COL_SOUND] : QPixmap() );
583 widgetChanged( item, KNotifyClient::Sound, on, m_soundPath );
586 void KNotifyWidget::loggingToggled( bool on )
588 Q3ListViewItem *item = m_listview->currentItem();
589 if ( !item )
590 return;
591 bool doIcon = on && !m_logfilePath->url().isEmpty();
592 item->setPixmap(COL_LOGFILE, doIcon ? d->pixmaps[COL_LOGFILE] : QPixmap());
593 widgetChanged( item, KNotifyClient::Logfile, on, m_logfilePath );
596 void KNotifyWidget::executeToggled( bool on )
598 Q3ListViewItem *item = m_listview->currentItem();
599 if ( !item )
600 return;
601 bool doIcon = on && !m_executePath->url().isEmpty();
602 item->setPixmap(COL_EXECUTE, doIcon ? d->pixmaps[COL_EXECUTE] : QPixmap());
603 widgetChanged( item, KNotifyClient::Execute, on, m_executePath );
606 void KNotifyWidget::messageBoxChanged()
608 if ( signalsBlocked() )
609 return;
611 m_passivePopup->setEnabled( m_messageBox->isChecked() );
613 Q3ListViewItem *item = m_listview->currentItem();
614 if ( !item )
615 return;
617 bool on = m_passivePopup->isEnabled();
618 item->setPixmap( COL_MESSAGE, on ? d->pixmaps[COL_MESSAGE] : QPixmap() );
620 Event &e = static_cast<ListViewItem*>( item )->event();
622 if ( m_messageBox->isChecked() ) {
623 if ( m_passivePopup->isChecked() ) {
624 e.presentation |= KNotifyClient::PassivePopup;
625 e.presentation &= ~KNotifyClient::Messagebox;
627 else {
628 e.presentation &= ~KNotifyClient::PassivePopup;
629 e.presentation |= KNotifyClient::Messagebox;
632 else {
633 e.presentation &= ~KNotifyClient::Messagebox;
634 e.presentation &= ~KNotifyClient::PassivePopup;
637 emit changed( true );
640 void KNotifyWidget::stderrToggled( bool on )
642 Q3ListViewItem *item = m_listview->currentItem();
643 if ( !item )
644 return;
645 item->setPixmap( COL_STDERR, on ? d->pixmaps[COL_STDERR] : QPixmap() );
646 widgetChanged( item, KNotifyClient::Stderr, on );
649 void KNotifyWidget::taskbarToggled( bool on )
651 Q3ListViewItem *item = m_listview->currentItem();
652 if ( !item )
653 return;
654 item->setPixmap( COL_TASKBAR, on ? d->pixmaps[COL_TASKBAR] : QPixmap() );
655 widgetChanged( item, KNotifyClient::Taskbar, on );
658 void KNotifyWidget::soundFileChanged( const QString& text )
660 if ( signalsBlocked() )
661 return;
663 Q3ListViewItem *item = m_listview->currentItem();
664 if ( !item )
665 return;
667 m_playButton->setEnabled( !text.isEmpty() );
669 currentEvent()->soundfile = text;
670 bool ok = !text.isEmpty() && m_playSound->isChecked();
671 item->setPixmap( COL_SOUND, ok ? d->pixmaps[COL_SOUND] : QPixmap() );
673 emit changed( true );
676 void KNotifyWidget::logfileChanged( const QString& text )
678 if ( signalsBlocked() )
679 return;
681 Q3ListViewItem *item = m_listview->currentItem();
682 if ( !item )
683 return;
685 currentEvent()->logfile = text;
686 bool ok = !text.isEmpty() && m_logToFile->isChecked();
687 item->setPixmap( COL_LOGFILE, ok ? d->pixmaps[COL_LOGFILE] : QPixmap() );
689 emit changed( true );
692 void KNotifyWidget::commandlineChanged( const QString& text )
694 if ( signalsBlocked() )
695 return;
697 Q3ListViewItem *item = m_listview->currentItem();
698 if ( !item )
699 return;
701 currentEvent()->commandline = text;
702 bool ok = !text.isEmpty() && m_execute->isChecked();
703 item->setPixmap( COL_EXECUTE, ok ? d->pixmaps[COL_EXECUTE] : QPixmap() );
705 emit changed( true );
708 void KNotifyWidget::slotItemClicked( Q3ListViewItem *item, const QPoint&,
709 int col )
711 if ( !item || !item->isSelected() )
712 return;
714 Event *event = currentEvent();
715 if ( !event )
716 return; // very unlikely, but safety first
718 bool doShowAdvanced = false;
720 switch( col )
722 case COL_EXECUTE:
723 m_execute->toggle();
724 m_executePath->setFocus();
725 doShowAdvanced = true;
726 break;
727 case COL_STDERR:
728 m_stderr->toggle();
729 break;
730 case COL_TASKBAR:
731 m_taskbar->toggle();
732 break;
733 case COL_MESSAGE:
734 m_passivePopup->setChecked( true ); // default to passive popups
735 m_messageBox->toggle();
736 break;
737 case COL_LOGFILE:
738 m_logToFile->toggle();
739 m_logfilePath->setFocus();
740 doShowAdvanced = true;
741 break;
742 case COL_SOUND:
743 m_playSound->toggle();
744 break;
745 default: // do nothing
746 break;
749 if ( doShowAdvanced && !m_logToFile->isVisible() )
751 showAdvanced( true );
752 m_listview->ensureItemVisible( m_listview->currentItem() );
756 void KNotifyWidget::sort( bool ascending )
758 m_listview->setSorting( COL_EVENT, ascending );
759 m_listview->sort();
762 void KNotifyWidget::selectItem( Q3ListViewItem *item )
764 if ( item )
766 m_listview->setCurrentItem( item );
767 item->setSelected( true );
768 slotEventChanged( item );
772 void KNotifyWidget::resetDefaults( bool ask )
774 if ( ask )
776 if ( KMessageBox::warningContinueCancel(this,
777 i18n("This will cause the notifications "
778 "to be reset to their defaults."),
779 i18n("Are You Sure?"),
780 i18n("&Reset"))
781 != KMessageBox::Continue)
782 return;
785 reload( true ); // defaults
786 emit changed( true );
789 void KNotifyWidget::reload( bool revertToDefaults )
791 m_listview->clear();
792 ApplicationListIterator it( m_visibleApps );
793 for ( ; it.current(); ++it )
795 it.current()->reloadEvents( revertToDefaults );
796 addToView( it.current()->eventList() );
799 m_listview->sort();
800 selectItem( m_listview->firstChild() );
803 void KNotifyWidget::save()
805 kdDebug() << "save\n";
807 ApplicationListIterator it( m_allApps );
808 while ( it.current() )
810 (*it)->save();
811 ++it;
814 if ( kapp )
816 if ( !KApplication::dcopClient()->isAttached() )
817 KApplication::dcopClient()->attach();
818 DCOPRef("knotify", "").send("reconfigure()");
821 emit changed( false );
824 // returns e.g. "kwin/eventsrc" from a given path
825 // "/opt/kde3/share/apps/kwin/eventsrc"
826 QString KNotifyWidget::makeRelative( const QString& fullPath )
828 int slash = fullPath.lastIndexOf( '/' ) - 1;
829 slash = fullPath.lastIndexOf( '/', slash );
831 if ( slash < 0 )
832 return QString::null;
834 return fullPath.mid( slash+1 );
837 Event * KNotifyWidget::currentEvent()
839 Q3ListViewItem *current = m_listview->currentItem();
840 if ( !current )
841 return 0L;
843 return &static_cast<ListViewItem*>( current )->event();
846 void KNotifyWidget::openSoundDialog( KURLRequester *requester )
848 // only need to init this once
849 requester->disconnect( SIGNAL( openFileDialog( KURLRequester * )),
850 this, SLOT( openSoundDialog( KURLRequester * )));
852 KFileDialog *fileDialog = requester->fileDialog();
853 fileDialog->setWindowTitle( i18n("Select Sound File") );
854 QStringList filters;
855 filters << "audio/x-wav" << "audio/x-mp3" << "application/ogg"
856 << "audio/x-adpcm";
857 fileDialog->setMimeFilter( filters );
859 // find the first "sound"-resource that contains files
860 const Application *app = currentEvent()->application();
861 QStringList soundDirs =
862 KGlobal::dirs()->findDirs("data", app->appName() + "/sounds");
863 soundDirs += KGlobal::dirs()->resourceDirs( "sound" );
865 if ( !soundDirs.isEmpty() ) {
866 KURL soundURL;
867 QDir dir;
868 dir.setFilter( QDir::Files | QDir::Readable );
869 QStringList::ConstIterator it = soundDirs.begin();
870 while ( it != soundDirs.end() ) {
871 dir = *it;
872 if ( dir.isReadable() && dir.count() > 2 ) {
873 soundURL.setPath( *it );
874 fileDialog->setURL( soundURL );
875 break;
877 ++it;
882 void KNotifyWidget::openLogDialog( KURLRequester *requester )
884 // only need to init this once
885 requester->disconnect( SIGNAL( openFileDialog( KURLRequester * )),
886 this, SLOT( openLogDialog( KURLRequester * )));
888 KFileDialog *fileDialog = requester->fileDialog();
889 fileDialog->setWindowTitle( i18n("Select Log File") );
890 QStringList filters;
891 filters << "text/x-log" << "text/plain";
892 fileDialog->setMimeFilter( filters );
895 void KNotifyWidget::openExecDialog( KURLRequester *requester )
897 // only need to init this once
898 requester->disconnect( SIGNAL( openFileDialog( KURLRequester * )),
899 this, SLOT( openExecDialog( KURLRequester * )));
902 KFileDialog *fileDialog = requester->fileDialog();
903 fileDialog->setWindowTitle( i18n("Select File to Execute") );
904 QStringList filters;
905 filters << "application/x-executable" << "application/x-shellscript"
906 << "application/x-perl" << "application/x-python";
907 fileDialog->setMimeFilter( filters );
910 void KNotifyWidget::playSound()
912 if (!KIO::NetAccess::exists( m_soundPath->url(), true, 0 )) {
913 bool foundSound=false;
915 // find the first "sound"-resource that contains files
916 const Application *app = currentEvent()->application();
917 QStringList soundDirs = KGlobal::dirs()->findDirs("data", app->appName() + "/sounds");
918 soundDirs += KGlobal::dirs()->resourceDirs( "sound" );
920 if ( !soundDirs.isEmpty() ) {
921 QDir dir;
922 dir.setFilter( QDir::Files | QDir::Readable );
923 QStringList::ConstIterator it = soundDirs.begin();
924 while ( it != soundDirs.end() ) {
925 dir = *it;
926 if ( dir.isReadable() && dir.count() > 2 &&
927 KIO::NetAccess::exists( *it + m_soundPath->url(), true, 0 )) {
928 foundSound=true;
929 break;
931 ++it;
934 if ( !foundSound ) {
935 KMessageBox::sorry(this, i18n("The specified file does not exist." ));
936 return;
939 KAudioPlayer::play( m_soundPath->url() );
942 void KNotifyWidget::enableAll()
944 bool enable = (sender() == m_buttonEnable);
945 enableAll( SelectionCombo::type(enable ? m_comboEnable : m_comboDisable),
946 enable );
949 void KNotifyWidget::enableAll( int what, bool enable )
951 if ( m_listview->childCount() == 0 )
952 return;
954 bool affectAll = m_affectAllApps->isChecked(); // multi-apps mode
956 ApplicationListIterator appIt( affectAll ? m_allApps : m_visibleApps );
957 for ( ; appIt.current(); ++appIt )
959 const EventList& events = appIt.current()->eventList();
960 EventListIterator it( events );
961 for ( ; it.current(); ++it )
963 if ( enable )
964 it.current()->presentation |= what;
965 else
966 it.current()->presentation &= ~what;
970 // now make the listview reflect the changes
971 Q3ListViewItemIterator it( m_listview->firstChild() );
972 for ( ; it.current(); ++it )
974 ListViewItem *item = static_cast<ListViewItem*>( it.current() );
975 updatePixmaps( item );
978 Q3ListViewItem *item = m_listview->currentItem();
979 if ( !item )
980 item = m_listview->firstChild();
981 selectItem( item );
983 emit changed( true );
987 //////////////////////////////////////////////////////////////////////
988 //////////////////////////////////////////////////////////////////////
992 // path must be "appname/eventsrc", i.e. a relative path
994 Application::Application( const QString &path )
996 QString config_file = path;
997 config_file[config_file.indexOf('/')] = '.';
998 m_events = 0L;
999 config = new KConfig(config_file, false, false);
1000 kc = new KConfig(path, true, false, "data");
1001 kc->setGroup( QLatin1String("Global") );
1002 m_icon = kc->readEntry(QLatin1String("IconName"),
1003 QLatin1String("misc"));
1004 m_description = kc->readEntry( QLatin1String("Comment"),
1005 i18n("No description available") );
1007 int index = path.indexOf( '/' );
1008 if ( index >= 0 )
1009 m_appname = path.left( index );
1010 else
1011 kdDebug() << "Cannot determine application name from path: " << path << endl;
1014 Application::~Application()
1016 delete config;
1017 delete kc;
1018 delete m_events;
1022 const EventList& Application::eventList()
1024 if ( !m_events ) {
1025 m_events = new EventList;
1026 m_events->setAutoDelete( true );
1027 reloadEvents();
1030 return *m_events;
1034 void Application::save()
1036 if ( !m_events )
1037 return;
1039 EventListIterator it( *m_events );
1040 Event *e;
1041 while ( (e = it.current()) ) {
1042 config->setGroup( "Event/" + e->configGroup );
1043 int n = KNotification::staticMetaObject.indexOfEnumerator( "NotifyPresentation" );
1044 config->writeEntry( "Action", QString(KNotification::staticMetaObject.enumerator(n).valueToKeys(e->presentation) ));
1045 config->writePathEntry( "sound", e->soundfile );
1046 config->writePathEntry( "logfile", e->logfile );
1047 config->writePathEntry( "commandline", e->commandline );
1049 ++it;
1051 config->sync();
1055 void Application::reloadEvents( bool revertToDefaults )
1057 if ( m_events )
1058 m_events->clear();
1059 else
1061 m_events = new EventList;
1062 m_events->setAutoDelete( true );
1065 Event *e = 0L;
1067 QString global = QLatin1String("Global");
1068 QString default_group = QLatin1String("<default>");
1069 QString name = QLatin1String("Name");
1070 QString comment = QLatin1String("Comment");
1072 QStringList conflist = kc->groupList();
1073 QStringList::ConstIterator it = conflist.begin();
1074 QRegExp rx("^Event/([^/]*)$");
1075 while ( it != conflist.end() ) {
1076 if ( rx.indexIn(*it) > -1 ) { // event group
1077 kc->setGroup( *it );
1079 e = new Event( this );
1080 e->name = kc->readEntry( name );
1081 e->description = kc->readEntry( comment );
1082 e->dontShow = kc->readNumEntry("nopresentation", 0 );
1083 e->configGroup = rx.cap(1);
1085 int presentationEnum = KNotification::staticMetaObject.indexOfEnumerator( "NotifyPresentation" );
1088 if ( e->name.isEmpty() || e->description.isEmpty() )
1089 delete e;
1090 else { // load the event
1091 // default to passive popups over plain messageboxes
1092 const QString& default_rep = kc->readEntry("Action");
1093 QString default_logfile = kc->readPathEntry("default_logfile");
1094 QString default_soundfile = kc->readPathEntry("sound");
1095 QString default_commandline = kc->readPathEntry("default_commandline");
1097 config->setGroup(*it);
1099 if ( revertToDefaults )
1101 e->presentation = KNotification::staticMetaObject.enumerator(presentationEnum).keysToValue(default_rep.toLatin1());
1102 e->logfile = default_logfile;
1103 e->soundfile = default_soundfile;
1104 e->commandline = default_commandline;
1107 else
1109 e->presentation = KNotification::staticMetaObject.enumerator(presentationEnum).keysToValue(
1110 config->readEntry("presentation", default_rep).toLatin1());
1111 e->logfile = config->readPathEntry("logfile",
1112 default_logfile);
1113 e->soundfile = config->readPathEntry("sound",
1114 default_soundfile);
1115 e->commandline = config->readPathEntry("commandline",
1116 default_commandline);
1119 m_events->append( e );
1123 ++it;
1126 return;
1129 ///////////////////////////////////////////////////////////////////
1130 ///////////////////////////////////////////////////////////////////
1132 ListViewItem::ListViewItem( Q3ListView *view, Event *event )
1133 : Q3ListViewItem( view ),
1134 m_event( event )
1136 setText( COL_EVENT, event->text() );
1139 int ListViewItem::compare ( Q3ListViewItem * i, int col, bool ascending ) const
1141 ListViewItem *item = static_cast<ListViewItem*>( i );
1142 int myPres = m_event->presentation;
1143 int otherPres = item->event().presentation;
1145 int action = 0;
1147 switch ( col )
1149 case COL_EVENT: // use default sorting
1150 return Q3ListViewItem::compare( i, col, ascending );
1152 case COL_EXECUTE:
1153 action = KNotifyClient::Execute;
1154 break;
1155 case COL_LOGFILE:
1156 action = KNotifyClient::Logfile;
1157 break;
1158 case COL_MESSAGE:
1159 action = (KNotifyClient::Messagebox | KNotifyClient::PassivePopup);
1160 break;
1161 case COL_SOUND:
1162 action = KNotifyClient::Sound;
1163 break;
1164 case COL_STDERR:
1165 action = KNotifyClient::Stderr;
1166 break;
1167 case COL_TASKBAR:
1168 action = KNotifyClient::Taskbar;
1169 break;
1172 if ( (myPres & action) == (otherPres & action) )
1174 // default sorting by event
1175 return Q3ListViewItem::compare( i, COL_EVENT, true );
1178 if ( myPres & action )
1179 return -1;
1180 if ( otherPres & action )
1181 return 1;
1183 return 0;
1186 #include "knotifydialog.moc"