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