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