korganizer

koeditorgeneraltodo.cpp

00001 /*
00002     This file is part of KOrganizer.
00003     Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
00004     Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 
00020     As a special exception, permission is given to link this program
00021     with any edition of Qt, and distribute the resulting executable,
00022     without including the source code for Qt in the source distribution.
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, mDueCheck );
00073   QWidget::setTabOrder( mDueCheck, mDueDateEdit );
00074   QWidget::setTabOrder( mDueDateEdit, mDueTimeEdit );
00075   QWidget::setTabOrder( mDueTimeEdit, mStartCheck );
00076   QWidget::setTabOrder( mStartCheck, mStartDateEdit );
00077   QWidget::setTabOrder( mStartDateEdit, mStartTimeEdit );
00078   QWidget::setTabOrder( mStartTimeEdit, 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 //   QWidget::setTabOrder( mAlarmIncrCombo, mAlarmSoundButton );
00085   QWidget::setTabOrder( mAlarmIncrCombo, mAlarmEditButton );
00086 //   QWidget::setTabOrder( mAlarmSoundButton, mAlarmProgramButton );
00087 //   QWidget::setTabOrder( mAlarmProgramButton, mDescriptionEdit );
00088   QWidget::setTabOrder( mAlarmEditButton, mDescriptionEdit );
00089   QWidget::setTabOrder( mDescriptionEdit, mCategoriesButton );
00090   QWidget::setTabOrder( mCategoriesButton, mSecrecyCombo );
00091 //  QWidget::setTabOrder( mSecrecyCombo, mDescriptionEdit );
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 due date for this to-do.");
00114   mDueCheck = new QCheckBox(i18n("&Due:"),timeBoxFrame);
00115   QWhatsThis::add( mDueCheck, whatsThis );
00116   layoutTimeBox->addWidget(mDueCheck,0,0);
00117   connect(mDueCheck,SIGNAL(toggled(bool)),SLOT(enableDueEdit(bool)));
00118   connect(mDueCheck,SIGNAL(toggled(bool)),SLOT(showAlarm()));
00119   connect(mDueCheck,SIGNAL(toggled(bool)),SIGNAL(dueDateEditToggle(bool)));
00120   connect(mDueCheck,SIGNAL(toggled(bool)),SLOT(dateChanged()));
00121 
00122   mDueDateEdit = new KDateEdit(timeBoxFrame);
00123   QWhatsThis::add( mDueDateEdit, whatsThis );
00124   layoutTimeBox->addWidget(mDueDateEdit,0,1);
00125   connect(mDueDateEdit,SIGNAL(dateChanged(const QDate&)),SLOT(dateChanged()));
00126 
00127   mDueTimeEdit = new KTimeEdit(timeBoxFrame);
00128   QWhatsThis::add( mDueTimeEdit,
00129                    i18n("Sets the due time for this to-do.") );
00130   layoutTimeBox->addWidget(mDueTimeEdit,0,2);
00131   connect(mDueTimeEdit,SIGNAL(timeChanged( QTime )),SLOT(dateChanged()));
00132 
00133   whatsThis = i18n("Sets the start date for this to-do");
00134   mStartCheck = new QCheckBox(i18n("Sta&rt:"),timeBoxFrame);
00135   QWhatsThis::add( mStartCheck, whatsThis );
00136   layoutTimeBox->addWidget(mStartCheck,1,0);
00137   connect(mStartCheck,SIGNAL(toggled(bool)),SLOT(enableStartEdit(bool)));
00138   connect(mStartCheck,SIGNAL(toggled(bool)),SLOT(startDateModified()));
00139 
00140   mStartDateEdit = new KDateEdit(timeBoxFrame);
00141   QWhatsThis::add( mStartDateEdit, whatsThis );
00142   layoutTimeBox->addWidget(mStartDateEdit,1,1);
00143   connect(mStartDateEdit,SIGNAL(dateChanged(const QDate&)),SLOT(startDateModified()));
00144 
00145   mStartTimeEdit = new KTimeEdit(timeBoxFrame);
00146   QWhatsThis::add( mStartTimeEdit,
00147                    i18n("Sets the start time for this to-do.") );
00148   layoutTimeBox->addWidget(mStartTimeEdit,1,2);
00149   connect(mStartTimeEdit,SIGNAL(timeChanged(QTime)),SLOT(startDateModified()));
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   // some more layouting
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     // xgettext:no-c-format
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   KOEditorGeneral::setDefaults(allDay);
00228 
00229   mTimeButton->setChecked( !allDay );
00230   if(mTimeButton->isChecked()) {
00231     mTimeButton->setEnabled(true);
00232   }
00233   else {
00234     mTimeButton->setEnabled(false);
00235   }
00236 
00237   enableTimeEdits( !allDay );
00238 
00239   mDueCheck->setChecked(false);
00240   enableDueEdit(false);
00241 
00242   enableAlarm(false);
00243 
00244   mStartCheck->setChecked(false);
00245   enableStartEdit(false);
00246 
00247   mDueDateEdit->setDate(due.date());
00248   mDueTimeEdit->setTime(due.time());
00249 
00250   mStartDateEdit->setDate(QDate::currentDate());
00251   mStartTimeEdit->setTime(QTime::currentTime());
00252   mStartDateModified = false;
00253 
00254   mPriorityCombo->setCurrentItem(5);
00255 
00256   mCompletedCombo->setCurrentItem(0);
00257 }
00258 
00259 void KOEditorGeneralTodo::readTodo(Todo *todo)
00260 {
00261   KOEditorGeneral::readIncidence(todo);
00262 
00263   QDateTime dueDT;
00264 
00265   if (todo->hasDueDate()) {
00266     enableAlarm( true );
00267     dueDT = todo->dtDue();
00268     mDueDateEdit->setDate(todo->dtDue().date());
00269     mDueTimeEdit->setTime(todo->dtDue().time());
00270     mDueCheck->setChecked(true);
00271   } else {
00272     enableAlarm( false );
00273     mDueDateEdit->setEnabled(false);
00274     mDueTimeEdit->setEnabled(false);
00275     mDueDateEdit->setDate(QDate::currentDate());
00276     mDueTimeEdit->setTime(QTime::currentTime());
00277     mDueCheck->setChecked(false);
00278   }
00279 
00280   if (todo->hasStartDate()) {
00281     mStartDateEdit->setDate(todo->dtStart().date());
00282     mStartTimeEdit->setTime(todo->dtStart().time());
00283     mStartCheck->setChecked(true);
00284   } else {
00285     mStartDateEdit->setEnabled(false);
00286     mStartTimeEdit->setEnabled(false);
00287     mStartDateEdit->setDate(QDate::currentDate());
00288     mStartTimeEdit->setTime(QTime::currentTime());
00289     mStartCheck->setChecked(false);
00290   }
00291 
00292   mTimeButton->setChecked( !todo->doesFloat() );
00293 
00294   mAlreadyComplete = false;
00295   mCompletedCombo->setCurrentItem(todo->percentComplete() / 10);
00296   if (todo->isCompleted() && todo->hasCompletedDate()) {
00297     mCompleted = todo->completed();
00298     mAlreadyComplete = true;
00299   }
00300   setCompletedDate();
00301 
00302   mPriorityCombo->setCurrentItem( todo->priority() );
00303   mStartDateModified = false;
00304 }
00305 
00306 void KOEditorGeneralTodo::writeTodo(Todo *todo)
00307 {
00308   KOEditorGeneral::writeIncidence(todo);
00309 
00310   // temp. until something better happens.
00311   QString tmpStr;
00312 
00313   todo->setHasDueDate(mDueCheck->isChecked());
00314   todo->setHasStartDate(mStartCheck->isChecked());
00315 
00316   QDate tmpSDate, tmpDDate;
00317   QTime tmpSTime, tmpDTime;
00318   QDateTime tmpStartDT, tmpDueDT;
00319   if ( mTimeButton->isChecked() ) {
00320     todo->setFloats(false);
00321 
00322     // set due date/time
00323     tmpDDate = mDueDateEdit->date();
00324     tmpDTime = mDueTimeEdit->getTime();
00325     tmpDueDT.setDate(tmpDDate);
00326     tmpDueDT.setTime(tmpDTime);
00327 
00328     // set start date/time
00329     if ( mStartCheck->isChecked() ) {
00330       tmpSDate = mStartDateEdit->date();
00331       tmpSTime = mStartTimeEdit->getTime();
00332       tmpStartDT.setDate(tmpSDate);
00333       tmpStartDT.setTime(tmpSTime);
00334     } else {
00335       tmpStartDT = tmpDueDT;
00336     }
00337   } else {
00338     todo->setFloats(true);
00339 
00340     // need to change this.
00341     tmpDDate = mDueDateEdit->date();
00342     tmpDTime.setHMS(0,0,0);
00343     tmpDueDT.setDate(tmpDDate);
00344     tmpDueDT.setTime(tmpDTime);
00345 
00346     if ( mStartCheck->isChecked() ) {
00347       tmpSDate = mStartDateEdit->date();
00348       tmpSTime.setHMS(0,0,0);
00349       tmpStartDT.setDate(tmpSDate);
00350       tmpStartDT.setTime(tmpSTime);
00351     } else {
00352       tmpStartDT = tmpDueDT;
00353     }
00354   }
00355 
00356   if ( todo->doesRecur() && !mStartDateModified ) {
00357     todo->setDtDue( tmpDueDT );
00358   } else {
00359       todo->setDtDue( tmpDueDT, true );
00360       todo->setDtStart( tmpStartDT );
00361       todo->setDtRecurrence( tmpDueDT );
00362   }
00363 
00364   todo->setPriority( mPriorityCombo->currentItem() );
00365 
00366   // set completion state
00367   todo->setPercentComplete(mCompletedCombo->currentItem() * 10);
00368 
00369   if (mCompletedCombo->currentItem() == 10 && mCompleted.isValid()) {
00370     QDateTime completed( mCompletionDateEdit->date(),
00371                          mCompletionTimeEdit->getTime() );
00372     int difference = mCompleted.secsTo( completed );
00373     if ( (difference < 60) && (difference > -60) &&
00374          (completed.time().minute() == mCompleted.time().minute() ) ) {
00375       // completion time wasn't changed substantially (only the seconds
00376       // truncated, but that's an effect done by KTimeEdit automatically).
00377       completed = mCompleted;
00378     }
00379     todo->setCompleted( completed );
00380   }
00381 }
00382 
00383 void KOEditorGeneralTodo::enableDueEdit(bool enable)
00384 {
00385   mDueDateEdit->setEnabled( enable );
00386 
00387   if(mDueCheck->isChecked() || mStartCheck->isChecked()) {
00388     mTimeButton->setEnabled(true);
00389   }
00390   else {
00391     mTimeButton->setEnabled(false);
00392     mTimeButton->setChecked(false);
00393   }
00394 
00395   if (enable) {
00396     mDueTimeEdit->setEnabled( mTimeButton->isChecked() );
00397   } else {
00398     mDueTimeEdit->setEnabled( false );
00399   }
00400 }
00401 
00402 void KOEditorGeneralTodo::enableStartEdit( bool enable )
00403 {
00404   mStartDateEdit->setEnabled( enable );
00405 
00406   if(mDueCheck->isChecked() || mStartCheck->isChecked()) {
00407     mTimeButton->setEnabled(true);
00408   }
00409   else {
00410     mTimeButton->setEnabled(false);
00411     mTimeButton->setChecked(false);
00412   }
00413 
00414   if (enable) {
00415     mStartTimeEdit->setEnabled( mTimeButton->isChecked() );
00416   } else {
00417     mStartTimeEdit->setEnabled( false );
00418   }
00419 }
00420 
00421 void KOEditorGeneralTodo::enableTimeEdits(bool enable)
00422 {
00423   if(mStartCheck->isChecked()) {
00424     mStartTimeEdit->setEnabled( enable );
00425   }
00426   if(mDueCheck->isChecked()) {
00427     mDueTimeEdit->setEnabled( enable );
00428   }
00429 }
00430 
00431 void KOEditorGeneralTodo::showAlarm()
00432 {
00433   enableAlarm( mDueCheck->isChecked() );
00434 }
00435 
00436 bool KOEditorGeneralTodo::validateInput()
00437 {
00438   if (mDueCheck->isChecked()) {
00439     if (!mDueDateEdit->date().isValid()) {
00440       KMessageBox::sorry(0,i18n("Please specify a valid due date."));
00441       return false;
00442     }
00443     if (mTimeButton->isChecked()) {
00444       if (!mDueTimeEdit->inputIsValid()) {
00445         KMessageBox::sorry(0,i18n("Please specify a valid due time."));
00446         return false;
00447       }
00448     }
00449   }
00450 
00451   if (mStartCheck->isChecked()) {
00452     if (!mStartDateEdit->date().isValid()) {
00453       KMessageBox::sorry(0,i18n("Please specify a valid start date."));
00454       return false;
00455     }
00456     if (mTimeButton->isChecked()) {
00457       if (!mStartTimeEdit->inputIsValid()) {
00458         KMessageBox::sorry(0,i18n("Please specify a valid start time."));
00459         return false;
00460       }
00461     }
00462   }
00463 
00464   if (mStartCheck->isChecked() && mDueCheck->isChecked()) {
00465     QDateTime startDate;
00466     QDateTime dueDate;
00467     startDate.setDate(mStartDateEdit->date());
00468     dueDate.setDate(mDueDateEdit->date());
00469     if (mTimeButton->isChecked()) {
00470       startDate.setTime(mStartTimeEdit->getTime());
00471       dueDate.setTime(mDueTimeEdit->getTime());
00472     }
00473     if (startDate > dueDate) {
00474       KMessageBox::sorry(0,
00475                          i18n("The start date cannot be after the due date."));
00476       return false;
00477     }
00478   }
00479 
00480   return KOEditorGeneral::validateInput();
00481 }
00482 
00483 void KOEditorGeneralTodo::completedChanged(int index)
00484 {
00485   if (index == 10) {
00486     mCompleted = QDateTime::currentDateTime();
00487   }
00488   setCompletedDate();
00489 }
00490 
00491 void KOEditorGeneralTodo::dateChanged()
00492 {
00493   KLocale *l = KGlobal::locale();
00494   QString dateTimeStr = "";
00495 
00496   if ( mStartCheck->isChecked() ) {
00497     dateTimeStr += i18n("Start: %1").arg(
00498                                      l->formatDate( mStartDateEdit->date() ) );
00499     if ( mTimeButton->isChecked() )
00500       dateTimeStr += QString(" %1").arg(
00501                                    l->formatTime( mStartTimeEdit->getTime() ) );
00502   }
00503 
00504   if ( mDueCheck->isChecked() ) {
00505     dateTimeStr += i18n("   Due: %1").arg(
00506                                       l->formatDate( mDueDateEdit->date() ) );
00507     if ( mTimeButton->isChecked() )
00508       dateTimeStr += QString(" %1").arg(
00509                                     l->formatTime( mDueTimeEdit->getTime() ) );
00510   }
00511 
00512   emit dateTimeStrChanged( dateTimeStr );
00513   QDateTime endDt( mDueDateEdit->date(), mDueTimeEdit->getTime() );
00514   emit signalDateTimeChanged( endDt, endDt );
00515 }
00516 
00517 void KOEditorGeneralTodo::startDateModified()
00518 {
00519   mStartDateModified = true;
00520   dateChanged();
00521 }
00522 
00523 void KOEditorGeneralTodo::setCompletedDate()
00524 {
00525   if (mCompletedCombo->currentItem() == 10 && mCompleted.isValid()) {
00526     mCompletedLabel->setText(i18n("co&mpleted on"));
00527 //        .arg(KGlobal::locale()->formatDateTime(mCompleted)));
00528     mCompletionDateEdit->show();
00529     mCompletionTimeEdit->show();
00530     mCompletionDateEdit->setDate( mCompleted.date() );
00531     mCompletionTimeEdit->setTime( mCompleted.time() );
00532   } else {
00533     mCompletedLabel->setText(i18n("co&mpleted"));
00534     mCompletionDateEdit->hide();
00535     mCompletionTimeEdit->hide();
00536   }
00537 }
00538 
00539 void KOEditorGeneralTodo::modified (Todo* todo, int modification)
00540 {
00541   switch (modification) {
00542   case KOGlobals::PRIORITY_MODIFIED:
00543     mPriorityCombo->setCurrentItem( todo->priority() );
00544     break;
00545   case KOGlobals::COMPLETION_MODIFIED:
00546     mCompletedCombo->setCurrentItem(todo->percentComplete() / 10);
00547     if (todo->isCompleted() && todo->hasCompletedDate()) {
00548       mCompleted = todo->completed();
00549     }
00550     setCompletedDate();
00551     break;
00552   case KOGlobals::CATEGORY_MODIFIED:
00553     setCategories (todo->categoriesStr ());
00554     break;
00555   case KOGlobals::UNKNOWN_MODIFIED: // fall through
00556   default:
00557     readTodo( todo );
00558     break;
00559   }
00560 }
KDE Home | KDE Accessibility Home | Description of Access Keys