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 <qfiledialog.h>
00027 #include <qlayout.h>
00028 #include <qvbox.h>
00029 #include <qbuttongroup.h>
00030 #include <qvgroupbox.h>
00031 #include <qwidgetstack.h>
00032 #include <qdatetime.h>
00033 #include <qcheckbox.h>
00034 #include <qlabel.h>
00035 #include <qspinbox.h>
00036 #include <qpushbutton.h>
00037 #include <qwhatsthis.h>
00038
00039 #include <kglobal.h>
00040 #include <klocale.h>
00041 #include <kiconloader.h>
00042 #include <kmessagebox.h>
00043 #include <kdebug.h>
00044 #include <kstandarddirs.h>
00045 #include <kfiledialog.h>
00046 #include <ktextedit.h>
00047
00048 #include <libkcal/todo.h>
00049
00050 #include <libkdepim/kdateedit.h>
00051
00052 #include "koprefs.h"
00053 #include "koglobals.h"
00054 #include "ktimeedit.h"
00055
00056 #include "koeditorgeneraltodo.h"
00057 #include "koeditorgeneraltodo.moc"
00058
00059 KOEditorGeneralTodo::KOEditorGeneralTodo(QObject* parent,
00060 const char* name)
00061 : KOEditorGeneral( parent, name)
00062 {
00063 setType( "Todo" );
00064 }
00065
00066 KOEditorGeneralTodo::~KOEditorGeneralTodo()
00067 {
00068 }
00069
00070 void KOEditorGeneralTodo::finishSetup()
00071 {
00072 QWidget::setTabOrder( mSummaryEdit, mLocationEdit );
00073 QWidget::setTabOrder( mLocationEdit, mStartCheck );
00074 QWidget::setTabOrder( mStartCheck, mStartDateEdit );
00075 QWidget::setTabOrder( mStartDateEdit, mStartTimeEdit );
00076 QWidget::setTabOrder( mStartTimeEdit, mDueCheck );
00077 QWidget::setTabOrder( mDueCheck, mDueDateEdit );
00078 QWidget::setTabOrder( mDueDateEdit, mDueTimeEdit );
00079 QWidget::setTabOrder( mDueTimeEdit, mTimeButton );
00080 QWidget::setTabOrder( mTimeButton, mCompletedCombo );
00081 QWidget::setTabOrder( mCompletedCombo, mPriorityCombo );
00082 QWidget::setTabOrder( mPriorityCombo, mAlarmButton );
00083 QWidget::setTabOrder( mAlarmButton, mAlarmTimeEdit );
00084 QWidget::setTabOrder( mAlarmTimeEdit, mAlarmIncrCombo );
00085
00086 QWidget::setTabOrder( mAlarmIncrCombo, mAlarmEditButton );
00087
00088
00089 QWidget::setTabOrder( mAlarmEditButton, mDescriptionEdit );
00090 QWidget::setTabOrder( mDescriptionEdit, mCategoriesButton );
00091 QWidget::setTabOrder( mCategoriesButton, mSecrecyCombo );
00092
00093
00094 mSummaryEdit->setFocus();
00095 }
00096
00097 void KOEditorGeneralTodo::initTime(QWidget *parent,QBoxLayout *topLayout)
00098 {
00099 kdDebug(5850) << k_funcinfo << endl;
00100 QBoxLayout *timeLayout = new QVBoxLayout(topLayout);
00101
00102 QGroupBox *timeGroupBox = new QGroupBox(1,QGroupBox::Horizontal,
00103 i18n("Date && Time"),parent);
00104 timeLayout->addWidget(timeGroupBox);
00105
00106 QFrame *timeBoxFrame = new QFrame(timeGroupBox);
00107 QWhatsThis::add( timeBoxFrame,
00108 i18n("Sets options for due and start dates and times "
00109 "for this to-do.") );
00110
00111 QGridLayout *layoutTimeBox = new QGridLayout(timeBoxFrame,1,1);
00112 layoutTimeBox->setSpacing(topLayout->spacing());
00113
00114
00115 QString whatsThis = i18n("Sets the start date for this to-do");
00116 mStartCheck = new QCheckBox(i18n("Sta&rt:"),timeBoxFrame);
00117 QWhatsThis::add( mStartCheck, whatsThis );
00118 layoutTimeBox->addWidget(mStartCheck,0,0);
00119 connect(mStartCheck,SIGNAL(toggled(bool)),SLOT(enableStartEdit(bool)));
00120 connect(mStartCheck,SIGNAL(toggled(bool)),SLOT(startDateModified()));
00121
00122 mStartDateEdit = new KDateEdit(timeBoxFrame);
00123 QWhatsThis::add( mStartDateEdit, whatsThis );
00124 layoutTimeBox->addWidget(mStartDateEdit,0,1);
00125 connect(mStartDateEdit,SIGNAL(dateChanged(const QDate&)),SLOT(startDateModified()));
00126
00127 mStartTimeEdit = new KTimeEdit(timeBoxFrame);
00128 QWhatsThis::add( mStartTimeEdit,
00129 i18n("Sets the start time for this to-do.") );
00130 layoutTimeBox->addWidget(mStartTimeEdit,0,2);
00131 connect(mStartTimeEdit,SIGNAL(timeChanged(QTime)),SLOT(startDateModified()));
00132
00133 whatsThis = i18n("Sets the due date for this to-do.");
00134 mDueCheck = new QCheckBox(i18n("&Due:"),timeBoxFrame);
00135 QWhatsThis::add( mDueCheck, whatsThis );
00136 layoutTimeBox->addWidget(mDueCheck,1,0);
00137 connect(mDueCheck,SIGNAL(toggled(bool)),SLOT(enableDueEdit(bool)));
00138 connect(mDueCheck,SIGNAL(toggled(bool)),SLOT(showAlarm()));
00139 connect(mDueCheck,SIGNAL(toggled(bool)),SIGNAL(dueDateEditToggle(bool)));
00140 connect(mDueCheck,SIGNAL(toggled(bool)),SLOT(dateChanged()));
00141
00142 mDueDateEdit = new KDateEdit(timeBoxFrame);
00143 QWhatsThis::add( mDueDateEdit, whatsThis );
00144 layoutTimeBox->addWidget(mDueDateEdit,1,1);
00145 connect(mDueDateEdit,SIGNAL(dateChanged(const QDate&)),SLOT(dateChanged()));
00146
00147 mDueTimeEdit = new KTimeEdit(timeBoxFrame);
00148 QWhatsThis::add( mDueTimeEdit,
00149 i18n("Sets the due time for this to-do.") );
00150 layoutTimeBox->addWidget(mDueTimeEdit,1,2);
00151 connect(mDueTimeEdit,SIGNAL(timeChanged( QTime )),SLOT(dateChanged()));
00152
00153 mTimeButton = new QCheckBox(i18n("Ti&me associated"),timeBoxFrame);
00154 QWhatsThis::add( mTimeButton,
00155 i18n("Sets whether or not this to-do's start and due dates "
00156 "have times associated with them.") );
00157 layoutTimeBox->addMultiCellWidget(mTimeButton,2,2,0,2);
00158
00159 connect(mTimeButton,SIGNAL(toggled(bool)),SLOT(enableTimeEdits(bool)));
00160 connect(mTimeButton,SIGNAL(toggled(bool)),SLOT(dateChanged()));
00161
00162
00163 layoutTimeBox->setColStretch(3,1);
00164
00165 QBoxLayout *secLayout = new QHBoxLayout();
00166 layoutTimeBox->addLayout( secLayout, 0, 4 );
00167 initSecrecy( timeBoxFrame, secLayout );
00168 }
00169
00170
00171 void KOEditorGeneralTodo::initCompletion(QWidget *parent, QBoxLayout *topLayout)
00172 {
00173 QString whatsThis = i18n("Sets the current completion status of this to-do "
00174 "as a percentage.");
00175 mCompletedCombo = new QComboBox(parent);
00176 QWhatsThis::add( mCompletedCombo, whatsThis );
00177 for (int i = 0; i <= 100; i+=10) {
00178
00179 QString label = i18n("Percent complete", "%1 %").arg (i);
00180 mCompletedCombo->insertItem(label);
00181 }
00182 connect(mCompletedCombo,SIGNAL(activated(int)),SLOT(completedChanged(int)));
00183 topLayout->addWidget(mCompletedCombo);
00184
00185 mCompletedLabel = new QLabel(i18n("co&mpleted"),parent);
00186 topLayout->addWidget(mCompletedLabel);
00187 mCompletedLabel->setBuddy( mCompletedCombo );
00188 mCompletionDateEdit = new KDateEdit( parent );
00189 mCompletionDateEdit->hide();
00190 topLayout->addWidget( mCompletionDateEdit );
00191 mCompletionTimeEdit = new KTimeEdit( parent, QTime() );
00192 mCompletionTimeEdit->hide();
00193 topLayout->addWidget( mCompletionTimeEdit );
00194 }
00195
00196 void KOEditorGeneralTodo::initPriority(QWidget *parent, QBoxLayout *topLayout)
00197 {
00198 QString whatsThis = i18n("Sets the priority of this to-do on a scale "
00199 "from one to nine, with one being the highest "
00200 "priority, five being a medium priority, and "
00201 "nine being the lowest. In programs that have a "
00202 "different scale, the numbers will be adjusted "
00203 "to match the appropriate scale.");
00204 QLabel *priorityLabel = new QLabel(i18n("&Priority:"),parent);
00205 topLayout->addWidget(priorityLabel);
00206
00207 mPriorityCombo = new QComboBox(parent);
00208 mPriorityCombo->insertItem(i18n("unspecified"));
00209 mPriorityCombo->insertItem(i18n("1 (highest)"));
00210 mPriorityCombo->insertItem(i18n("2"));
00211 mPriorityCombo->insertItem(i18n("3"));
00212 mPriorityCombo->insertItem(i18n("4"));
00213 mPriorityCombo->insertItem(i18n("5 (medium)"));
00214 mPriorityCombo->insertItem(i18n("6"));
00215 mPriorityCombo->insertItem(i18n("7"));
00216 mPriorityCombo->insertItem(i18n("8"));
00217 mPriorityCombo->insertItem(i18n("9 (lowest)"));
00218 topLayout->addWidget(mPriorityCombo);
00219 priorityLabel->setBuddy( mPriorityCombo );
00220 }
00221
00222 void KOEditorGeneralTodo::initStatus(QWidget *parent,QBoxLayout *topLayout)
00223 {
00224 QBoxLayout *statusLayout = new QHBoxLayout(topLayout);
00225
00226 initCompletion( parent, statusLayout );
00227
00228 statusLayout->addStretch( 1 );
00229
00230 initPriority( parent, statusLayout );
00231 }
00232
00233 void KOEditorGeneralTodo::setDefaults( const QDateTime &due, bool allDay )
00234 {
00235 kdDebug(5850) << k_funcinfo << due <<endl;
00236 KOEditorGeneral::setDefaults(allDay);
00237
00238 mTimeButton->setChecked( !allDay );
00239 mTimeButton->setEnabled( mTimeButton->isChecked() );
00240
00241 enableTimeEdits( !allDay );
00242
00243 mDueCheck->setChecked( due.isValid() );
00244 enableDueEdit( due.isValid() );
00245
00246 mStartCheck->setChecked(false);
00247 enableStartEdit(false);
00248
00249 if ( due.isValid() ) {
00250 mDueDateEdit->setDate( due.date() );
00251 mDueTimeEdit->setTime( due.time() );
00252 } else {
00253
00254 mDueDateEdit->setDate( QDate::currentDate().addDays(1) );
00255 mDueTimeEdit->setTime( QTime::currentTime() );
00256 }
00257
00258 if ( !due.isValid() || (QDateTime::currentDateTime() < due) ) {
00259 mStartDateEdit->setDate( QDate::currentDate() );
00260 mStartTimeEdit->setTime( QTime::currentTime() );
00261 } else {
00262 mStartDateEdit->setDate( due.date().addDays( -1 ) );
00263 mStartTimeEdit->setTime( due.time() );
00264 }
00265 mStartDateModified = false;
00266
00267 mPriorityCombo->setCurrentItem(5);
00268
00269 mCompletedCombo->setCurrentItem(0);
00270 }
00271
00272 void KOEditorGeneralTodo::readTodo(Todo *todo, Calendar *calendar, const QDate &date )
00273 {
00274 KOEditorGeneral::readIncidence(todo, calendar);
00275
00276 QDateTime dueDT;
00277
00278 if (todo->hasDueDate()) {
00279 enableAlarm( true );
00280 dueDT = todo->dtDue();
00281 if ( todo->doesRecur() && date.isValid() ) {
00282 dueDT.addDays( todo->dtDue().date().daysTo( date ) );
00283 }
00284 mDueDateEdit->setDate(dueDT.date());
00285 mDueTimeEdit->setTime(dueDT.time());
00286 mDueCheck->setChecked(true);
00287 } else {
00288 enableAlarm( false );
00289 mDueDateEdit->setEnabled(false);
00290 mDueTimeEdit->setEnabled(false);
00291 mDueDateEdit->setDate(QDate::currentDate());
00292 mDueTimeEdit->setTime(QTime::currentTime());
00293 mDueCheck->setChecked(false);
00294 }
00295
00296 if (todo->hasStartDate()) {
00297 QDateTime startDT = todo->dtStart();
00298 if ( todo->doesRecur() && date.isValid() ) {
00299 startDT.setDate( date );
00300 }
00301 mStartDateEdit->setDate(startDT.date());
00302 mStartTimeEdit->setTime(startDT.time());
00303 mStartCheck->setChecked(true);
00304 } else {
00305 mStartDateEdit->setEnabled(false);
00306 mStartTimeEdit->setEnabled(false);
00307 mStartDateEdit->setDate(QDate::currentDate());
00308 mStartTimeEdit->setTime(QTime::currentTime());
00309 mStartCheck->setChecked(false);
00310 }
00311
00312 mTimeButton->setChecked( !todo->doesFloat() );
00313
00314 mAlreadyComplete = false;
00315 mCompletedCombo->setCurrentItem(todo->percentComplete() / 10);
00316 if (todo->isCompleted() && todo->hasCompletedDate()) {
00317 mCompleted = todo->completed();
00318 mAlreadyComplete = true;
00319 }
00320 setCompletedDate();
00321
00322 mPriorityCombo->setCurrentItem( todo->priority() );
00323 mStartDateModified = false;
00324 }
00325
00326 void KOEditorGeneralTodo::writeTodo(Todo *todo)
00327 {
00328 KOEditorGeneral::writeIncidence(todo);
00329
00330
00331 QString tmpStr;
00332
00333 todo->setHasDueDate(mDueCheck->isChecked());
00334 todo->setHasStartDate(mStartCheck->isChecked());
00335
00336 QDate tmpSDate, tmpDDate;
00337 QTime tmpSTime, tmpDTime;
00338 QDateTime tmpStartDT, tmpDueDT;
00339 if ( mTimeButton->isChecked() ) {
00340 todo->setFloats(false);
00341
00342
00343 tmpDDate = mDueDateEdit->date();
00344 tmpDTime = mDueTimeEdit->getTime();
00345 tmpDueDT.setDate(tmpDDate);
00346 tmpDueDT.setTime(tmpDTime);
00347
00348
00349 if ( mStartCheck->isChecked() ) {
00350 tmpSDate = mStartDateEdit->date();
00351 tmpSTime = mStartTimeEdit->getTime();
00352 tmpStartDT.setDate(tmpSDate);
00353 tmpStartDT.setTime(tmpSTime);
00354 } else {
00355 tmpStartDT = tmpDueDT;
00356 }
00357 } else {
00358 todo->setFloats(true);
00359
00360
00361 tmpDDate = mDueDateEdit->date();
00362 tmpDTime.setHMS(0,0,0);
00363 tmpDueDT.setDate(tmpDDate);
00364 tmpDueDT.setTime(tmpDTime);
00365
00366 if ( mStartCheck->isChecked() ) {
00367 tmpSDate = mStartDateEdit->date();
00368 tmpSTime.setHMS(0,0,0);
00369 tmpStartDT.setDate(tmpSDate);
00370 tmpStartDT.setTime(tmpSTime);
00371 } else {
00372 tmpStartDT = tmpDueDT;
00373 }
00374 }
00375
00376
00377 if ( todo->doesRecur() && !mStartDateModified ) {
00378 todo->setDtDue( tmpDueDT );
00379 } else {
00380 todo->setDtDue( tmpDueDT, true );
00381 todo->setDtStart( tmpStartDT );
00382 todo->setDtRecurrence( tmpDueDT );
00383 }
00384
00385 todo->setPriority( mPriorityCombo->currentItem() );
00386
00387
00388 todo->setPercentComplete(mCompletedCombo->currentItem() * 10);
00389
00390 if (mCompletedCombo->currentItem() == 10 && mCompleted.isValid()) {
00391 QDateTime completed( mCompletionDateEdit->date(),
00392 mCompletionTimeEdit->getTime() );
00393 int difference = mCompleted.secsTo( completed );
00394 if ( (difference < 60) && (difference > -60) &&
00395 (completed.time().minute() == mCompleted.time().minute() ) ) {
00396
00397
00398 completed = mCompleted;
00399 }
00400 todo->setCompleted( completed );
00401 }
00402 }
00403
00404 void KOEditorGeneralTodo::enableDueEdit(bool enable)
00405 {
00406 mDueDateEdit->setEnabled( enable );
00407
00408 if(mDueCheck->isChecked() || mStartCheck->isChecked()) {
00409 mTimeButton->setEnabled(true);
00410 } else {
00411 mTimeButton->setEnabled(false);
00412 }
00413
00414 if (enable) {
00415 mDueTimeEdit->setEnabled( mTimeButton->isChecked() );
00416 } else {
00417 mDueTimeEdit->setEnabled( false );
00418 }
00419 }
00420
00421 void KOEditorGeneralTodo::enableStartEdit( bool enable )
00422 {
00423 mStartDateEdit->setEnabled( enable );
00424
00425 if(mDueCheck->isChecked() || mStartCheck->isChecked()) {
00426 mTimeButton->setEnabled(true);
00427 }
00428 else {
00429 mTimeButton->setEnabled(false);
00430 mTimeButton->setChecked(false);
00431 }
00432
00433 if (enable) {
00434 mStartTimeEdit->setEnabled( mTimeButton->isChecked() );
00435 } else {
00436 mStartTimeEdit->setEnabled( false );
00437 }
00438 }
00439
00440 void KOEditorGeneralTodo::enableTimeEdits(bool enable)
00441 {
00442 if(mStartCheck->isChecked()) {
00443 mStartTimeEdit->setEnabled( enable );
00444 }
00445 if(mDueCheck->isChecked()) {
00446 mDueTimeEdit->setEnabled( enable );
00447 }
00448 }
00449
00450 void KOEditorGeneralTodo::showAlarm()
00451 {
00452 enableAlarm( mDueCheck->isChecked() );
00453 }
00454
00455 bool KOEditorGeneralTodo::validateInput()
00456 {
00457 if (mDueCheck->isChecked()) {
00458 if (!mDueDateEdit->date().isValid()) {
00459 KMessageBox::sorry(0,i18n("Please specify a valid due date."));
00460 return false;
00461 }
00462 if (mTimeButton->isChecked()) {
00463 if (!mDueTimeEdit->inputIsValid()) {
00464 KMessageBox::sorry(0,i18n("Please specify a valid due time."));
00465 return false;
00466 }
00467 }
00468 }
00469
00470 if (mStartCheck->isChecked()) {
00471 if (!mStartDateEdit->date().isValid()) {
00472 KMessageBox::sorry(0,i18n("Please specify a valid start date."));
00473 return false;
00474 }
00475 if (mTimeButton->isChecked()) {
00476 if (!mStartTimeEdit->inputIsValid()) {
00477 KMessageBox::sorry(0,i18n("Please specify a valid start time."));
00478 return false;
00479 }
00480 }
00481 }
00482
00483 if (mStartCheck->isChecked() && mDueCheck->isChecked()) {
00484 QDateTime startDate;
00485 QDateTime dueDate;
00486 startDate.setDate(mStartDateEdit->date());
00487 dueDate.setDate(mDueDateEdit->date());
00488 if (mTimeButton->isChecked()) {
00489 startDate.setTime(mStartTimeEdit->getTime());
00490 dueDate.setTime(mDueTimeEdit->getTime());
00491 }
00492 if (startDate > dueDate) {
00493 KMessageBox::sorry(0,
00494 i18n("The start date cannot be after the due date."));
00495 return false;
00496 }
00497 }
00498
00499 return KOEditorGeneral::validateInput();
00500 }
00501
00502 void KOEditorGeneralTodo::completedChanged(int index)
00503 {
00504 if (index == 10) {
00505 mCompleted = QDateTime::currentDateTime();
00506 }
00507 setCompletedDate();
00508 }
00509
00510 void KOEditorGeneralTodo::dateChanged()
00511 {
00512 KLocale *l = KGlobal::locale();
00513 QString dateTimeStr = "";
00514
00515 if ( mStartCheck->isChecked() ) {
00516 dateTimeStr += i18n("Start: %1").arg(
00517 l->formatDate( mStartDateEdit->date() ) );
00518 if ( mTimeButton->isChecked() )
00519 dateTimeStr += QString(" %1").arg(
00520 l->formatTime( mStartTimeEdit->getTime() ) );
00521 }
00522
00523 if ( mDueCheck->isChecked() ) {
00524 dateTimeStr += i18n(" Due: %1").arg(
00525 l->formatDate( mDueDateEdit->date() ) );
00526 if ( mTimeButton->isChecked() )
00527 dateTimeStr += QString(" %1").arg(
00528 l->formatTime( mDueTimeEdit->getTime() ) );
00529 }
00530
00531 emit dateTimeStrChanged( dateTimeStr );
00532 QDateTime endDt( mDueDateEdit->date(), mDueTimeEdit->getTime() );
00533 emit signalDateTimeChanged( endDt, endDt );
00534 }
00535
00536 void KOEditorGeneralTodo::startDateModified()
00537 {
00538 mStartDateModified = true;
00539 dateChanged();
00540 }
00541
00542 void KOEditorGeneralTodo::setCompletedDate()
00543 {
00544 if (mCompletedCombo->currentItem() == 10 && mCompleted.isValid()) {
00545 mCompletedLabel->setText(i18n("co&mpleted on"));
00546
00547 mCompletionDateEdit->show();
00548 mCompletionTimeEdit->show();
00549 mCompletionDateEdit->setDate( mCompleted.date() );
00550 mCompletionTimeEdit->setTime( mCompleted.time() );
00551 } else {
00552 mCompletedLabel->setText(i18n("co&mpleted"));
00553 mCompletionDateEdit->hide();
00554 mCompletionTimeEdit->hide();
00555 }
00556 }
00557
00558 void KOEditorGeneralTodo::modified (Todo* todo, KOGlobals::HowChanged modification)
00559 {
00560 switch (modification) {
00561 case KOGlobals::PRIORITY_MODIFIED:
00562 mPriorityCombo->setCurrentItem( todo->priority() );
00563 break;
00564 case KOGlobals::COMPLETION_MODIFIED:
00565 mCompletedCombo->setCurrentItem(todo->percentComplete() / 10);
00566 if (todo->isCompleted() && todo->hasCompletedDate()) {
00567 mCompleted = todo->completed();
00568 }
00569 setCompletedDate();
00570 break;
00571 case KOGlobals::CATEGORY_MODIFIED:
00572 setCategories( todo->categories() );
00573 break;
00574 case KOGlobals::UNKNOWN_MODIFIED:
00575 default:
00576 readTodo( todo, 0, QDate() );
00577 break;
00578 }
00579 }