-rw-r--r-- | korganizer/kotodoeditor.cpp | 29 | ||||
-rw-r--r-- | korganizer/kotodoviewitem.cpp | 40 | ||||
-rw-r--r-- | libkcal/incidence.cpp | 9 | ||||
-rw-r--r-- | libkcal/incidence.h | 5 | ||||
-rw-r--r-- | libkcal/incidencebase.cpp | 1 | ||||
-rw-r--r-- | libkcal/incidencebase.h | 4 | ||||
-rw-r--r-- | libkcal/todo.cpp | 47 | ||||
-rw-r--r-- | libkcal/todo.h | 2 |
8 files changed, 130 insertions, 7 deletions
diff --git a/korganizer/kotodoeditor.cpp b/korganizer/kotodoeditor.cpp index 069dda8..9232e09 100644 --- a/korganizer/kotodoeditor.cpp +++ b/korganizer/kotodoeditor.cpp @@ -260,157 +260,186 @@ void KOTodoEditor::deleteTodo() if (mTodo) { if (KOPrefs::instance()->mConfirm) { switch (msgItemDelete()) { case KMessageBox::Continue: // OK emit todoToBeDeleted(mTodo); emit dialogClose(mTodo); mCalendar->deleteTodo(mTodo); emit todoDeleted(); reject(); break; } } else { emit todoToBeDeleted(mTodo); emit dialogClose(mTodo); mCalendar->deleteTodo(mTodo); emit todoDeleted(); reject(); } } else { reject(); } } void KOTodoEditor::setDefaults(QDateTime due,Todo *relatedEvent,bool allDay) { mRelatedTodo = relatedEvent; mGeneral->setDefaults(due,allDay); mDetails->setDefaults(); showPage( 0 ); if ( mRelatedTodo ) { mGeneral->setCategories (mRelatedTodo->categoriesStr ()); mGeneral->setSecrecy (mRelatedTodo->secrecy ()); if ( mRelatedTodo->priority() < 3 ) mGeneral->mPriorityCombo->setCurrentItem(mRelatedTodo->priority()-1); mGeneral->mSummaryEdit->lineEdit()->setText(mRelatedTodo->summary()+": "); int len = mRelatedTodo->summary().length(); mGeneral->mSummaryEdit->lineEdit()->setFocus(); mGeneral->mSummaryEdit->lineEdit()->setCursorPosition ( len+2 ); mGeneral->mSummaryEdit->lineEdit()->setSelection ( 0, len+2 ); } else mGeneral->setFocusOn( 2 ); tabWidget()->setTabEnabled ( mRecurrence->parentWidget(), false ); mRecurrence->setDefaults(QDateTime::currentDateTime(),QDateTime::currentDateTime().addSecs( 3600 ),true); } void KOTodoEditor::checkRecurrence() { if ( mGeneral->mDueCheck->isChecked() && mGeneral->mStartCheck->isChecked()) { tabWidget()->setTabEnabled ( mRecurrence->parentWidget(), true ); if ( mTodo ) mRecurrence->readEvent( mTodo ); else { bool time = mGeneral->mTimeButton->isChecked(); QDateTime from,to; if ( time ) { to = QDateTime( mGeneral->mDueDateEdit->date(), mGeneral->mDueTimeEdit->getTime() ) ; from = QDateTime( mGeneral->mStartDateEdit->date(),mGeneral->mStartTimeEdit->getTime( )) ; } else { to = QDateTime( mGeneral->mDueDateEdit->date(), QTime( 0,0,0) ) ; from = QDateTime( mGeneral->mStartDateEdit->date(),QTime( 0,0,0) ) ; } + if ( to < from ) + to = from; mRecurrence->setDefaults(from,to,!time); } } else { tabWidget()->setTabEnabled ( mRecurrence->parentWidget(), false ); mRecurrence->setDefaults(QDateTime::currentDateTime(),QDateTime::currentDateTime().addSecs( 3600 ),true); } } void KOTodoEditor::readTodo(Todo *todo) { mGeneral->readTodo(todo); mDetails->readEvent(todo); mRelatedTodo = 0;//todo->relatedTo(); // categories // mCategoryDialog->setSelected(todo->categories()); // We should handle read-only events here. } void KOTodoEditor::writeTodo(Todo *event) { mGeneral->writeTodo(event); mDetails->writeEvent(event); // set related event, i.e. parent to-do in this case. if (mRelatedTodo) { event->setRelatedTo(mRelatedTodo); } if ( mGeneral->mDueCheck->isChecked() && mGeneral->mStartCheck->isChecked()) { mRecurrence->writeEvent(event); + event->setRecurrenceID( event->dtStart().addSecs(-1) ); + event->setRecurDates(); +#if 0 + bool ok; + QDateTime next = event->getNextOccurence( event->dtStart().addSecs(-1), &ok ); + if ( ok ) { + QDateTime from,to; + bool time = mGeneral->mTimeButton->isChecked(); + if ( time ) { + to = QDateTime( mGeneral->mDueDateEdit->date(), mGeneral->mDueTimeEdit->getTime() ) ; + from = QDateTime( mGeneral->mStartDateEdit->date(),mGeneral->mStartTimeEdit->getTime( )) ; + } else { + to = QDateTime( mGeneral->mDueDateEdit->date(), QTime( 0,0,0) ) ; + from = QDateTime( mGeneral->mStartDateEdit->date(),QTime( 0,0,0) ) ; + } + if ( to < from ) + to = from; + int secs = from.secsTo( to ); + event->setRecurrenceID( next ); + event->setDtStart( next ); + event->setDtDue( next.addSecs( secs ) ); + } + else { + event->setHasRecurrenceID( false ); + event->recurrence()->unsetRecurs(); + } +#endif } else event->recurrence()->unsetRecurs(); } bool KOTodoEditor::validateInput() { if (!mGeneral->validateInput()) return false; if (!mDetails->validateInput()) return false; return true; } int KOTodoEditor::msgItemDelete() { return KMessageBox::warningContinueCancel(this, i18n("This item will be permanently deleted."), i18n("KOrganizer Confirmation"),i18n("Delete")); } void KOTodoEditor::modified (int modification) { if (modification == KOGlobals::CATEGORY_MODIFIED || KOGlobals::UNKNOWN_MODIFIED == modification ) // mCategoryDialog->setSelected (mTodo->categories ()); mGeneral->modified (mTodo, modification); } void KOTodoEditor::slotLoadTemplate() { QString fileName =locateLocal( "templates", "todos" ); QDir t_dir; if ( !t_dir.exists(fileName) ) t_dir.mkdir ( fileName ); fileName += "/todo"; fileName = KFileDialog::getSaveFileName( fileName , "Load Todo template", this ); if ( fileName.length() == 0 ) return; CalendarLocal cal; ICalFormat format; if ( !format.load( &cal, fileName ) ) { KMessageBox::error( this, i18n("Error loading template file\n '%1'.") .arg( fileName ) ); return ; } QPtrList<Todo> todos = cal.todos(); Todo * todo = todos.first(); if ( !todo ) { KMessageBox::error( this, i18n("Template does not\ncontain a valid Todo.")); } else { readTodo( todo ); } } void KOTodoEditor::slotSaveTemplate() { QString fileName =locateLocal( "templates", "todos" ); QDir t_dir; if ( !t_dir.exists(fileName) ) t_dir.mkdir ( fileName ); fileName += "/todo"; fileName = KFileDialog::getSaveFileName( fileName , "Save as Todo template", this ); diff --git a/korganizer/kotodoviewitem.cpp b/korganizer/kotodoviewitem.cpp index 0e847c2..70f00c6 100644 --- a/korganizer/kotodoviewitem.cpp +++ b/korganizer/kotodoviewitem.cpp @@ -130,170 +130,208 @@ void KOTodoViewItem::construct() } else { setText(6,mTodo->dtStartTimeStr()); QTime t = mTodo->dtStart().time(); skeyt.sprintf("%02d%02d",t.hour(),t.minute()); } } else { setText(5,""); setText(6,""); } setSortKey(5,skeyd); setSortKey(6,skeyt); setText(7,mTodo->cancelled() ? i18n("Yes") : i18n("No")); setText(8,mTodo->categoriesStr()); #if 0 // Find sort id in description. It's the text behind the last '#' character // found in the description. White spaces are removed from beginning and end // of sort id. int pos = mTodo->description().findRev('#'); if (pos < 0) { setText(6,""); } else { QString str = mTodo->description().mid(pos+1); str.stripWhiteSpace(); setText(6,str); } #endif m_known = false; m_init = false; setMyPixmap(); } void KOTodoViewItem::setMyPixmap() { int size = 5; QPixmap pixi = QPixmap( 1, 1 ); // if ( !mTodo->isCompleted() && mTodo->hasDueDate() && mTodo->dtDue() < QDateTime::currentDateTime() ) { // pixi = SmallIcon("redcross16"); // } else { QPainter p; int pixSize = 0; QPixmap pPix = QPixmap( size, size ); if ( mTodo->description().length() > 0 ) { pixi.resize(size, pixSize+size); pPix.fill( Qt::darkGreen ); p.begin( &pixi ); p. drawPixmap ( 0, pixSize, pPix); p.end(); pixSize += size; } if ( mTodo->isAlarmEnabled() ) { pixi.resize(size, pixSize+size); pPix.fill( Qt::red ); p.begin( &pixi ); p. drawPixmap ( 0, pixSize, pPix); p.end(); pixSize += size; } + if ( mTodo->doesRecur() ) { + pixi.resize(size, pixSize+size); + pPix.fill( Qt::blue ); + p.begin( &pixi ); + p. drawPixmap ( 0, pixSize, pPix); + p.end(); + pixSize += size; + } // } if ( pixi.width() > 1 ) { setPixmap ( 0,pixi ) ; } else { setPixmap ( 0,QPixmap() ) ; } } void KOTodoViewItem::stateChange(bool state) { - // qDebug("KOTodoViewItem::stateChange "); + // qDebug("KOTodoViewItem::stateChange %d ", state); // do not change setting on startup if ( m_init ) return; if (isOn()!=state) { setOn(state); //qDebug("SETON "); return; } if ( mTodo->isCompleted() == state ) { //qDebug("STATECHANGE:nothing to do "); return; } QString keyd = "=="; QString keyt = "=="; //qDebug("KOTodoViewItem::stateChange %s ", text(0).latin1()); + if ( mTodo->doesRecur() ){ + QDateTime start = mTodo->dtStart(); mTodo->setCompleted(state); + if ( start != mTodo->dtStart() ) { + if ( state && !mTodo->isCompleted() ) { + setOn( false ); + state = false; + } + } + } else + mTodo->setCompleted(state); + if (state) mTodo->setCompleted(QDateTime::currentDateTime()); if (mTodo->hasDueDate()) { setText(3, mTodo->dtDueDateStr()); QDate d = mTodo->dtDue().date(); keyd.sprintf("%04d%02d%02d",d.year(),d.month(),d.day()); setSortKey(3,keyd); if (mTodo->doesFloat()) { setText(4,""); } else { setText(4,mTodo->dtDueTimeStr()); QTime t = mTodo->dtDue().time(); keyt.sprintf("%02d%02d",t.hour(),t.minute()); setSortKey(4,keyt); } } + if (mTodo->hasStartDate()) { + QString skeyt = "=="; + QString skeyd = "=="; + setText(5, mTodo->dtStartDateStr()); + QDate d = mTodo->dtStart().date(); + skeyd.sprintf("%04d%02d%02d",d.year(),d.month(),d.day()); + + if (mTodo->doesFloat()) { + setText(6,""); + } + else { + setText(6,mTodo->dtStartTimeStr()); + QTime t = mTodo->dtStart().time(); + skeyt.sprintf("%02d%02d",t.hour(),t.minute()); + + } + setSortKey(5,skeyd); + setSortKey(6,skeyt); + } if (mTodo->isCompleted()) setSortKey(1,QString::number(9)+keyd+keyt); else setSortKey(1,QString::number(mTodo->priority())+keyd+keyt); setText(2,i18n("%1 %").arg(QString::number(mTodo->percentComplete()))); if (mTodo->percentComplete()<100) { if (mTodo->isCompleted()) setSortKey(2,QString::number(999)); else setSortKey(2,QString::number(mTodo->percentComplete())); } else { if (mTodo->isCompleted()) setSortKey(2,QString::number(999)); else setSortKey(2,QString::number(99)); } if ( state ) { QListViewItem * myChild = firstChild(); KOTodoViewItem *item; while( myChild ) { //qDebug("stateCH "); item = static_cast<KOTodoViewItem*>(myChild); item->stateChange(state); myChild = myChild->nextSibling(); } } else { QListViewItem * myChild = parent(); if ( myChild ) (static_cast<KOTodoViewItem*>(myChild))->stateChange(state); } mTodoView->modified(true); setMyPixmap(); mTodoView->setTodoModified( mTodo ); } bool KOTodoViewItem::isAlternate() { KOTodoListView *lv = static_cast<KOTodoListView *>(listView()); if (lv && lv->alternateBackground().isValid()) { KOTodoViewItem *above = 0; above = static_cast<KOTodoViewItem *>(itemAbove()); m_known = above ? above->m_known : true; if (m_known) { m_odd = above ? !above->m_odd : false; } else { KOTodoViewItem *item; bool previous = true; if (QListViewItem::parent()) { item = static_cast<KOTodoViewItem *>(QListViewItem::parent()); if (item) previous = item->m_odd; item = static_cast<KOTodoViewItem *>(QListViewItem::parent()->firstChild()); } else { item = static_cast<KOTodoViewItem *>(lv->firstChild()); } while(item) { item->m_odd = previous = !previous; item->m_known = true; diff --git a/libkcal/incidence.cpp b/libkcal/incidence.cpp index dbc159c..0684af2 100644 --- a/libkcal/incidence.cpp +++ b/libkcal/incidence.cpp @@ -586,64 +586,73 @@ void Incidence::setRecurrence( Recurrence * r) delete mRecurrence; mRecurrence = r; } void Incidence::setLocation(const QString &location) { if (mReadOnly) return; mLocation = location; updated(); } QString Incidence::location() const { return mLocation; } ushort Incidence::doesRecur() const { if ( mRecurrence ) return mRecurrence->doesRecur(); else return Recurrence::rNone; } QDateTime Incidence::getNextOccurence( const QDateTime& dt, bool* ok ) const { QDateTime incidenceStart = dt; *ok = false; if ( doesRecur() ) { bool last; recurrence()->getPreviousDateTime( incidenceStart , &last ); int count = 0; if ( !last ) { while ( !last ) { ++count; incidenceStart = recurrence()->getNextDateTime( incidenceStart, &last ); if ( recursOn( incidenceStart.date() ) ) { last = true; // exit while llop } else { if ( last ) { // no alarm on last recurrence return QDateTime (); } int year = incidenceStart.date().year(); // workaround for bug in recurrence if ( count == 100 || year < 1000 || year > 5000 ) { return QDateTime (); } incidenceStart = incidenceStart.addSecs( 1 ); } } } else { return QDateTime (); } } else { if ( hasStartDate () ) { incidenceStart = dtStart(); } if ( type() =="Todo" ) { if ( ((Todo*)this)->hasDueDate() ) incidenceStart = ((Todo*)this)->dtDue(); } } if ( incidenceStart > dt ) *ok = true; return incidenceStart; } +QDateTime Incidence::dtStart() const +{ + if ( doesRecur() ) { + if ( type() == "Todo" ) { + ((Todo*)this)->checkSetCompletedFalse(); + } + } + return mDtStart; +} diff --git a/libkcal/incidence.h b/libkcal/incidence.h index 38d2aaa..0ae9656 100644 --- a/libkcal/incidence.h +++ b/libkcal/incidence.h @@ -208,101 +208,102 @@ class Incidence : public IncidenceBase /** return the event's secrecy in string format. */ QString secrecyStr() const; /** return list of all availbale secrecy classes */ static QStringList secrecyList(); /** return human-readable name of secrecy class */ static QString secrecyName(int); /** returns TRUE if the date specified is one on which the event will * recur. */ bool recursOn(const QDate &qd) const; // VEVENT and VTODO, but not VJOURNAL (move to EventBase class?): /** set resources used, such as Office, Car, etc. */ void setResources(const QStringList &resources); /** return list of current resources */ QStringList resources() const; /** set the event's priority, 0 is undefined, 1 highest (decreasing order) */ void setPriority(int priority); /** get the event's priority */ int priority() const; /** All alarms that are associated with this incidence */ QPtrList<Alarm> alarms() const; /** Create a new alarm which is associated with this incidence */ Alarm* newAlarm(); /** Add an alarm which is associated with this incidence */ void addAlarm(Alarm*); /** Remove an alarm that is associated with this incidence */ void removeAlarm(Alarm*); /** Remove all alarms that are associated with this incidence */ void clearAlarms(); /** return whether any alarm associated with this incidence is enabled */ bool isAlarmEnabled() const; /** Return the recurrence rule associated with this incidence. If there is none, returns an appropriate (non-0) object. */ Recurrence *recurrence() const; void setRecurrence(Recurrence * r); /** Forward to Recurrence::doesRecur(). */ ushort doesRecur() const; /** set the event's/todo's location. Do _not_ use it with journal */ void setLocation(const QString &location); /** return the event's/todo's location. Do _not_ use it with journal */ QString location() const; /** returns TRUE or FALSE depending on whether the todo has a start date */ bool hasStartDate() const; /** sets the event's hasStartDate value. */ void setHasStartDate(bool f); QDateTime getNextOccurence( const QDateTime& dt, bool* yes ) const; bool cancelled() const; void setCancelled( bool b ); bool hasRecurrenceID() const; void setHasRecurrenceID( bool b ); void setRecurrenceID(QDateTime); QDateTime recurrenceID () const; + QDateTime dtStart() const; protected: QPtrList<Alarm> mAlarms; QPtrList<Incidence> mRelations; + QDateTime mRecurrenceID; + bool mHasRecurrenceID; private: int mRevision; bool mCancelled; // base components of jounal, event and todo - QDateTime mRecurrenceID; - bool mHasRecurrenceID; QDateTime mCreated; QString mDescription; QString mSummary; QStringList mCategories; Incidence *mRelatedTo; QString mRelatedToUid; DateList mExDates; QPtrList<Attachment> mAttachments; QStringList mResources; bool mHasStartDate; // if todo has associated start date int mSecrecy; int mPriority; // 1 = highest, 2 = less, etc. //QPtrList<Alarm> mAlarms; Recurrence *mRecurrence; QString mLocation; }; bool operator==( const Incidence&, const Incidence& ); } #endif diff --git a/libkcal/incidencebase.cpp b/libkcal/incidencebase.cpp index 7525a4a..51f2e9d 100644 --- a/libkcal/incidencebase.cpp +++ b/libkcal/incidencebase.cpp @@ -118,128 +118,129 @@ bool KCal::operator==( const IncidenceBase& i1, const IncidenceBase& i2 ) } QDateTime IncidenceBase::getEvenTime( QDateTime dt ) { QTime t = dt.time(); dt.setTime( QTime (t.hour (), t.minute (), t.second () ) ); return dt; } void IncidenceBase::setUid(const QString &uid) { mUid = uid; updated(); } QString IncidenceBase::uid() const { return mUid; } void IncidenceBase::setLastModified(const QDateTime &lm) { // DON'T! updated() because we call this from // Calendar::updateEvent(). mLastModified = getEvenTime(lm); //qDebug("IncidenceBase::setLastModified %s ",lm.toString().latin1()); } QDateTime IncidenceBase::lastModified() const { return mLastModified; } void IncidenceBase::setOrganizer(const QString &o) { // we don't check for readonly here, because it is // possible that by setting the organizer we are changing // the event's readonly status... mOrganizer = o; if (mOrganizer.left(7).upper() == "MAILTO:") mOrganizer = mOrganizer.remove(0,7); updated(); } QString IncidenceBase::organizer() const { return mOrganizer; } void IncidenceBase::setReadOnly( bool readOnly ) { mReadOnly = readOnly; } void IncidenceBase::setDtStart(const QDateTime &dtStart) { // if (mReadOnly) return; mDtStart = getEvenTime(dtStart); updated(); } + QDateTime IncidenceBase::dtStart() const { return mDtStart; } QString IncidenceBase::dtStartTimeStr() const { return KGlobal::locale()->formatTime(dtStart().time()); } QString IncidenceBase::dtStartDateStr(bool shortfmt) const { return KGlobal::locale()->formatDate(dtStart().date(),shortfmt); } QString IncidenceBase::dtStartStr(bool shortfmt) const { return KGlobal::locale()->formatDateTime(dtStart(), shortfmt); } bool IncidenceBase::doesFloat() const { return mFloats; } void IncidenceBase::setFloats(bool f) { if (mReadOnly) return; mFloats = f; updated(); } bool IncidenceBase::addAttendee(Attendee *a, bool doupdate) { if (mReadOnly) return false; if (a->name().left(7).upper() == "MAILTO:") a->setName(a->name().remove(0,7)); QPtrListIterator<Attendee> qli(mAttendees); qli.toFirst(); while (qli) { if (*qli.current() == *a) return false; ++qli; } mAttendees.append(a); if (doupdate) updated(); return true; } #if 0 void IncidenceBase::removeAttendee(Attendee *a) { if (mReadOnly) return; mAttendees.removeRef(a); updated(); } void IncidenceBase::removeAttendee(const char *n) { Attendee *a; diff --git a/libkcal/incidencebase.h b/libkcal/incidencebase.h index f9a6558..8624786 100644 --- a/libkcal/incidencebase.h +++ b/libkcal/incidencebase.h @@ -13,160 +13,160 @@ Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef KCAL_INCIDENCEBASE_H #define KCAL_INCIDENCEBASE_H // // Incidence - base class of calendaring components // #include <qdatetime.h> #include <qstringlist.h> #include <qvaluelist.h> #include <qptrlist.h> #include "customproperties.h" #include "attendee.h" namespace KCal { typedef QValueList<QDate> DateList; /** This class provides the base class common to all calendar components. */ class IncidenceBase : public CustomProperties { public: class Observer { public: virtual void incidenceUpdated( IncidenceBase * ) = 0; }; IncidenceBase(); IncidenceBase(const IncidenceBase &); virtual ~IncidenceBase(); virtual QCString type() const = 0; /** Set the unique id for the event */ void setUid(const QString &); /** Return the unique id for the event */ QString uid() const; /** Sets the time the incidence was last modified. */ void setLastModified(const QDateTime &lm); /** Return the time the incidence was last modified. */ QDateTime lastModified() const; /** sets the organizer for the event */ void setOrganizer(const QString &o); QString organizer() const; /** Set readonly status. */ virtual void setReadOnly( bool ); /** Return if the object is read-only. */ bool isReadOnly() const { return mReadOnly; } /** for setting the event's starting date/time with a QDateTime. */ virtual void setDtStart(const QDateTime &dtStart); /** returns an event's starting date/time as a QDateTime. */ - QDateTime dtStart() const; + virtual QDateTime dtStart() const; /** returns an event's starting time as a string formatted according to the users locale settings */ QString dtStartTimeStr() const; /** returns an event's starting date as a string formatted according to the users locale settings */ QString dtStartDateStr(bool shortfmt=true) const; /** returns an event's starting date and time as a string formatted according to the users locale settings */ QString dtStartStr(bool shortfmt=true) const; virtual void setDuration(int seconds); int duration() const; void setHasDuration(bool); bool hasDuration() const; /** Return true or false depending on whether the incidence "floats," * i.e. has a date but no time attached to it. */ bool doesFloat() const; /** Set whether the incidence floats, i.e. has a date but no time attached to it. */ void setFloats(bool f); /** Add Attendee to this incidence. IncidenceBase takes ownership of the Attendee object. */ bool addAttendee(Attendee *a, bool doupdate=true ); // void removeAttendee(Attendee *a); // void removeAttendee(const char *n); /** Remove all Attendees. */ void clearAttendees(); /** Return list of attendees. */ QPtrList<Attendee> attendees() const { return mAttendees; }; /** Return number of attendees. */ int attendeeCount() const { return mAttendees.count(); }; /** Return the Attendee with this email */ Attendee* attendeeByMail(const QString &); /** Return first Attendee with one of this emails */ Attendee* attendeeByMails(const QStringList &, const QString& email = QString::null); /** pilot syncronization states */ enum { SYNCNONE = 0, SYNCMOD = 1, SYNCDEL = 3 }; /** Set synchronisation satus. */ void setSyncStatus(int stat); /** Return synchronisation status. */ int syncStatus() const; /** Set Pilot Id. */ void setPilotId(int id); /** Return Pilot Id. */ int pilotId() const; void setTempSyncStat(int id); int tempSyncStat() const; void setIDStr( const QString & ); QString IDStr() const; void setID( const QString &, const QString & ); QString getID( const QString & ); void setCsum( const QString &, const QString & ); QString getCsum( const QString & ); void removeID(const QString &); void registerObserver( Observer * ); void unRegisterObserver( Observer * ); void updated(); protected: + QDateTime mDtStart; bool mReadOnly; QDateTime getEvenTime( QDateTime ); private: // base components - QDateTime mDtStart; QString mOrganizer; QString mUid; QDateTime mLastModified; QPtrList<Attendee> mAttendees; bool mFloats; int mDuration; bool mHasDuration; QString mExternalId; int mTempSyncStat; // PILOT SYNCHRONIZATION STUFF int mPilotId; // unique id for pilot sync int mSyncStatus; // status (for sync) QPtrList<Observer> mObservers; }; bool operator==( const IncidenceBase&, const IncidenceBase& ); } #endif diff --git a/libkcal/todo.cpp b/libkcal/todo.cpp index 9c04a7e..1f54c2f 100644 --- a/libkcal/todo.cpp +++ b/libkcal/todo.cpp @@ -250,165 +250,208 @@ void Todo::setStatus(const QString &statStr) else if (ss == "ACCEPTED") mStatus = ACCEPTED; else if (ss == "SENT") mStatus = SENT; else if (ss == "TENTATIVE") mStatus = TENTATIVE; else if (ss == "CONFIRMED") mStatus = CONFIRMED; else if (ss == "DECLINED") mStatus = DECLINED; else if (ss == "COMPLETED") mStatus = COMPLETED; else if (ss == "DELEGATED") mStatus = DELEGATED; updated(); } void Todo::setStatus(int status) { if (mReadOnly) return; mStatus = status; updated(); } int Todo::status() const { return mStatus; } QString Todo::statusStr() const { switch(mStatus) { case NEEDS_ACTION: return QString("NEEDS ACTION"); break; case ACCEPTED: return QString("ACCEPTED"); break; case SENT: return QString("SENT"); break; case TENTATIVE: return QString("TENTATIVE"); break; case CONFIRMED: return QString("CONFIRMED"); break; case DECLINED: return QString("DECLINED"); break; case COMPLETED: return QString("COMPLETED"); break; case DELEGATED: return QString("DELEGATED"); break; } return QString(""); } #endif bool Todo::isCompleted() const { - if (mPercentComplete == 100) return true; + if (mPercentComplete == 100) { + return true; + } else return false; } void Todo::setCompleted(bool completed) { + if ( mHasRecurrenceID && completed && mPercentComplete != 100 ) { + if ( !setRecurDates() ) + completed = false; + } if (completed) mPercentComplete = 100; else { mPercentComplete = 0; mHasCompletedDate = false; } updated(); } QDateTime Todo::completed() const { return mCompleted; } QString Todo::completedStr( bool shortF ) const { return KGlobal::locale()->formatDateTime(mCompleted, shortF); } void Todo::setCompleted(const QDateTime &completed) { //qDebug("Todo::setCompleted "); if ( mHasCompletedDate ) { // qDebug("has completed data - return "); return; } mHasCompletedDate = true; mPercentComplete = 100; mCompleted = getEvenTime(completed); updated(); } bool Todo::hasCompletedDate() const { return mHasCompletedDate; } int Todo::percentComplete() const { return mPercentComplete; } - +bool Todo::setRecurDates() +{ + if ( !mHasRecurrenceID ) + return true; + int secs = mDtStart.secsTo( dtDue() ); + bool ok; + qDebug("--------------------setRecurDates() "); + //qDebug("%s %s %s ",mDtStart.toString().latin1(), dtDue().toString().latin1(),mRecurrenceID.toString().latin1() ); + QDateTime next = getNextOccurence( mRecurrenceID, &ok ); + if ( ok ) { + mRecurrenceID = next; + mDtStart = next; + setDtDue( next.addSecs( secs ) ); + if ( QDateTime::currentDateTime() > next) + return false; + } else { + setHasRecurrenceID( false ); + recurrence()->unsetRecurs(); + } + return true; +} void Todo::setPercentComplete(int v) { + if ( mHasRecurrenceID && v == 100 && mPercentComplete != 100 ) { + if ( !setRecurDates() ) + v = 0; + } mPercentComplete = v; if ( v != 100 ) mHasCompletedDate = false; updated(); } QDateTime Todo::getNextAlarmDateTime( bool * ok, int * offset ) const { if ( isCompleted() || ! hasDueDate() || cancelled() ) { *ok = false; return QDateTime (); } QDateTime incidenceStart; incidenceStart = dtDue(); bool enabled = false; Alarm* alarm; int off = 0; QDateTime alarmStart = QDateTime::currentDateTime().addDays( 3650 );; // if ( QDateTime::currentDateTime() > incidenceStart ){ // *ok = false; // return incidenceStart; // } for (QPtrListIterator<Alarm> it(mAlarms); (alarm = it.current()) != 0; ++it) { if (alarm->enabled()) { if ( alarm->hasTime () ) { if ( alarm->time() < alarmStart ) { alarmStart = alarm->time(); enabled = true; off = alarmStart.secsTo( incidenceStart ); } } else { int secs = alarm->startOffset().asSeconds(); if ( incidenceStart.addSecs( secs ) < alarmStart ) { alarmStart = incidenceStart.addSecs( secs ); enabled = true; off = -secs; } } } } if ( enabled ) { if ( alarmStart > QDateTime::currentDateTime() ) { *ok = true; * offset = off; return alarmStart; } } *ok = false; return QDateTime (); } +void Todo::checkSetCompletedFalse() +{ + if ( !hasRecurrenceID() ) { + qDebug("ERROR 1 in Todo::checkSetCompletedFalse"); + } + // qDebug("Todo::checkSetCompletedFalse()"); + //qDebug("%s %s %s ",mDtStart.toString().latin1(), dtDue().toString().latin1(),mRecurrenceID.toString().latin1() ); + if ( mPercentComplete == 100 && mDtStart == mRecurrenceID && QDateTime::currentDateTime() > mDtStart) { + qDebug("%s %s %s ",mDtStart.toString().latin1(), dtDue().toString().latin1(),mRecurrenceID.toString().latin1() ); + setCompleted( false ); + qDebug("Todo::checkSetCompletedFalse++++++++++++++++++++++++++++ "); + } +} diff --git a/libkcal/todo.h b/libkcal/todo.h index 137b252..a22d4b7 100644 --- a/libkcal/todo.h +++ b/libkcal/todo.h @@ -51,84 +51,86 @@ class Todo : public Incidence users locale settings */ QString dtDueTimeStr() const; /** returns an event's due date as a string formatted according to the users locale settings */ QString dtDueDateStr(bool shortfmt=true) const; /** returns an event's due date and time as a string formatted according to the users locale settings */ QString dtDueStr(bool shortfmt=true) const; /** returns TRUE or FALSE depending on whether the todo has a due date */ bool hasDueDate() const; /** sets the event's hasDueDate value. */ void setHasDueDate(bool f); /* Looks for a subtodo (including itself ) which is not complete and is - overdue, or - due today. It returns 0 for nothing found, 1 for found a todo which is due today and no overdue found 2 for found a overdue todo */ int hasDueSubTodo( bool checkSubtodos = true ); /* same as above, but a specific date can be specified*/ int hasDueSubTodoForDate( const QDate & date, bool checkSubtodos ); /** sets the event's status to the string specified. The string * must be a recognized value for the status field, i.e. a string * equivalent of the possible status enumerations previously described. */ // void setStatus(const QString &statStr); /** sets the event's status to the value specified. See the enumeration * above for possible values. */ // void setStatus(int); /** return the event's status. */ // int status() const; /** return the event's status in string format. */ // QString statusStr() const; /** return, if this todo is completed */ bool isCompleted() const; /** set completed state of this todo */ void setCompleted(bool); /** Return how many percent of the task are completed. Returns a value between 0 and 100. */ int percentComplete() const; /** Set how many percent of the task are completed. Valid values are in the range from 0 to 100. */ void setPercentComplete(int); /** return date and time when todo was completed */ QDateTime completed() const; QString completedStr(bool shortF = true) const; /** set date and time of completion */ void setCompleted(const QDateTime &completed); /** Return true, if todo has a date associated with completion */ bool hasCompletedDate() const; bool contains ( Todo*); + void checkSetCompletedFalse(); + bool setRecurDates(); private: bool accept(Visitor &v) { return v.visit(this); } QDateTime mDtDue; // due date of todo bool mHasDueDate; // if todo has associated due date // int mStatus; // confirmed/delegated/tentative/etc QDateTime mCompleted; bool mHasCompletedDate; int mPercentComplete; }; bool operator==( const Todo&, const Todo& ); } #endif |