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 <tqtooltip.h>
00026 #include <tqlayout.h>
00027 #include <tqvbox.h>
00028 #include <tqbuttongroup.h>
00029 #include <tqvgroupbox.h>
00030 #include <tqwidgetstack.h>
00031 #include <tqspinbox.h>
00032 #include <tqdatetime.h>
00033 #include <tqlabel.h>
00034 #include <tqcheckbox.h>
00035 #include <tqcombobox.h>
00036 #include <tqpushbutton.h>
00037 #include <tqwhatsthis.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(TQObject* parent,
00060 const char* name) :
00061 KOEditorGeneral( parent, name)
00062 {
00063 connect( this, TQT_SIGNAL( dateTimesChanged( const TQDateTime &, const TQDateTime & )),
00064 TQT_SLOT( setDuration() ) );
00065 connect( this, TQT_SIGNAL( dateTimesChanged( const TQDateTime &, const TQDateTime & )),
00066 TQT_SLOT( emitDateTimeStr() ));
00067 }
00068
00069 KOEditorGeneralEvent::~KOEditorGeneralEvent()
00070 {
00071 }
00072
00073 void KOEditorGeneralEvent::finishSetup()
00074 {
00075 TQWidget::setTabOrder( mSummaryEdit, mLocationEdit );
00076 TQWidget::setTabOrder( mLocationEdit, mStartDateEdit );
00077 TQWidget::setTabOrder( mStartDateEdit, mStartTimeEdit );
00078 TQWidget::setTabOrder( mStartTimeEdit, mEndDateEdit );
00079 TQWidget::setTabOrder( mEndDateEdit, mEndTimeEdit );
00080 TQWidget::setTabOrder( mEndTimeEdit, mAlldayEventCheckbox );
00081 TQWidget::setTabOrder( mAlldayEventCheckbox, mRecEditButton );
00082 TQWidget::setTabOrder( mRecEditButton, mAlarmButton );
00083 TQWidget::setTabOrder( mAlarmButton, mAlarmTimeEdit );
00084 TQWidget::setTabOrder( mAlarmTimeEdit, mAlarmIncrCombo );
00085 TQWidget::setTabOrder( mAlarmIncrCombo, mAlarmAdvancedButton );
00086 TQWidget::setTabOrder( mAlarmAdvancedButton, mFreeTimeCombo );
00087 TQWidget::setTabOrder( mFreeTimeCombo, mDescriptionEdit );
00088 TQWidget::setTabOrder( mDescriptionEdit, mCategoriesButton );
00089 TQWidget::setTabOrder( mCategoriesButton, mSecrecyCombo );
00090
00091 mSummaryEdit->setFocus();
00092 }
00093
00094 void KOEditorGeneralEvent::initTime(TQWidget *parent,TQBoxLayout *topLayout)
00095 {
00096 TQBoxLayout *timeLayout = new TQVBoxLayout(topLayout);
00097
00098 TQGroupBox *timeGroupBox = new TQGroupBox(1,Qt::Horizontal,
00099 i18n("Date && Time"),parent);
00100 TQWhatsThis::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 TQFrame *timeBoxFrame = new TQFrame(timeGroupBox);
00106
00107 TQGridLayout *layoutTimeBox = new TQGridLayout( timeBoxFrame );
00108 layoutTimeBox->setSpacing(topLayout->spacing());
00109 layoutTimeBox->setColStretch( 3, 1 );
00110
00111 mStartDateLabel = new TQLabel(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 TQLabel(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 TQCheckBox(i18n("All-&day"),timeBoxFrame);
00132 layoutTimeBox->addWidget( mAlldayEventCheckbox, 0, 3 );
00133 connect(mAlldayEventCheckbox, TQT_SIGNAL(toggled(bool)),TQT_SLOT(associateTime(bool)));
00134
00135 mDurationLabel = new TQLabel( timeBoxFrame );
00136 layoutTimeBox->addWidget( mDurationLabel, 1, 3 );
00137
00138
00139 connect(mStartTimeEdit, TQT_SIGNAL(timeChanged(TQTime)),
00140 this, TQT_SLOT(startTimeChanged(TQTime)));
00141 connect(mEndTimeEdit, TQT_SIGNAL(timeChanged(TQTime)),
00142 this, TQT_SLOT(endTimeChanged(TQTime)));
00143
00144
00145 connect(mStartDateEdit, TQT_SIGNAL(dateChanged(const TQDate&)),
00146 this, TQT_SLOT(startDateChanged(const TQDate&)));
00147 connect(mEndDateEdit, TQT_SIGNAL(dateChanged(const TQDate&)),
00148 this, TQT_SLOT(endDateChanged(const TQDate&)));
00149
00150 TQLabel *label = new TQLabel( i18n( "Recurrence:" ), timeBoxFrame );
00151 layoutTimeBox->addWidget( label, 2, 0 );
00152 TQBoxLayout *recLayout = new TQHBoxLayout();
00153 layoutTimeBox->addMultiCellLayout( recLayout, 2, 2, 1, 4 );
00154 mRecEditButton = new TQPushButton( timeBoxFrame );
00155 mRecEditButton->setIconSet( KOGlobals::self()->smallIconSet( "recur", 16 ) );
00156 recLayout->addWidget( mRecEditButton );
00157 connect( mRecEditButton, TQT_SIGNAL(clicked()), TQT_SIGNAL(editRecurrence()) );
00158 mRecEditLabel = new TQLabel( TQString(), timeBoxFrame );
00159 recLayout->addWidget( mRecEditLabel );
00160 recLayout->addStretch( 1 );
00161
00162 label = new TQLabel( i18n("Reminder:"), timeBoxFrame );
00163 layoutTimeBox->addWidget( label, 3, 0 );
00164 TQBoxLayout *alarmLineLayout = new TQHBoxLayout();
00165 layoutTimeBox->addMultiCellLayout( alarmLineLayout, 3, 3, 1, 4 );
00166 initAlarm( timeBoxFrame, alarmLineLayout );
00167 alarmLineLayout->addStretch( 1 );
00168
00169 TQBoxLayout *secLayout = new TQHBoxLayout();
00170 layoutTimeBox->addLayout( secLayout, 0, 4 );
00171 initSecrecy( timeBoxFrame, secLayout );
00172
00173 TQBoxLayout *classLayout = new TQHBoxLayout();
00174 layoutTimeBox->addLayout( classLayout, 1, 4 );
00175 initClass( timeBoxFrame, classLayout );
00176 }
00177
00178 void KOEditorGeneralEvent::initClass(TQWidget *parent,TQBoxLayout *topLayout)
00179 {
00180 TQBoxLayout *classLayout = new TQHBoxLayout(topLayout);
00181
00182 TQLabel *freeTimeLabel = new TQLabel(i18n("S&how time as:"),parent);
00183 TQString whatsThis = i18n("Sets how this time will appear on your Free/Busy "
00184 "information.");
00185 TQWhatsThis::add( freeTimeLabel, whatsThis );
00186 classLayout->addWidget(freeTimeLabel);
00187
00188 mFreeTimeCombo = new TQComboBox(false, parent);
00189 TQWhatsThis::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(TQWidget * parent, TQBoxLayout * layout)
00197 {
00198 TQBoxLayout *topLayout = new TQHBoxLayout( layout );
00199 mInvitationBar = new TQFrame( parent );
00200 mInvitationBar->setPaletteBackgroundColor( KGlobalSettings::alternateBackgroundColor() );
00201 topLayout->addWidget( mInvitationBar );
00202
00203 TQBoxLayout *barLayout = new TQHBoxLayout( mInvitationBar );
00204 barLayout->setSpacing( layout->spacing() );
00205 TQLabel *label = new TQLabel( i18n("You have not yet definitely responded to this invitation." ), mInvitationBar );
00206 barLayout->addWidget( label );
00207 barLayout->addStretch( 1 );
00208 TQPushButton *button = new TQPushButton( i18n("Accept"), mInvitationBar );
00209 connect( button, TQT_SIGNAL(clicked()), TQT_SIGNAL(acceptInvitation()) );
00210 connect( button, TQT_SIGNAL(clicked()), mInvitationBar, TQT_SLOT(hide()) );
00211 barLayout->addWidget( button );
00212 button = new TQPushButton( i18n("Decline"), mInvitationBar );
00213 connect( button, TQT_SIGNAL(clicked()), TQT_SIGNAL(declineInvitation()) );
00214 connect( button, TQT_SIGNAL(clicked()), mInvitationBar, TQT_SLOT(hide()) );
00215 barLayout->addWidget( button );
00216
00217 mInvitationBar->hide();
00218 }
00219
00220 void KOEditorGeneralEvent::timeStuffDisable(bool disable)
00221 {
00222 mStartTimeEdit->setEnabled( !disable );
00223 mEndTimeEdit->setEnabled( !disable );
00224
00225 setDuration();
00226 emitDateTimeStr();
00227 }
00228
00229 void KOEditorGeneralEvent::associateTime(bool time)
00230 {
00231 timeStuffDisable(time);
00232 allDayChanged(time);
00233 }
00234
00235 void KOEditorGeneralEvent::setDateTimes( const TQDateTime &start, const TQDateTime &end )
00236 {
00237
00238
00239 mStartDateEdit->setDate(start.date());
00240
00241 mStartTimeEdit->blockSignals( true );
00242 mStartTimeEdit->setTime(start.time());
00243 mStartTimeEdit->blockSignals( false );
00244 mEndDateEdit->setDate(end.date());
00245 mEndTimeEdit->setTime(end.time());
00246
00247 mCurrStartDateTime = start;
00248 mCurrEndDateTime = end;
00249
00250 setDuration();
00251 emitDateTimeStr();
00252 }
00253
00254 void KOEditorGeneralEvent::startTimeChanged( TQTime newtime )
00255 {
00256 kdDebug(5850) << "KOEditorGeneralEvent::startTimeChanged() " << TQString(newtime.toString()) << endl;
00257
00258 int secsep = mCurrStartDateTime.secsTo(mCurrEndDateTime);
00259
00260 mCurrStartDateTime.setTime(newtime);
00261
00262
00263 mCurrEndDateTime = mCurrStartDateTime.addSecs(secsep);
00264 mEndTimeEdit->setTime(mCurrEndDateTime.time());
00265 mEndDateEdit->setDate(mCurrEndDateTime.date());
00266
00267 emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime);
00268 }
00269
00270 void KOEditorGeneralEvent::endTimeChanged( TQTime newtime )
00271 {
00272
00273
00274 TQDateTime newdt(mCurrEndDateTime.date(), newtime);
00275 mCurrEndDateTime = newdt;
00276
00277 emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime);
00278 }
00279
00280 void KOEditorGeneralEvent::startDateChanged( const TQDate &newdate )
00281 {
00282 if ( !newdate.isValid() )
00283 return;
00284
00285 int daysep = mCurrStartDateTime.daysTo(mCurrEndDateTime);
00286
00287 mCurrStartDateTime.setDate(newdate);
00288
00289
00290 mCurrEndDateTime.setDate(mCurrStartDateTime.date().addDays(daysep));
00291 mEndDateEdit->setDate(mCurrEndDateTime.date());
00292
00293 emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime);
00294 }
00295
00296 void KOEditorGeneralEvent::endDateChanged( const TQDate &newdate )
00297 {
00298 if ( !newdate.isValid() )
00299 return;
00300
00301 TQDateTime newdt(newdate, mCurrEndDateTime.time());
00302 mCurrEndDateTime = newdt;
00303
00304 emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime);
00305 }
00306
00307 void KOEditorGeneralEvent::setDefaults( const TQDateTime &from,
00308 const TQDateTime &to, bool allDay)
00309 {
00310 KOEditorGeneral::setDefaults(allDay);
00311
00312 mAlldayEventCheckbox->setChecked(allDay);
00313 timeStuffDisable(allDay);
00314
00315 setDateTimes(from,to);
00316 }
00317
00318 void KOEditorGeneralEvent::readEvent( Event *event, Calendar *calendar, const TQDate &date, bool tmpl )
00319 {
00320 TQString tmpStr;
00321
00322 mAlldayEventCheckbox->setChecked(event->doesFloat());
00323 timeStuffDisable(event->doesFloat());
00324
00325 if ( !tmpl ) {
00326 TQDateTime startDT = event->dtStart();
00327 TQDateTime endDT = event->dtEnd();
00328 if ( event->doesRecur() && date.isValid() ) {
00329
00330 TQDateTime kdt( date, TQTime( 0, 0, 0 ) );
00331 const int eventLength = startDT.daysTo( endDT );
00332 kdt = kdt.addSecs( -1 );
00333 startDT.setDate( event->recurrence()->getNextDateTime( kdt ).date() );
00334 if ( event->hasEndDate() ) {
00335 endDT.setDate( startDT.addDays( eventLength ).date() );
00336 } else {
00337 if ( event->hasDuration() ) {
00338 endDT = startDT.addSecs( event->duration() );
00339 } else {
00340 endDT = startDT;
00341 }
00342 }
00343 }
00344
00345 setDateTimes( startDT, endDT );
00346 }
00347
00348 switch( event->transparency() ) {
00349 case Event::Transparent:
00350 mFreeTimeCombo->setCurrentItem(1);
00351 break;
00352 case Event::Opaque:
00353 mFreeTimeCombo->setCurrentItem(0);
00354 break;
00355 }
00356
00357 updateRecurrenceSummary( event );
00358
00359 Attendee *me = event->attendeeByMails( KOPrefs::instance()->allEmails() );
00360 if ( event->attendeeCount() > 1 &&
00361 me && ( me->status() == Attendee::NeedsAction ||
00362 me->status() == Attendee::Tentative ||
00363 me->status() == Attendee::InProcess ) ) {
00364 mInvitationBar->show();
00365 } else {
00366 mInvitationBar->hide();
00367 }
00368
00369 readIncidence(event, calendar);
00370 }
00371
00372 void KOEditorGeneralEvent::writeEvent(Event *event)
00373 {
00374
00375
00376 writeIncidence(event);
00377
00378 TQDate tmpDate;
00379 TQTime tmpTime;
00380 TQDateTime tmpDT;
00381
00382
00383 TQString tmpStr;
00384
00385 if (mAlldayEventCheckbox->isChecked()) {
00386 event->setFloats(true);
00387
00388 tmpDate = mStartDateEdit->date();
00389 tmpTime.setHMS(0,0,0);
00390 tmpDT.setDate(tmpDate);
00391 tmpDT.setTime(tmpTime);
00392 event->setDtStart(tmpDT);
00393
00394 tmpDate = mEndDateEdit->date();
00395 tmpTime.setHMS(0,0,0);
00396 tmpDT.setDate(tmpDate);
00397 tmpDT.setTime(tmpTime);
00398 event->setDtEnd(tmpDT);
00399 } else {
00400 event->setFloats(false);
00401
00402
00403 tmpDate = mEndDateEdit->date();
00404 tmpTime = mEndTimeEdit->getTime();
00405 tmpDT.setDate(tmpDate);
00406 tmpDT.setTime(tmpTime);
00407 event->setDtEnd(tmpDT);
00408
00409
00410 tmpDate = mStartDateEdit->date();
00411 tmpTime = mStartTimeEdit->getTime();
00412 tmpDT.setDate(tmpDate);
00413 tmpDT.setTime(tmpTime);
00414 event->setDtStart(tmpDT);
00415 }
00416
00417 event->setTransparency(mFreeTimeCombo->currentItem() > 0
00418 ? KCal::Event::Transparent
00419 : KCal::Event::Opaque);
00420
00421
00422 }
00423
00424 void KOEditorGeneralEvent::setDuration()
00425 {
00426 TQString tmpStr, catStr;
00427 int hourdiff, minutediff;
00428
00429
00430 if(mCurrEndDateTime >= mCurrStartDateTime) {
00431
00432 if (mAlldayEventCheckbox->isChecked()) {
00433 int daydiff = mCurrStartDateTime.date().daysTo(mCurrEndDateTime.date()) + 1;
00434 tmpStr = i18n("Duration: ");
00435 tmpStr.append(i18n("1 Day","%n Days",daydiff));
00436 } else {
00437 hourdiff = mCurrStartDateTime.date().daysTo(mCurrEndDateTime.date()) * 24;
00438 hourdiff += mCurrEndDateTime.time().hour() -
00439 mCurrStartDateTime.time().hour();
00440 minutediff = mCurrEndDateTime.time().minute() -
00441 mCurrStartDateTime.time().minute();
00442
00443 if (minutediff < 0 && hourdiff > 0) {
00444 hourdiff -= 1;
00445 minutediff += 60;
00446 }
00447 if (hourdiff || minutediff){
00448 tmpStr = i18n("Duration: ");
00449 if (hourdiff){
00450 catStr = i18n("1 hour","%n hours",hourdiff);
00451 tmpStr.append(catStr);
00452 }
00453 if (hourdiff && minutediff){
00454 tmpStr += i18n(", ");
00455 }
00456 if (minutediff){
00457 catStr = i18n("1 minute","%n minutes",minutediff);
00458 tmpStr += catStr;
00459 }
00460 } else tmpStr = "";
00461 }
00462 }
00463 mDurationLabel->setText(tmpStr);
00464 TQWhatsThis::add( mDurationLabel,
00465 i18n("Shows the duration of the event or to-do with the "
00466 "current start and end dates and times.") );
00467 }
00468
00469 void KOEditorGeneralEvent::emitDateTimeStr()
00470 {
00471 KLocale *l = KGlobal::locale();
00472
00473 TQString from,to;
00474 if (mAlldayEventCheckbox->isChecked()) {
00475 from = l->formatDate(mCurrStartDateTime.date());
00476 to = l->formatDate(mCurrEndDateTime.date());
00477 } else {
00478 from = l->formatDateTime(mCurrStartDateTime);
00479 to = l->formatDateTime(mCurrEndDateTime);
00480 }
00481
00482 TQString str = i18n("From: %1 To: %2 %3").arg(from).arg(to)
00483 .arg(mDurationLabel->text());
00484
00485 emit dateTimeStrChanged(str);
00486 }
00487
00488 bool KOEditorGeneralEvent::validateInput()
00489 {
00490
00491
00492 if (!mAlldayEventCheckbox->isChecked()) {
00493 if (!mStartTimeEdit->inputIsValid()) {
00494 KMessageBox::sorry( 0,
00495 i18n("Please specify a valid start time, for example '%1'.")
00496 .arg( KGlobal::locale()->formatTime( TQTime::currentTime() ) ) );
00497 return false;
00498 }
00499
00500 if (!mEndTimeEdit->inputIsValid()) {
00501 KMessageBox::sorry( 0,
00502 i18n("Please specify a valid end time, for example '%1'.")
00503 .arg( KGlobal::locale()->formatTime( TQTime::currentTime() ) ) );
00504 return false;
00505 }
00506 }
00507
00508 if (!mStartDateEdit->date().isValid()) {
00509 KMessageBox::sorry( 0,
00510 i18n("Please specify a valid start date, for example '%1'.")
00511 .arg( KGlobal::locale()->formatDate( TQDate::currentDate() ) ) );
00512 return false;
00513 }
00514
00515 if (!mEndDateEdit->date().isValid()) {
00516 KMessageBox::sorry( 0,
00517 i18n("Please specify a valid end date, for example '%1'.")
00518 .arg( KGlobal::locale()->formatDate( TQDate::currentDate() ) ) );
00519 return false;
00520 }
00521
00522 TQDateTime startDt,endDt;
00523 startDt.setDate(mStartDateEdit->date());
00524 endDt.setDate(mEndDateEdit->date());
00525 if (!mAlldayEventCheckbox->isChecked()) {
00526 startDt.setTime(mStartTimeEdit->getTime());
00527 endDt.setTime(mEndTimeEdit->getTime());
00528 }
00529
00530 if ( startDt > endDt ) {
00531 KMessageBox::sorry(
00532 0,
00533 i18n( "The event ends before it starts.\n"
00534 "Please correct dates and times." ) );
00535 return false;
00536 }
00537
00538 return KOEditorGeneral::validateInput();
00539 }
00540
00541 void KOEditorGeneralEvent::updateRecurrenceSummary( Event *event )
00542 {
00543 if ( event->doesRecur() ) {
00544 mRecEditLabel->setText( IncidenceFormatter::recurrenceString( event ) );
00545 } else {
00546 mRecEditLabel->setText( TQString() );
00547 }
00548 }