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 ( event->attendeeCount() > 1 &&
00345        me && ( me->status() == Attendee::NeedsAction ||
00346        me->status() == Attendee::Tentative ||
00347        me->status() == Attendee::InProcess ) ) {
00348     mInvitationBar->show();
00349   } else {
00350     mInvitationBar->hide();
00351   }
00352 
00353   readIncidence(event, calendar);
00354 }
00355 
00356 void KOEditorGeneralEvent::writeEvent(Event *event)
00357 {
00358 //  kdDebug(5850) << "KOEditorGeneralEvent::writeEvent()" << endl;
00359 
00360   writeIncidence(event);
00361 
00362   QDate tmpDate;
00363   QTime tmpTime;
00364   QDateTime tmpDT;
00365 
00366   // temp. until something better happens.
00367   QString tmpStr;
00368 
00369   if (mAlldayEventCheckbox->isChecked()) {
00370     event->setFloats(true);
00371     // need to change this.
00372     tmpDate = mStartDateEdit->date();
00373     tmpTime.setHMS(0,0,0);
00374     tmpDT.setDate(tmpDate);
00375     tmpDT.setTime(tmpTime);
00376     event->setDtStart(tmpDT);
00377 
00378     tmpDate = mEndDateEdit->date();
00379     tmpTime.setHMS(0,0,0);
00380     tmpDT.setDate(tmpDate);
00381     tmpDT.setTime(tmpTime);
00382     event->setDtEnd(tmpDT);
00383   } else {
00384     event->setFloats(false);
00385 
00386     // set date/time end
00387     tmpDate = mEndDateEdit->date();
00388     tmpTime = mEndTimeEdit->getTime();
00389     tmpDT.setDate(tmpDate);
00390     tmpDT.setTime(tmpTime);
00391     event->setDtEnd(tmpDT);
00392 
00393     // set date/time start
00394     tmpDate = mStartDateEdit->date();
00395     tmpTime = mStartTimeEdit->getTime();
00396     tmpDT.setDate(tmpDate);
00397     tmpDT.setTime(tmpTime);
00398     event->setDtStart(tmpDT);
00399   } // check for float
00400 
00401   event->setTransparency(mFreeTimeCombo->currentItem() > 0
00402                          ? KCal::Event::Transparent
00403                          : KCal::Event::Opaque);
00404 
00405 //  kdDebug(5850) << "KOEditorGeneralEvent::writeEvent() done" << endl;
00406 }
00407 
00408 void KOEditorGeneralEvent::setDuration()
00409 {
00410   QString tmpStr, catStr;
00411   int hourdiff, minutediff;
00412   // end<date is an accepted temporary state while typing, but don't show
00413   // any duration if this happens
00414   if(mCurrEndDateTime >= mCurrStartDateTime) {
00415 
00416     if (mAlldayEventCheckbox->isChecked()) {
00417       int daydiff = mCurrStartDateTime.date().daysTo(mCurrEndDateTime.date()) + 1;
00418       tmpStr = i18n("Duration: ");
00419       tmpStr.append(i18n("1 Day","%n Days",daydiff));
00420     } else {
00421       hourdiff = mCurrStartDateTime.date().daysTo(mCurrEndDateTime.date()) * 24;
00422       hourdiff += mCurrEndDateTime.time().hour() -
00423                   mCurrStartDateTime.time().hour();
00424       minutediff = mCurrEndDateTime.time().minute() -
00425                    mCurrStartDateTime.time().minute();
00426       // If minutediff is negative, "borrow" 60 minutes from hourdiff
00427       if (minutediff < 0 && hourdiff > 0) {
00428         hourdiff -= 1;
00429         minutediff += 60;
00430       }
00431       if (hourdiff || minutediff){
00432         tmpStr = i18n("Duration: ");
00433         if (hourdiff){
00434           catStr = i18n("1 hour","%n hours",hourdiff);
00435           tmpStr.append(catStr);
00436         }
00437         if (hourdiff && minutediff){
00438           tmpStr += i18n(", ");
00439         }
00440         if (minutediff){
00441           catStr = i18n("1 minute","%n minutes",minutediff);
00442           tmpStr += catStr;
00443         }
00444       } else tmpStr = "";
00445     }
00446   }
00447   mDurationLabel->setText(tmpStr);
00448   QWhatsThis::add( mDurationLabel,
00449        i18n("Shows the duration of the event or to-do with the "
00450       "current start and end dates and times.") );
00451 }
00452 
00453 void KOEditorGeneralEvent::emitDateTimeStr()
00454 {
00455   KLocale *l = KGlobal::locale();
00456 
00457   QString from,to;
00458   if (mAlldayEventCheckbox->isChecked()) {
00459     from = l->formatDate(mCurrStartDateTime.date());
00460     to = l->formatDate(mCurrEndDateTime.date());
00461   } else {
00462     from = l->formatDateTime(mCurrStartDateTime);
00463     to = l->formatDateTime(mCurrEndDateTime);
00464   }
00465 
00466   QString str = i18n("From: %1   To: %2   %3").arg(from).arg(to)
00467                 .arg(mDurationLabel->text());
00468 
00469   emit dateTimeStrChanged(str);
00470 }
00471 
00472 bool KOEditorGeneralEvent::validateInput()
00473 {
00474 //  kdDebug(5850) << "KOEditorGeneralEvent::validateInput()" << endl;
00475 
00476   if (!mAlldayEventCheckbox->isChecked()) {
00477     if (!mStartTimeEdit->inputIsValid()) {
00478       KMessageBox::sorry( 0,
00479           i18n("Please specify a valid start time, for example '%1'.")
00480           .arg( KGlobal::locale()->formatTime( QTime::currentTime() ) ) );
00481       return false;
00482     }
00483 
00484     if (!mEndTimeEdit->inputIsValid()) {
00485       KMessageBox::sorry( 0,
00486           i18n("Please specify a valid end time, for example '%1'.")
00487           .arg( KGlobal::locale()->formatTime( QTime::currentTime() ) ) );
00488       return false;
00489     }
00490   }
00491 
00492   if (!mStartDateEdit->date().isValid()) {
00493     KMessageBox::sorry( 0,
00494         i18n("Please specify a valid start date, for example '%1'.")
00495         .arg( KGlobal::locale()->formatDate( QDate::currentDate() ) ) );
00496     return false;
00497   }
00498 
00499   if (!mEndDateEdit->date().isValid()) {
00500     KMessageBox::sorry( 0,
00501         i18n("Please specify a valid end date, for example '%1'.")
00502         .arg( KGlobal::locale()->formatDate( QDate::currentDate() ) ) );
00503     return false;
00504   }
00505 
00506   QDateTime startDt,endDt;
00507   startDt.setDate(mStartDateEdit->date());
00508   endDt.setDate(mEndDateEdit->date());
00509   if (!mAlldayEventCheckbox->isChecked()) {
00510     startDt.setTime(mStartTimeEdit->getTime());
00511     endDt.setTime(mEndTimeEdit->getTime());
00512   }
00513 
00514   if (startDt > endDt) {
00515     KMessageBox::sorry(0,i18n("The event ends before it starts.\n"
00516                                  "Please correct dates and times."));
00517     return false;
00518   }
00519 
00520   return KOEditorGeneral::validateInput();
00521 }
00522 
00523 void KOEditorGeneralEvent::updateRecurrenceSummary(const QString & summary)
00524 {
00525   mRecurrenceSummary->setText( summary );
00526 }
KDE Home | KDE Accessibility Home | Description of Access Keys