korganizer

koeditoralarms.cpp

00001 /*
00002     This file is part of KOrganizer.
00003 
00004     Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
00005     Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00006 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020 
00021     As a special exception, permission is given to link this program
00022     with any edition of Qt, and distribute the resulting executable,
00023     without including the source code for Qt in the source distribution.
00024 */
00025 
00026 #include "koeditoralarms_base.h"
00027 #include "koeditoralarms.h"
00028 
00029 #include <qlayout.h>
00030 #include <qlistview.h>
00031 #include <qpushbutton.h>
00032 #include <qspinbox.h>
00033 #include <qcombobox.h>
00034 #include <qcheckbox.h>
00035 #include <qbuttongroup.h>
00036 #include <qtextedit.h>
00037 #include <qwidgetstack.h>
00038 
00039 #include <kurlrequester.h>
00040 #include <klocale.h>
00041 #include <kdebug.h>
00042 
00043 #include <libkcal/alarm.h>
00044 #include <libkcal/incidence.h>
00045 
00046 #include <libemailfunctions/email.h>
00047 
00048 class AlarmListViewItem : public QListViewItem
00049 {
00050   public:
00051     AlarmListViewItem( QListView *parent, KCal::Alarm *alarm );
00052     virtual ~AlarmListViewItem();
00053     KCal::Alarm *alarm() const { return mAlarm; }
00054     void construct();
00055     enum AlarmViewColumns { ColAlarmType=0, ColAlarmOffset, ColAlarmRepeat };
00056   protected:
00057     KCal::Alarm *mAlarm;
00058 };
00059 
00060 AlarmListViewItem::AlarmListViewItem( QListView *parent, KCal::Alarm *alarm )
00061     : QListViewItem( parent )
00062 {
00063   if ( alarm ) {
00064     mAlarm = new KCal::Alarm( *alarm );
00065   } else {
00066     mAlarm = new KCal::Alarm( 0 );
00067   }
00068   construct();
00069 }
00070 
00071 AlarmListViewItem::~AlarmListViewItem()
00072 {
00073   delete mAlarm;
00074 }
00075 
00076 void AlarmListViewItem::construct()
00077 {
00078   if ( mAlarm ) {
00079     // Alarm type:
00080     QString type;
00081     switch ( mAlarm->type() ) {
00082       case KCal::Alarm::Display:
00083         type = i18n("Reminder Dialog");
00084         break;
00085       case KCal::Alarm::Procedure:
00086         type = i18n("Program");
00087         break;
00088       case KCal::Alarm::Email:
00089         type = i18n("Email");
00090         break;
00091       case KCal::Alarm::Audio:
00092         type = i18n("Audio");
00093         break;
00094       default:
00095         type = i18n("Unknown");
00096         break;
00097     }
00098     setText( ColAlarmType, type );
00099 
00100     // Alarm offset:
00101     QString offsetstr;
00102     int offset = 0;
00103     if ( mAlarm->hasStartOffset() ) {
00104       offset = mAlarm->startOffset().asSeconds();
00105       if ( offset < 0 ) {
00106         offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 before the start");
00107         offset = -offset;
00108       } else {
00109         offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 after the start");
00110       }
00111     } else if ( mAlarm->hasEndOffset() ) {
00112       offset = mAlarm->endOffset().asSeconds();
00113       if ( offset < 0 ) {
00114         offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 before the end");
00115         offset = -offset;
00116       } else {
00117         offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 after the end");
00118       }
00119     }
00120 
00121     offset = offset / 60; // make minutes
00122     int useoffset = offset;
00123 
00124     if ( offset % (24*60) == 0 && offset>0 ) { // divides evenly into days?
00125       useoffset = offset / (24*60);
00126       offsetstr = offsetstr.arg( i18n("1 day", "%n days", useoffset ) );
00127     } else if (offset % 60 == 0 && offset>0 ) { // divides evenly into hours?
00128       useoffset = offset / 60;
00129       offsetstr = offsetstr.arg( i18n("1 hour", "%n hours", useoffset ) );
00130     } else {
00131       useoffset = offset;
00132       offsetstr = offsetstr.arg( i18n("1 minute", "%n minutes", useoffset ) );
00133     }
00134     setText( ColAlarmOffset, offsetstr );
00135 
00136     // Alarm repeat
00137     if ( mAlarm->repeatCount()>0 ) {
00138       setText( ColAlarmRepeat, i18n("Yes") );
00139     } else {
00140       setText( ColAlarmRepeat, i18n("No") );
00141     }
00142   }
00143 }
00144 
00145 
00146 KOEditorAlarms::KOEditorAlarms( KCal::Alarm::List *alarms, QWidget *parent,
00147                                 const char *name )
00148   : KDialogBase( parent, name, true, i18n("Edit Reminders"), Ok | Cancel ), mAlarms( alarms ),mCurrentItem(0L)
00149 {
00150   setMainWidget( mWidget = new KOEditorAlarms_base( this ) );
00151   mWidget->mAlarmList->setColumnWidthMode( 0, QListView::Maximum );
00152   mWidget->mAlarmList->setColumnWidthMode( 1, QListView::Maximum );
00153   connect( mWidget->mAlarmList, SIGNAL( selectionChanged( QListViewItem * ) ),
00154            SLOT( selectionChanged( QListViewItem * ) ) );
00155   connect( mWidget->mAddButton, SIGNAL( clicked() ), SLOT( slotAdd() ) );
00156   connect( mWidget->mRemoveButton, SIGNAL( clicked() ), SLOT( slotRemove() ) );
00157   connect( mWidget->mDuplicateButton, SIGNAL( clicked() ), SLOT( slotDuplicate() ) );
00158 
00159   connect( mWidget->mAlarmOffset, SIGNAL( valueChanged( int ) ), SLOT( changed() ) );
00160   connect( mWidget->mOffsetUnit, SIGNAL( activated( int ) ), SLOT( changed() ) );
00161   connect( mWidget->mBeforeAfter, SIGNAL( activated( int ) ), SLOT( changed() ) );
00162   connect( mWidget->mRepeats, SIGNAL( toggled( bool ) ), SLOT( changed() ) );
00163   connect( mWidget->mRepeatCount, SIGNAL( valueChanged( int ) ), SLOT( changed() ) );
00164   connect( mWidget->mRepeatInterval, SIGNAL( valueChanged( int ) ), SLOT( changed() ) );
00165   connect( mWidget->mAlarmType, SIGNAL(clicked(int)), SLOT( changed() ) );
00166   connect( mWidget->mDisplayText, SIGNAL( textChanged() ), SLOT( changed() ) );
00167   connect( mWidget->mSoundFile, SIGNAL( textChanged( const QString & ) ), SLOT( changed() ) );
00168   connect( mWidget->mApplication, SIGNAL( textChanged( const QString & ) ), SLOT( changed() ) );
00169   connect( mWidget->mAppArguments, SIGNAL( textChanged( const QString & ) ), SLOT( changed() ) );
00170   connect( mWidget->mEmailAddress, SIGNAL( textChanged( const QString & ) ), SLOT( changed() ) );
00171   connect( mWidget->mEmailText, SIGNAL( textChanged() ), SLOT( changed() ) );
00172 
00173   init();
00174 }
00175 
00176 KOEditorAlarms::~KOEditorAlarms()
00177 {
00178 }
00179 
00180 void KOEditorAlarms::changed()
00181 {
00182   if ( !mInitializing && mCurrentItem ) {
00183     writeAlarm( mCurrentItem->alarm() );
00184     mCurrentItem->construct();
00185   }
00186 }
00187 
00188 void KOEditorAlarms::readAlarm( KCal::Alarm *alarm )
00189 {
00190   if ( !alarm ) return;
00191 
00192   mInitializing = true;
00193 
00194   // Offsets
00195   int offset;
00196   int beforeafterpos = 0;
00197   if ( alarm->hasEndOffset() ) {
00198     beforeafterpos = 2;
00199     offset = alarm->endOffset().asSeconds();
00200   } else {
00201     // TODO: Also allow alarms at fixed times, not relative to start/end
00202     offset = alarm->startOffset().asSeconds();
00203   }
00204   // Negative offset means before the start/end...
00205   if ( offset < 0 ) {
00206     offset = -offset;
00207   } else {
00208     ++beforeafterpos;
00209   }
00210   mWidget->mBeforeAfter->setCurrentItem( beforeafterpos );
00211 
00212   offset = offset / 60; // make minutes
00213   int useoffset = offset;
00214 
00215   if ( offset % (24*60) == 0 && offset>0 ) { // divides evenly into days?
00216     useoffset = offset / (24*60);
00217     mWidget->mOffsetUnit->setCurrentItem( 2 );
00218   } else if (offset % 60 == 0 && offset>0 ) { // divides evenly into hours?
00219     useoffset = offset / 60;
00220     mWidget->mOffsetUnit->setCurrentItem( 1 );
00221   } else {
00222     useoffset = offset;
00223     mWidget->mOffsetUnit->setCurrentItem( 0 );
00224   }
00225   mWidget->mAlarmOffset->setValue( useoffset );
00226 
00227 
00228   // Repeating
00229   mWidget->mRepeats->setChecked( alarm->repeatCount()>0 );
00230   if ( alarm->repeatCount()>0 ) {
00231     mWidget->mRepeatCount->setValue( alarm->repeatCount() );
00232     mWidget->mRepeatInterval->setValue( alarm->snoozeTime() );
00233   }
00234 
00235   switch ( alarm->type() ) {
00236     case KCal::Alarm::Audio:
00237         mWidget->mAlarmType->setButton( 1 );
00238         mWidget->mSoundFile->setURL( alarm->audioFile() );
00239         break;
00240     case KCal::Alarm::Procedure:
00241         mWidget->mAlarmType->setButton( 2 );
00242         mWidget->mApplication->setURL( alarm->programFile() );
00243         mWidget->mAppArguments->setText( alarm->programArguments() );
00244         break;
00245     case KCal::Alarm::Email: {
00246         mWidget->mAlarmType->setButton( 3 );
00247         QValueList<KCal::Person> addresses = alarm->mailAddresses();
00248         QStringList add;
00249         for ( QValueList<KCal::Person>::ConstIterator it = addresses.begin();
00250               it != addresses.end(); ++it ) {
00251           add << (*it).fullName();
00252         }
00253         mWidget->mEmailAddress->setText( add.join(", ") );
00254         mWidget->mEmailText->setText( alarm->mailText() );
00255         break;}
00256     case KCal::Alarm::Display:
00257     case KCal::Alarm::Invalid:
00258     default:
00259         mWidget->mAlarmType->setButton( 0 );
00260         mWidget->mDisplayText->setText( alarm->text() );
00261         break;
00262   }
00263 
00264   mWidget->mTypeStack->raiseWidget( mWidget->mAlarmType->selectedId() );
00265 
00266   mInitializing = false;
00267 }
00268 
00269 void KOEditorAlarms::writeAlarm( KCal::Alarm *alarm )
00270 {
00271   // Offsets
00272   int offset = mWidget->mAlarmOffset->value()*60; // minutes
00273   int offsetunit = mWidget->mOffsetUnit->currentItem();
00274   if ( offsetunit >= 1 ) offset *= 60; // hours
00275   if ( offsetunit >= 2 ) offset *= 24; // days
00276   if ( offsetunit >= 3 ) offset *= 7; // weeks
00277 
00278   int beforeafterpos = mWidget->mBeforeAfter->currentItem();
00279   if ( beforeafterpos % 2 == 0 ) { // before -> negative
00280     offset = -offset;
00281   }
00282 
00283   // TODO: Add possibility to specify a given time for the reminder
00284   if ( beforeafterpos / 2 == 0 ) { // start offset
00285     alarm->setStartOffset( KCal::Duration( offset ) );
00286   } else {
00287     alarm->setEndOffset( KCal::Duration( offset ) );
00288   }
00289 
00290   // Repeating
00291   if ( mWidget->mRepeats->isChecked() ) {
00292     alarm->setRepeatCount( mWidget->mRepeatCount->value() );
00293     alarm->setSnoozeTime( mWidget->mRepeatInterval->value() );
00294   } else {
00295     alarm->setRepeatCount( 0 );
00296   }
00297 
00298   switch ( mWidget->mAlarmType->selectedId() ) {
00299     case 1: // Audio
00300         alarm->setAudioAlarm( mWidget->mSoundFile->url() );
00301         break;
00302     case 2: // Procedure
00303         alarm->setProcedureAlarm( mWidget->mApplication->url(), mWidget->mAppArguments->text() );
00304         break;
00305     case 3: { // Email
00306         QStringList addresses = KPIM::splitEmailAddrList( mWidget->mEmailAddress->text() );
00307         QValueList<KCal::Person> add;
00308         for ( QStringList::Iterator it = addresses.begin(); it != addresses.end();
00309               ++it ) {
00310           add << KCal::Person( *it );
00311         }
00312         // TODO: Add a subject line and possibilities for attachments
00313         alarm->setEmailAlarm( QString::null, mWidget->mEmailText->text(),
00314                               add );
00315         break; }
00316     case 0: // Display
00317     default:
00318         alarm->setDisplayAlarm( mWidget->mDisplayText->text() );
00319         break;
00320   }
00321 }
00322 
00323 void KOEditorAlarms::selectionChanged( QListViewItem *listviewitem )
00324 {
00325   AlarmListViewItem *item = dynamic_cast<AlarmListViewItem*>(listviewitem);
00326   mCurrentItem = item;
00327   mWidget->mTimeGroup->setEnabled( item );
00328   mWidget->mTypeGroup->setEnabled( item );
00329   if ( item ) {
00330     readAlarm( item->alarm() );
00331   }
00332 }
00333 
00334 void KOEditorAlarms::slotOk()
00335 {
00336   // copy the mAlarms list
00337   if ( mAlarms ) {
00338     mAlarms->clear();
00339     QListViewItemIterator it( mWidget->mAlarmList );
00340     while ( it.current() ) {
00341       AlarmListViewItem *item = dynamic_cast<AlarmListViewItem*>(*it);
00342       if ( item ) {
00343         mAlarms->append( new KCal::Alarm( *(item->alarm()) ) );
00344       }
00345       ++it;
00346     }
00347   }
00348   accept();
00349 }
00350 
00351 void KOEditorAlarms::slotAdd()
00352 {
00353   mCurrentItem = new AlarmListViewItem( mWidget->mAlarmList, 0 );
00354   mWidget->mAlarmList->setCurrentItem( mCurrentItem );
00355 //   selectionChanged( mCurrentItem );
00356 }
00357 
00358 void KOEditorAlarms::slotDuplicate()
00359 {
00360   if ( mCurrentItem ) {
00361     mCurrentItem = new AlarmListViewItem( mWidget->mAlarmList, mCurrentItem->alarm() );
00362     mWidget->mAlarmList->setCurrentItem( mCurrentItem );
00363 //     selectionChanged( mCurrentItem );
00364   }
00365 }
00366 
00367 void KOEditorAlarms::slotRemove()
00368 {
00369   if ( mCurrentItem ) {
00370     delete mCurrentItem;
00371     mCurrentItem = dynamic_cast<AlarmListViewItem*>( mWidget->mAlarmList->currentItem() );
00372     mWidget->mAlarmList->setSelected( mCurrentItem, true );
00373 
00374   }
00375 }
00376 
00377 void KOEditorAlarms::init()
00378 {
00379   mInitializing = true;
00380   KCal::Alarm::List::ConstIterator it;
00381   for ( it = mAlarms->begin(); it != mAlarms->end(); ++it ) {
00382     new AlarmListViewItem( mWidget->mAlarmList, *it );
00383   }
00384   mWidget->mAlarmList->setSelected( mWidget->mAlarmList->firstChild(), true );
00385   mInitializing = false;
00386 }
00387 
00388 #include "koeditoralarms.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys