00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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 <kmessagebox.h>
00043 #include <kfiledialog.h>
00044 #include <kstandarddirs.h>
00045 #include <ktextedit.h>
00046
00047 #include <libkcal/event.h>
00048 #include <libkcal/incidenceformatter.h>
00049
00050 #include "ktimeedit.h"
00051 #include <libkdepim/kdateedit.h>
00052
00053 #include "koprefs.h"
00054 #include "koglobals.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, mRecEditButton );
00082 QWidget::setTabOrder( mRecEditButton, mAlarmButton );
00083 QWidget::setTabOrder( mAlarmButton, mAlarmTimeEdit );
00084 QWidget::setTabOrder( mAlarmTimeEdit, mAlarmIncrCombo );
00085
00086 QWidget::setTabOrder( mAlarmIncrCombo, mAlarmEditButton );
00087
00088
00089 QWidget::setTabOrder( mAlarmEditButton, mFreeTimeCombo );
00090 QWidget::setTabOrder( mFreeTimeCombo, mDescriptionEdit );
00091 QWidget::setTabOrder( mDescriptionEdit, mCategoriesButton );
00092 QWidget::setTabOrder( mCategoriesButton, mSecrecyCombo );
00093
00094
00095 mSummaryEdit->setFocus();
00096 }
00097
00098 void KOEditorGeneralEvent::initTime(QWidget *parent,QBoxLayout *topLayout)
00099 {
00100 QBoxLayout *timeLayout = new QVBoxLayout(topLayout);
00101
00102 QGroupBox *timeGroupBox = new QGroupBox(1,QGroupBox::Horizontal,
00103 i18n("Date && Time"),parent);
00104 QWhatsThis::add( timeGroupBox,
00105 i18n("Sets options related to the date and time of the "
00106 "event or to-do.") );
00107 timeLayout->addWidget(timeGroupBox);
00108
00109 QFrame *timeBoxFrame = new QFrame(timeGroupBox);
00110
00111 QGridLayout *layoutTimeBox = new QGridLayout( timeBoxFrame );
00112 layoutTimeBox->setSpacing(topLayout->spacing());
00113 layoutTimeBox->setColStretch( 3, 1 );
00114
00115 mStartDateLabel = new QLabel(i18n("&Start:"),timeBoxFrame);
00116 layoutTimeBox->addWidget(mStartDateLabel,0,0);
00117
00118 mStartDateEdit = new KDateEdit(timeBoxFrame);
00119 layoutTimeBox->addWidget(mStartDateEdit,0,1);
00120 mStartDateLabel->setBuddy( mStartDateEdit );
00121
00122 mStartTimeEdit = new KTimeEdit(timeBoxFrame);
00123 layoutTimeBox->addWidget(mStartTimeEdit,0,2);
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
00143 connect(mStartTimeEdit, SIGNAL(timeChanged(QTime)),
00144 this, SLOT(startTimeChanged(QTime)));
00145 connect(mEndTimeEdit, SIGNAL(timeChanged(QTime)),
00146 this, SLOT(endTimeChanged(QTime)));
00147
00148
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 QLabel *label = new QLabel( i18n( "Recurrence:" ), timeBoxFrame );
00155 layoutTimeBox->addWidget( label, 2, 0 );
00156 QBoxLayout *recLayout = new QHBoxLayout();
00157 layoutTimeBox->addMultiCellLayout( recLayout, 2, 2, 1, 4 );
00158 mRecEditButton = new QPushButton( timeBoxFrame );
00159 mRecEditButton->setIconSet( KOGlobals::self()->smallIconSet( "recur", 16 ) );
00160 recLayout->addWidget( mRecEditButton );
00161 connect( mRecEditButton, SIGNAL(clicked()), SIGNAL(editRecurrence()) );
00162 mRecEditLabel = new QLabel( QString(), timeBoxFrame );
00163 recLayout->addWidget( mRecEditLabel );
00164 recLayout->addStretch( 1 );
00165
00166 label = new QLabel( i18n("Reminder:"), timeBoxFrame );
00167 layoutTimeBox->addWidget( label, 3, 0 );
00168 QBoxLayout *alarmLineLayout = new QHBoxLayout();
00169 layoutTimeBox->addMultiCellLayout( alarmLineLayout, 3, 3, 1, 4 );
00170 initAlarm( timeBoxFrame, alarmLineLayout );
00171 alarmLineLayout->addStretch( 1 );
00172
00173 QBoxLayout *secLayout = new QHBoxLayout();
00174 layoutTimeBox->addLayout( secLayout, 0, 4 );
00175 initSecrecy( timeBoxFrame, secLayout );
00176
00177 QBoxLayout *classLayout = new QHBoxLayout();
00178 layoutTimeBox->addLayout( classLayout, 1, 4 );
00179 initClass( timeBoxFrame, classLayout );
00180 }
00181
00182 void KOEditorGeneralEvent::initClass(QWidget *parent,QBoxLayout *topLayout)
00183 {
00184 QBoxLayout *classLayout = new QHBoxLayout(topLayout);
00185
00186 QLabel *freeTimeLabel = new QLabel(i18n("S&how time as:"),parent);
00187 QString whatsThis = i18n("Sets how this time will appear on your Free/Busy "
00188 "information.");
00189 QWhatsThis::add( freeTimeLabel, whatsThis );
00190 classLayout->addWidget(freeTimeLabel);
00191
00192 mFreeTimeCombo = new QComboBox(false, parent);
00193 QWhatsThis::add( mFreeTimeCombo, whatsThis );
00194 mFreeTimeCombo->insertItem(i18n("Busy"));
00195 mFreeTimeCombo->insertItem(i18n("Free"));
00196 classLayout->addWidget(mFreeTimeCombo);
00197 freeTimeLabel->setBuddy( mFreeTimeCombo );
00198 }
00199
00200 void KOEditorGeneralEvent::initInvitationBar(QWidget * parent, QBoxLayout * layout)
00201 {
00202 QBoxLayout *topLayout = new QHBoxLayout( layout );
00203 mInvitationBar = new QFrame( parent );
00204 mInvitationBar->setPaletteBackgroundColor( KGlobalSettings::alternateBackgroundColor() );
00205 topLayout->addWidget( mInvitationBar );
00206
00207 QBoxLayout *barLayout = new QHBoxLayout( mInvitationBar );
00208 barLayout->setSpacing( layout->spacing() );
00209 QLabel *label = new QLabel( i18n("You have not yet definitely responded to this invitation." ), mInvitationBar );
00210 barLayout->addWidget( label );
00211 barLayout->addStretch( 1 );
00212 QPushButton *button = new QPushButton( i18n("Accept"), mInvitationBar );
00213 connect( button, SIGNAL(clicked()), SIGNAL(acceptInvitation()) );
00214 connect( button, SIGNAL(clicked()), mInvitationBar, SLOT(hide()) );
00215 barLayout->addWidget( button );
00216 button = new QPushButton( i18n("Decline"), mInvitationBar );
00217 connect( button, SIGNAL(clicked()), SIGNAL(declineInvitation()) );
00218 connect( button, SIGNAL(clicked()), mInvitationBar, SLOT(hide()) );
00219 barLayout->addWidget( button );
00220
00221 mInvitationBar->hide();
00222 }
00223
00224 void KOEditorGeneralEvent::timeStuffDisable(bool disable)
00225 {
00226 mStartTimeEdit->setEnabled( !disable );
00227 mEndTimeEdit->setEnabled( !disable );
00228
00229 setDuration();
00230 emitDateTimeStr();
00231 }
00232
00233 void KOEditorGeneralEvent::associateTime(bool time)
00234 {
00235 timeStuffDisable(time);
00236
00237 allDayChanged(time);
00238 }
00239
00240 void KOEditorGeneralEvent::setDateTimes( const QDateTime &start, const QDateTime &end )
00241 {
00242
00243
00244 mStartDateEdit->setDate(start.date());
00245
00246 mStartTimeEdit->blockSignals( true );
00247 mStartTimeEdit->setTime(start.time());
00248 mStartTimeEdit->blockSignals( false );
00249 mEndDateEdit->setDate(end.date());
00250 mEndTimeEdit->setTime(end.time());
00251
00252 mCurrStartDateTime = start;
00253 mCurrEndDateTime = end;
00254
00255 setDuration();
00256 emitDateTimeStr();
00257 }
00258
00259 void KOEditorGeneralEvent::startTimeChanged( QTime newtime )
00260 {
00261 kdDebug(5850) << "KOEditorGeneralEvent::startTimeChanged() " << newtime.toString() << endl;
00262
00263 int secsep = mCurrStartDateTime.secsTo(mCurrEndDateTime);
00264
00265 mCurrStartDateTime.setTime(newtime);
00266
00267
00268 mCurrEndDateTime = mCurrStartDateTime.addSecs(secsep);
00269 mEndTimeEdit->setTime(mCurrEndDateTime.time());
00270 mEndDateEdit->setDate(mCurrEndDateTime.date());
00271
00272 emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime);
00273 }
00274
00275 void KOEditorGeneralEvent::endTimeChanged( QTime newtime )
00276 {
00277
00278
00279 QDateTime newdt(mCurrEndDateTime.date(), newtime);
00280 mCurrEndDateTime = newdt;
00281
00282 emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime);
00283 }
00284
00285 void KOEditorGeneralEvent::startDateChanged( const QDate &newdate )
00286 {
00287 if ( !newdate.isValid() )
00288 return;
00289
00290 int daysep = mCurrStartDateTime.daysTo(mCurrEndDateTime);
00291
00292 mCurrStartDateTime.setDate(newdate);
00293
00294
00295 mCurrEndDateTime.setDate(mCurrStartDateTime.date().addDays(daysep));
00296 mEndDateEdit->setDate(mCurrEndDateTime.date());
00297
00298 emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime);
00299 }
00300
00301 void KOEditorGeneralEvent::endDateChanged( const QDate &newdate )
00302 {
00303 if ( !newdate.isValid() )
00304 return;
00305
00306 QDateTime newdt(newdate, mCurrEndDateTime.time());
00307 mCurrEndDateTime = newdt;
00308
00309 emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime);
00310 }
00311
00312 void KOEditorGeneralEvent::setDefaults( const QDateTime &from,
00313 const QDateTime &to, bool allDay)
00314 {
00315 KOEditorGeneral::setDefaults(allDay);
00316
00317 mAlldayEventCheckbox->setChecked(allDay);
00318 timeStuffDisable(allDay);
00319
00320 setDateTimes(from,to);
00321 }
00322
00323 void KOEditorGeneralEvent::readEvent( Event *event, Calendar *calendar, const QDate &date, bool tmpl )
00324 {
00325 QString tmpStr;
00326
00327 mAlldayEventCheckbox->setChecked(event->doesFloat());
00328 timeStuffDisable(event->doesFloat());
00329
00330 if ( !tmpl ) {
00331 QDateTime startDT = event->dtStart();
00332 QDateTime endDT = event->dtEnd();
00333 if ( event->doesRecur() && date.isValid() ) {
00334
00335 QDateTime kdt( date, QTime( 0, 0, 0 ) );
00336 int diffDays = startDT.daysTo( kdt );
00337 kdt = kdt.addSecs( -1 );
00338 startDT.setDate( event->recurrence()->getNextDateTime( kdt ).date() );
00339 if ( event->hasEndDate() ) {
00340 endDT = endDT.addDays( diffDays );
00341 if ( startDT > endDT ) {
00342 startDT.setDate( event->recurrence()->getPreviousDateTime( kdt ).date() );
00343 endDT = startDT.addDays( event->dtStart().daysTo( event->dtEnd() ) );
00344 }
00345 } else {
00346 if ( event->hasDuration() ) {
00347 endDT = startDT.addSecs( event->duration() );
00348 } else {
00349 endDT = startDT;
00350 }
00351 }
00352 }
00353
00354 setDateTimes( startDT, endDT );
00355 }
00356
00357 switch( event->transparency() ) {
00358 case Event::Transparent:
00359 mFreeTimeCombo->setCurrentItem(1);
00360 break;
00361 case Event::Opaque:
00362 mFreeTimeCombo->setCurrentItem(0);
00363 break;
00364 }
00365
00366 updateRecurrenceSummary( event );
00367
00368 Attendee *me = event->attendeeByMails( KOPrefs::instance()->allEmails() );
00369 if ( event->attendeeCount() > 1 &&
00370 me && ( me->status() == Attendee::NeedsAction ||
00371 me->status() == Attendee::Tentative ||
00372 me->status() == Attendee::InProcess ) ) {
00373 mInvitationBar->show();
00374 } else {
00375 mInvitationBar->hide();
00376 }
00377
00378 readIncidence(event, calendar);
00379 }
00380
00381 void KOEditorGeneralEvent::writeEvent(Event *event)
00382 {
00383
00384
00385 writeIncidence(event);
00386
00387 QDate tmpDate;
00388 QTime tmpTime;
00389 QDateTime tmpDT;
00390
00391
00392 QString tmpStr;
00393
00394 if (mAlldayEventCheckbox->isChecked()) {
00395 event->setFloats(true);
00396
00397 tmpDate = mStartDateEdit->date();
00398 tmpTime.setHMS(0,0,0);
00399 tmpDT.setDate(tmpDate);
00400 tmpDT.setTime(tmpTime);
00401 event->setDtStart(tmpDT);
00402
00403 tmpDate = mEndDateEdit->date();
00404 tmpTime.setHMS(0,0,0);
00405 tmpDT.setDate(tmpDate);
00406 tmpDT.setTime(tmpTime);
00407 event->setDtEnd(tmpDT);
00408 } else {
00409 event->setFloats(false);
00410
00411
00412 tmpDate = mEndDateEdit->date();
00413 tmpTime = mEndTimeEdit->getTime();
00414 tmpDT.setDate(tmpDate);
00415 tmpDT.setTime(tmpTime);
00416 event->setDtEnd(tmpDT);
00417
00418
00419 tmpDate = mStartDateEdit->date();
00420 tmpTime = mStartTimeEdit->getTime();
00421 tmpDT.setDate(tmpDate);
00422 tmpDT.setTime(tmpTime);
00423 event->setDtStart(tmpDT);
00424 }
00425
00426 event->setTransparency(mFreeTimeCombo->currentItem() > 0
00427 ? KCal::Event::Transparent
00428 : KCal::Event::Opaque);
00429
00430
00431 }
00432
00433 void KOEditorGeneralEvent::setDuration()
00434 {
00435 QString tmpStr, catStr;
00436 int hourdiff, minutediff;
00437
00438
00439 if(mCurrEndDateTime >= mCurrStartDateTime) {
00440
00441 if (mAlldayEventCheckbox->isChecked()) {
00442 int daydiff = mCurrStartDateTime.date().daysTo(mCurrEndDateTime.date()) + 1;
00443 tmpStr = i18n("Duration: ");
00444 tmpStr.append(i18n("1 Day","%n Days",daydiff));
00445 } else {
00446 hourdiff = mCurrStartDateTime.date().daysTo(mCurrEndDateTime.date()) * 24;
00447 hourdiff += mCurrEndDateTime.time().hour() -
00448 mCurrStartDateTime.time().hour();
00449 minutediff = mCurrEndDateTime.time().minute() -
00450 mCurrStartDateTime.time().minute();
00451
00452 if (minutediff < 0 && hourdiff > 0) {
00453 hourdiff -= 1;
00454 minutediff += 60;
00455 }
00456 if (hourdiff || minutediff){
00457 tmpStr = i18n("Duration: ");
00458 if (hourdiff){
00459 catStr = i18n("1 hour","%n hours",hourdiff);
00460 tmpStr.append(catStr);
00461 }
00462 if (hourdiff && minutediff){
00463 tmpStr += i18n(", ");
00464 }
00465 if (minutediff){
00466 catStr = i18n("1 minute","%n minutes",minutediff);
00467 tmpStr += catStr;
00468 }
00469 } else tmpStr = "";
00470 }
00471 }
00472 mDurationLabel->setText(tmpStr);
00473 QWhatsThis::add( mDurationLabel,
00474 i18n("Shows the duration of the event or to-do with the "
00475 "current start and end dates and times.") );
00476 }
00477
00478 void KOEditorGeneralEvent::emitDateTimeStr()
00479 {
00480 KLocale *l = KGlobal::locale();
00481
00482 QString from,to;
00483 if (mAlldayEventCheckbox->isChecked()) {
00484 from = l->formatDate(mCurrStartDateTime.date());
00485 to = l->formatDate(mCurrEndDateTime.date());
00486 } else {
00487 from = l->formatDateTime(mCurrStartDateTime);
00488 to = l->formatDateTime(mCurrEndDateTime);
00489 }
00490
00491 QString str = i18n("From: %1 To: %2 %3").arg(from).arg(to)
00492 .arg(mDurationLabel->text());
00493
00494 emit dateTimeStrChanged(str);
00495 }
00496
00497 bool KOEditorGeneralEvent::validateInput()
00498 {
00499
00500
00501 if (!mAlldayEventCheckbox->isChecked()) {
00502 if (!mStartTimeEdit->inputIsValid()) {
00503 KMessageBox::sorry( 0,
00504 i18n("Please specify a valid start time, for example '%1'.")
00505 .arg( KGlobal::locale()->formatTime( QTime::currentTime() ) ) );
00506 return false;
00507 }
00508
00509 if (!mEndTimeEdit->inputIsValid()) {
00510 KMessageBox::sorry( 0,
00511 i18n("Please specify a valid end time, for example '%1'.")
00512 .arg( KGlobal::locale()->formatTime( QTime::currentTime() ) ) );
00513 return false;
00514 }
00515 }
00516
00517 if (!mStartDateEdit->date().isValid()) {
00518 KMessageBox::sorry( 0,
00519 i18n("Please specify a valid start date, for example '%1'.")
00520 .arg( KGlobal::locale()->formatDate( QDate::currentDate() ) ) );
00521 return false;
00522 }
00523
00524 if (!mEndDateEdit->date().isValid()) {
00525 KMessageBox::sorry( 0,
00526 i18n("Please specify a valid end date, for example '%1'.")
00527 .arg( KGlobal::locale()->formatDate( QDate::currentDate() ) ) );
00528 return false;
00529 }
00530
00531 QDateTime startDt,endDt;
00532 startDt.setDate(mStartDateEdit->date());
00533 endDt.setDate(mEndDateEdit->date());
00534 if (!mAlldayEventCheckbox->isChecked()) {
00535 startDt.setTime(mStartTimeEdit->getTime());
00536 endDt.setTime(mEndTimeEdit->getTime());
00537 }
00538
00539 if ( startDt > endDt ) {
00540 KMessageBox::sorry(
00541 0,
00542 i18n( "The event ends before it starts.\n"
00543 "Please correct dates and times." ) );
00544 return false;
00545 }
00546
00547 return KOEditorGeneral::validateInput();
00548 }
00549
00550 void KOEditorGeneralEvent::updateRecurrenceSummary( Event *event )
00551 {
00552 if ( event->doesRecur() ) {
00553 mRecEditLabel->setText( IncidenceFormatter::recurrenceString( event ) );
00554 } else {
00555 mRecEditLabel->setText( QString() );
00556 }
00557 }