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