korganizer

koeditorgeneralevent.cpp

00001 /*
00002     This file is part of KOrganizer.
00003     Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
00004     Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 
00020     As a special exception, permission is given to link this program
00021     with any edition of Qt, and distribute the resulting executable,
00022     without including the source code for Qt in the source distribution.
00023 */
00024 
00025 #include <qtooltip.h>
00026 #include <qlayout.h>
00027 #include <qvbox.h>
00028 #include <qbuttongroup.h>
00029 #include <qvgroupbox.h>
00030 #include <qwidgetstack.h>
00031 #include <qspinbox.h>
00032 #include <qdatetime.h>
00033 #include <qlabel.h>
00034 #include <qcheckbox.h>
00035 #include <qcombobox.h>
00036 #include <qpushbutton.h>
00037 #include <qwhatsthis.h>
00038 
00039 #include <kdebug.h>
00040 #include <kglobal.h>
00041 #include <klocale.h>
00042 #include <kiconloader.h>
00043 #include <kmessagebox.h>
00044 #include <kfiledialog.h>
00045 #include <kstandarddirs.h>
00046 #include <ktextedit.h>
00047 
00048 #include <libkcal/event.h>
00049 #include <libkcal/incidenceformatter.h>
00050 
00051 #include "ktimeedit.h"
00052 #include <libkdepim/kdateedit.h>
00053 
00054 #include "koprefs.h"
00055 
00056 #include "koeditorgeneralevent.h"
00057 #include "koeditorgeneralevent.moc"
00058 
00059 KOEditorGeneralEvent::KOEditorGeneralEvent(QObject* parent,
00060                                            const char* name) :
00061   KOEditorGeneral( parent, name)
00062 {
00063   connect( this, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & )),
00064            SLOT( setDuration() ) );
00065   connect( this, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & )),
00066            SLOT( emitDateTimeStr() ));
00067 }
00068 
00069 KOEditorGeneralEvent::~KOEditorGeneralEvent()
00070 {
00071 }
00072 
00073 void KOEditorGeneralEvent::finishSetup()
00074 {
00075   QWidget::setTabOrder( mSummaryEdit, mLocationEdit );
00076   QWidget::setTabOrder( mLocationEdit, mStartDateEdit );
00077   QWidget::setTabOrder( mStartDateEdit, mStartTimeEdit );
00078   QWidget::setTabOrder( mStartTimeEdit, mEndDateEdit );
00079   QWidget::setTabOrder( mEndDateEdit, mEndTimeEdit );
00080   QWidget::setTabOrder( mEndTimeEdit, mAlldayEventCheckbox );
00081   QWidget::setTabOrder( mAlldayEventCheckbox, mAlarmButton );
00082   QWidget::setTabOrder( mAlarmButton, mAlarmTimeEdit );
00083   QWidget::setTabOrder( mAlarmTimeEdit, mAlarmIncrCombo );
00084 //   QWidget::setTabOrder( mAlarmIncrCombo, mAlarmSoundButton );
00085   QWidget::setTabOrder( mAlarmIncrCombo, mAlarmEditButton );
00086 //   QWidget::setTabOrder( mAlarmSoundButton, mAlarmProgramButton );
00087 //   QWidget::setTabOrder( mAlarmProgramButton, mFreeTimeCombo );
00088   QWidget::setTabOrder( mAlarmEditButton, mFreeTimeCombo );
00089   QWidget::setTabOrder( mFreeTimeCombo, mDescriptionEdit );
00090   QWidget::setTabOrder( mDescriptionEdit, mCategoriesButton );
00091   QWidget::setTabOrder( mCategoriesButton, mSecrecyCombo );
00092 //  QWidget::setTabOrder( mSecrecyCombo, mDescriptionEdit );
00093 
00094   mSummaryEdit->setFocus();
00095 }
00096 
00097 void KOEditorGeneralEvent::initTime(QWidget *parent,QBoxLayout *topLayout)
00098 {
00099   QBoxLayout *timeLayout = new QVBoxLayout(topLayout);
00100 
00101   QGroupBox *timeGroupBox = new QGroupBox(1,QGroupBox::Horizontal,
00102                                           i18n("Date && Time"),parent);
00103   QWhatsThis::add( timeGroupBox,
00104        i18n("Sets options related to the date and time of the "
00105             "event or to-do.") );
00106   timeLayout->addWidget(timeGroupBox);
00107 
00108   QFrame *timeBoxFrame = new QFrame(timeGroupBox);
00109 
00110   QGridLayout *layoutTimeBox = new QGridLayout( timeBoxFrame );
00111   layoutTimeBox->setSpacing(topLayout->spacing());
00112   layoutTimeBox->setColStretch( 3, 1 );
00113 
00114   mStartDateLabel = new QLabel(i18n("&Start:"),timeBoxFrame);
00115   layoutTimeBox->addWidget(mStartDateLabel,0,0);
00116 
00117   mStartDateEdit = new KDateEdit(timeBoxFrame);
00118   layoutTimeBox->addWidget(mStartDateEdit,0,1);
00119   mStartDateLabel->setBuddy( mStartDateEdit );
00120 
00121   mStartTimeEdit = new KTimeEdit(timeBoxFrame);
00122   layoutTimeBox->addWidget(mStartTimeEdit,0,2);
00123 
00124 
00125   mEndDateLabel = new QLabel(i18n("&End:"),timeBoxFrame);
00126   layoutTimeBox->addWidget(mEndDateLabel,1,0);
00127 
00128   mEndDateEdit = new KDateEdit(timeBoxFrame);
00129   layoutTimeBox->addWidget(mEndDateEdit,1,1);
00130   mEndDateLabel->setBuddy( mEndDateEdit );
00131 
00132   mEndTimeEdit = new KTimeEdit(timeBoxFrame);
00133   layoutTimeBox->addWidget(mEndTimeEdit,1,2);
00134 
00135   mAlldayEventCheckbox = new QCheckBox(i18n("All-&day"),timeBoxFrame);
00136   layoutTimeBox->addWidget( mAlldayEventCheckbox, 0, 3 );
00137   connect(mAlldayEventCheckbox, SIGNAL(toggled(bool)),SLOT(associateTime(bool)));
00138 
00139   mDurationLabel = new QLabel( timeBoxFrame );
00140   layoutTimeBox->addWidget( mDurationLabel, 1, 3 );
00141 
00142   // time widgets are checked if they contain a valid time
00143   connect(mStartTimeEdit, SIGNAL(timeChanged(QTime)),
00144           this, SLOT(startTimeChanged(QTime)));
00145   connect(mEndTimeEdit, SIGNAL(timeChanged(QTime)),
00146           this, SLOT(endTimeChanged(QTime)));
00147 
00148   // date widgets are checked if they contain a valid date
00149   connect(mStartDateEdit, SIGNAL(dateChanged(const QDate&)),
00150           this, SLOT(startDateChanged(const QDate&)));
00151   connect(mEndDateEdit, SIGNAL(dateChanged(const QDate&)),
00152           this, SLOT(endDateChanged(const QDate&)));
00153 
00154   QBoxLayout *recLayout = new QHBoxLayout();
00155   layoutTimeBox->addMultiCellLayout( recLayout, 2, 2, 1, 4 );
00156   mRecurrenceSummary = new QLabel( QString(), timeBoxFrame );
00157   recLayout->addWidget( mRecurrenceSummary );
00158   QPushButton *recEditButton = new QPushButton( i18n("Edit..."), timeBoxFrame );
00159   recLayout->addWidget( recEditButton );
00160   connect( recEditButton, SIGNAL(clicked()), SIGNAL(editRecurrence()) );
00161   recLayout->addStretch( 1 );
00162 
00163   QLabel *label = new QLabel( i18n("Reminder:"), timeBoxFrame );
00164   layoutTimeBox->addWidget( label, 3, 0 );
00165   QBoxLayout *alarmLineLayout = new QHBoxLayout();
00166   layoutTimeBox->addMultiCellLayout( alarmLineLayout, 3, 3, 1, 4 );
00167   initAlarm( timeBoxFrame, alarmLineLayout );
00168   alarmLineLayout->addStretch( 1 );
00169 
00170   QBoxLayout *secLayout = new QHBoxLayout();
00171   layoutTimeBox->addLayout( secLayout, 0, 4 );
00172   initSecrecy( timeBoxFrame, secLayout );
00173 
00174   QBoxLayout *classLayout = new QHBoxLayout();
00175   layoutTimeBox->addLayout( classLayout, 1, 4 );
00176   initClass( timeBoxFrame, classLayout );
00177 }
00178 
00179 void KOEditorGeneralEvent::initClass(QWidget *parent,QBoxLayout *topLayout)
00180 {
00181   QBoxLayout *classLayout = new QHBoxLayout(topLayout);
00182 
00183   QLabel *freeTimeLabel = new QLabel(i18n("S&how time as:"),parent);
00184   QString whatsThis = i18n("Sets how this time will appear on your Free/Busy "
00185                            "information.");
00186   QWhatsThis::add( freeTimeLabel, whatsThis );
00187   classLayout->addWidget(freeTimeLabel);
00188 
00189   mFreeTimeCombo = new QComboBox(false, parent);
00190   QWhatsThis::add( mFreeTimeCombo, whatsThis );
00191   mFreeTimeCombo->insertItem(i18n("Busy"));
00192   mFreeTimeCombo->insertItem(i18n("Free"));
00193   classLayout->addWidget(mFreeTimeCombo);
00194   freeTimeLabel->setBuddy( mFreeTimeCombo );
00195 }
00196 
00197 void KOEditorGeneralEvent::initInvitationBar(QWidget * parent, QBoxLayout * layout)
00198 {
00199   QBoxLayout *topLayout = new QHBoxLayout( layout );
00200   mInvitationBar = new QFrame( parent );
00201   mInvitationBar->setPaletteBackgroundColor( KGlobalSettings::alternateBackgroundColor() );
00202   topLayout->addWidget( mInvitationBar );
00203 
00204   QBoxLayout *barLayout = new QHBoxLayout( mInvitationBar );
00205   barLayout->setSpacing( layout->spacing() );
00206   QLabel *label = new QLabel( i18n("You have not yet definitely responded to this invitation." ), mInvitationBar );
00207   barLayout->addWidget( label );
00208   barLayout->addStretch( 1 );
00209   QPushButton *button = new QPushButton( i18n("Accept"), mInvitationBar );
00210   connect( button, SIGNAL(clicked()), SIGNAL(acceptInvitation()) );
00211   connect( button, SIGNAL(clicked()), mInvitationBar, SLOT(hide()) );
00212   barLayout->addWidget( button );
00213   button = new QPushButton( i18n("Decline"), mInvitationBar );
00214   connect( button, SIGNAL(clicked()), SIGNAL(declineInvitation()) );
00215   connect( button, SIGNAL(clicked()), mInvitationBar, SLOT(hide()) );
00216   barLayout->addWidget( button );
00217 
00218   mInvitationBar->hide();
00219 }
00220 
00221 void KOEditorGeneralEvent::timeStuffDisable(bool disable)
00222 {
00223   mStartTimeEdit->setEnabled( !disable );
00224   mEndTimeEdit->setEnabled( !disable );
00225 
00226   setDuration();
00227   emitDateTimeStr();
00228 }
00229 
00230 void KOEditorGeneralEvent::associateTime(bool time)
00231 {
00232   timeStuffDisable(time);
00233   //if(alarmButton->isChecked()) alarmStuffDisable(noTime);
00234   allDayChanged(time);
00235 }
00236 
00237 void KOEditorGeneralEvent::setDateTimes( const QDateTime &start, const QDateTime &end )
00238 {
00239 //  kdDebug(5850) << "KOEditorGeneralEvent::setDateTimes(): Start DateTime: " << start.toString() << endl;
00240 
00241   mStartDateEdit->setDate(start.date());
00242   // KTimeEdit seems to emit some signals when setTime() is called.
00243   mStartTimeEdit->blockSignals( true );
00244   mStartTimeEdit->setTime(start.time());
00245   mStartTimeEdit->blockSignals( false );
00246   mEndDateEdit->setDate(end.date());
00247   mEndTimeEdit->setTime(end.time());
00248 
00249   mCurrStartDateTime = start;
00250   mCurrEndDateTime = end;
00251 
00252   setDuration();
00253   emitDateTimeStr();
00254 }
00255 
00256 void KOEditorGeneralEvent::startTimeChanged( QTime newtime )
00257 {
00258   kdDebug(5850) << "KOEditorGeneralEvent::startTimeChanged() " << newtime.toString() << endl;
00259 
00260   int secsep = mCurrStartDateTime.secsTo(mCurrEndDateTime);
00261 
00262   mCurrStartDateTime.setTime(newtime);
00263 
00264   // adjust end time so that the event has the same duration as before.
00265   mCurrEndDateTime = mCurrStartDateTime.addSecs(secsep);
00266   mEndTimeEdit->setTime(mCurrEndDateTime.time());
00267   mEndDateEdit->setDate(mCurrEndDateTime.date());
00268 
00269   emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime);
00270 }
00271 
00272 void KOEditorGeneralEvent::endTimeChanged( QTime newtime )
00273 {
00274 //  kdDebug(5850) << "KOEditorGeneralEvent::endTimeChanged " << newtime.toString() << endl;
00275 
00276   QDateTime newdt(mCurrEndDateTime.date(), newtime);
00277   mCurrEndDateTime = newdt;
00278 
00279   emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime);
00280 }
00281 
00282 void KOEditorGeneralEvent::startDateChanged( const QDate &newdate )
00283 {
00284   if ( !newdate.isValid() )
00285     return;
00286 
00287   int daysep = mCurrStartDateTime.daysTo(mCurrEndDateTime);
00288 
00289   mCurrStartDateTime.setDate(newdate);
00290 
00291   // adjust end date so that the event has the same duration as before
00292   mCurrEndDateTime.setDate(mCurrStartDateTime.date().addDays(daysep));
00293   mEndDateEdit->setDate(mCurrEndDateTime.date());
00294 
00295   emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime);
00296 }
00297 
00298 void KOEditorGeneralEvent::endDateChanged( const QDate &newdate )
00299 {
00300   if ( !newdate.isValid() )
00301     return;
00302 
00303   QDateTime newdt(newdate, mCurrEndDateTime.time());
00304   mCurrEndDateTime = newdt;
00305 
00306   emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime);
00307 }
00308 
00309 void KOEditorGeneralEvent::setDefaults( const QDateTime &from,
00310                                         const QDateTime &to, bool allDay)
00311 {
00312   KOEditorGeneral::setDefaults(allDay);
00313 
00314   mAlldayEventCheckbox->setChecked(allDay);
00315   timeStuffDisable(allDay);
00316 
00317   setDateTimes(from,to);
00318 }
00319 
00320 void KOEditorGeneralEvent::readEvent( Event *event, Calendar *calendar, bool tmpl )
00321 {
00322   QString tmpStr;
00323 
00324   mAlldayEventCheckbox->setChecked(event->doesFloat());
00325   timeStuffDisable(event->doesFloat());
00326 
00327   if ( !tmpl ) {
00328     // the rest is for the events only
00329     setDateTimes(event->dtStart(),event->dtEnd());
00330   }
00331 
00332   switch( event->transparency() ) {
00333   case Event::Transparent:
00334     mFreeTimeCombo->setCurrentItem(1);
00335     break;
00336   case Event::Opaque:
00337     mFreeTimeCombo->setCurrentItem(0);
00338     break;
00339   }
00340 
00341   mRecurrenceSummary->setText( IncidenceFormatter::recurrenceString( event ) );
00342 
00343   Attendee *me = event->attendeeByMails( KOPrefs::instance()->allEmails() );
00344   if ( me && (me->status() == Attendee::NeedsAction || me->status() == Attendee::Tentative ||
00345        me->status() == Attendee::InProcess) ) {
00346     mInvitationBar->show();
00347   } else {
00348     mInvitationBar->hide();
00349   }
00350 
00351   readIncidence(event, calendar);
00352 }
00353 
00354 void KOEditorGeneralEvent::writeEvent(Event *event)
00355 {
00356 //  kdDebug(5850) << "KOEditorGeneralEvent::writeEvent()" << endl;
00357 
00358   writeIncidence(event);
00359 
00360   QDate tmpDate;
00361   QTime tmpTime;
00362   QDateTime tmpDT;
00363 
00364   // temp. until something better happens.
00365   QString tmpStr;
00366 
00367   if (mAlldayEventCheckbox->isChecked()) {
00368     event->setFloats(true);
00369     // need to change this.
00370     tmpDate = mStartDateEdit->date();
00371     tmpTime.setHMS(0,0,0);
00372     tmpDT.setDate(tmpDate);
00373     tmpDT.setTime(tmpTime);
00374     event->setDtStart(tmpDT);
00375 
00376     tmpDate = mEndDateEdit->date();
00377     tmpTime.setHMS(0,0,0);
00378     tmpDT.setDate(tmpDate);
00379     tmpDT.setTime(tmpTime);
00380     event->setDtEnd(tmpDT);
00381   } else {
00382     event->setFloats(false);
00383 
00384     // set date/time end
00385     tmpDate = mEndDateEdit->date();
00386     tmpTime = mEndTimeEdit->getTime();
00387     tmpDT.setDate(tmpDate);
00388     tmpDT.setTime(tmpTime);
00389     event->setDtEnd(tmpDT);
00390 
00391     // set date/time start
00392     tmpDate = mStartDateEdit->date();
00393     tmpTime = mStartTimeEdit->getTime();
00394     tmpDT.setDate(tmpDate);
00395     tmpDT.setTime(tmpTime);
00396     event->setDtStart(tmpDT);
00397   } // check for float
00398 
00399   event->setTransparency(mFreeTimeCombo->currentItem() > 0
00400                          ? KCal::Event::Transparent
00401                          : KCal::Event::Opaque);
00402 
00403 //  kdDebug(5850) << "KOEditorGeneralEvent::writeEvent() done" << endl;
00404 }
00405 
00406 void KOEditorGeneralEvent::setDuration()
00407 {
00408   QString tmpStr, catStr;
00409   int hourdiff, minutediff;
00410   // end<date is an accepted temporary state while typing, but don't show
00411   // any duration if this happens
00412   if(mCurrEndDateTime >= mCurrStartDateTime) {
00413 
00414     if (mAlldayEventCheckbox->isChecked()) {
00415       int daydiff = mCurrStartDateTime.date().daysTo(mCurrEndDateTime.date()) + 1;
00416       tmpStr = i18n("Duration: ");
00417       tmpStr.append(i18n("1 Day","%n Days",daydiff));
00418     } else {
00419       hourdiff = mCurrStartDateTime.date().daysTo(mCurrEndDateTime.date()) * 24;
00420       hourdiff += mCurrEndDateTime.time().hour() -
00421                   mCurrStartDateTime.time().hour();
00422       minutediff = mCurrEndDateTime.time().minute() -
00423                    mCurrStartDateTime.time().minute();
00424       // If minutediff is negative, "borrow" 60 minutes from hourdiff
00425       if (minutediff < 0 && hourdiff > 0) {
00426         hourdiff -= 1;
00427         minutediff += 60;
00428       }
00429       if (hourdiff || minutediff){
00430         tmpStr = i18n("Duration: ");
00431         if (hourdiff){
00432           catStr = i18n("1 hour","%n hours",hourdiff);
00433           tmpStr.append(catStr);
00434         }
00435         if (hourdiff && minutediff){
00436           tmpStr += i18n(", ");
00437         }
00438         if (minutediff){
00439           catStr = i18n("1 minute","%n minutes",minutediff);
00440           tmpStr += catStr;
00441         }
00442       } else tmpStr = "";
00443     }
00444   }
00445   mDurationLabel->setText(tmpStr);
00446   QWhatsThis::add( mDurationLabel,
00447        i18n("Shows the duration of the event or to-do with the "
00448       "current start and end dates and times.") );
00449 }
00450 
00451 void KOEditorGeneralEvent::emitDateTimeStr()
00452 {
00453   KLocale *l = KGlobal::locale();
00454 
00455   QString from,to;
00456   if (mAlldayEventCheckbox->isChecked()) {
00457     from = l->formatDate(mCurrStartDateTime.date());
00458     to = l->formatDate(mCurrEndDateTime.date());
00459   } else {
00460     from = l->formatDateTime(mCurrStartDateTime);
00461     to = l->formatDateTime(mCurrEndDateTime);
00462   }
00463 
00464   QString str = i18n("From: %1   To: %2   %3").arg(from).arg(to)
00465                 .arg(mDurationLabel->text());
00466 
00467   emit dateTimeStrChanged(str);
00468 }
00469 
00470 bool KOEditorGeneralEvent::validateInput()
00471 {
00472 //  kdDebug(5850) << "KOEditorGeneralEvent::validateInput()" << endl;
00473 
00474   if (!mAlldayEventCheckbox->isChecked()) {
00475     if (!mStartTimeEdit->inputIsValid()) {
00476       KMessageBox::sorry( 0,
00477           i18n("Please specify a valid start time, for example '%1'.")
00478           .arg( KGlobal::locale()->formatTime( QTime::currentTime() ) ) );
00479       return false;
00480     }
00481 
00482     if (!mEndTimeEdit->inputIsValid()) {
00483       KMessageBox::sorry( 0,
00484           i18n("Please specify a valid end time, for example '%1'.")
00485           .arg( KGlobal::locale()->formatTime( QTime::currentTime() ) ) );
00486       return false;
00487     }
00488   }
00489 
00490   if (!mStartDateEdit->date().isValid()) {
00491     KMessageBox::sorry( 0,
00492         i18n("Please specify a valid start date, for example '%1'.")
00493         .arg( KGlobal::locale()->formatDate( QDate::currentDate() ) ) );
00494     return false;
00495   }
00496 
00497   if (!mEndDateEdit->date().isValid()) {
00498     KMessageBox::sorry( 0,
00499         i18n("Please specify a valid end date, for example '%1'.")
00500         .arg( KGlobal::locale()->formatDate( QDate::currentDate() ) ) );
00501     return false;
00502   }
00503 
00504   QDateTime startDt,endDt;
00505   startDt.setDate(mStartDateEdit->date());
00506   endDt.setDate(mEndDateEdit->date());
00507   if (!mAlldayEventCheckbox->isChecked()) {
00508     startDt.setTime(mStartTimeEdit->getTime());
00509     endDt.setTime(mEndTimeEdit->getTime());
00510   }
00511 
00512   if (startDt > endDt) {
00513     KMessageBox::sorry(0,i18n("The event ends before it starts.\n"
00514                                  "Please correct dates and times."));
00515     return false;
00516   }
00517 
00518   return KOEditorGeneral::validateInput();
00519 }
00520 
00521 void KOEditorGeneralEvent::updateRecurrenceSummary(const QString & summary)
00522 {
00523   mRecurrenceSummary->setText( summary );
00524 }
KDE Home | KDE Accessibility Home | Description of Access Keys