libkpimexchange Library API Documentation

dateset.cpp

00001 /*
00002     This file is part of libkpimexchange.
00003     Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org>
00004 
00005     This library is free software; you can redistribute it and/or modify it
00006     under the terms of the GNU Library General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or (at your
00008     option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful, but WITHOUT
00011     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013     License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to the
00017     Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00018     02111-1307, USA.
00019 */
00020 
00021 // $Id: dateset.cpp,v 1.2 2002/08/05 13:19:11 janpascal Exp $
00022 
00023 #include <qptrlist.h>
00024 #include <qdatetime.h>
00025 #include <qpair.h>
00026 
00027 #include <kdebug.h>
00028 
00029 #include "dateset.h"
00030 
00031 DateSet::DateSet()
00032 {
00033   kdDebug() << "Creating DateSet" << endl;
00034   // mOldestDate = 
00035   mDates = new RangeList();
00036   mDates->setAutoDelete( true );
00037 }
00038 
00039 DateSet::~DateSet()
00040 {
00041   kdDebug() << "Deleting DateSet" << endl;
00042   delete mDates;
00043 }
00044 
00045 void DateSet::add( QDate const& date )
00046 {
00047   if (mDates->isEmpty()) {
00048     mDates->insert( 0, new QPair<QDate,QDate>( date, date ) );
00049     return;
00050   } 
00051   int i = find( date );
00052   mDates->insert( i, new QPair<QDate,QDate>( date, date ) );
00053   tryMerge( i );
00054   tryMerge( i-1 );
00055 }
00056 
00057 void DateSet::add( QDate const& from, QDate const& to )
00058 {
00059   if (mDates->isEmpty()) {
00060     mDates->insert( 0, new QPair<QDate,QDate>( from, to ) );
00061     return;
00062   } 
00063   uint i = find( from );
00064   kdDebug() << "Adding range at position " << i << endl;
00065   mDates->insert( i, new QPair<QDate,QDate>( from, to ) );
00066 
00067   do {
00068   } while ( tryMerge( i ) );
00069   do {
00070   } while ( tryMerge( i-1 ) );
00071 /*  
00072   QPair<QDate,QDate>* item = mDates->at( i );
00073 
00074   if (to >= item->first)
00075     return;
00076 
00077   if (to.daysTo( item->first ) == 1 )
00078     item->first = from;
00079   else
00080     mDates->insert( i, new QPair<QDate,QDate>( from, to ) );
00081 */
00082 }
00083 
00084 void DateSet::remove( QDate const& date )
00085 {
00086   if (mDates->isEmpty()) {
00087     return;
00088   } 
00089 
00090   uint i = find( date );
00091   if ( i == mDates->count() )
00092     return;
00093 
00094   QPair<QDate,QDate>* item = mDates->at( i );
00095   if ( date < item->first )
00096     return;
00097   if ( date == item->first ) {
00098     if ( date == item->second ) {
00099       mDates->remove( i );
00100     } else {
00101       item->first = item->first.addDays( 1 );
00102     }
00103     return;
00104   }
00105 
00106   if ( date == item->second ) {
00107     item->second = item->second.addDays( -1 );
00108   } else {
00109     mDates->insert( i, new QPair<QDate,QDate>(item->first, date.addDays( -1 ) ) );
00110     item->first = date.addDays( 1 );
00111   }
00112 }
00113 
00114 void DateSet::remove( QDate const& from, QDate const& to )
00115 {
00116   if (mDates->isEmpty()) {
00117     return;
00118   } 
00119   
00120   uint i = find( from );
00121   if ( i == mDates->count() )
00122     return;
00123   
00124   while( i < mDates->count() ) {
00125     QPair<QDate,QDate>* item = mDates->at( i );
00126     // Check if we're done: next item is later dan removal period
00127     if ( to < item->first )
00128       break;
00129 
00130     // Check if entire item should be removed
00131     if ( from <= item->first && to >= item->second ) {
00132       mDates->remove( i );
00133       // Don't skip the next range
00134       continue;
00135     }
00136 
00137     // Check if we should take a slice out of the middle of the item
00138     if ( from > item->first && to < item->second ) {
00139       mDates->insert( i, new QPair<QDate,QDate>( item->first, from.addDays( -1 ) ) );
00140       item->first = to.addDays( 1 );
00141       break; // We're done
00142     }
00143 
00144     // Now check if we should take off the beginning of the item
00145     if ( from <= item->first ) {
00146       item->first = to.addDays( 1 );
00147       // Finished
00148       break;
00149     }
00150 
00151     // Only one possibility left: we should take off the end
00152     // of the current range
00153     item->second = from.addDays( -1 );
00154     i++;
00155   }
00156 }
00157 
00158 bool DateSet::contains( QDate const& date )
00159 {
00160   if (mDates->isEmpty()) {
00161     return false;
00162   } 
00163 
00164   uint i = find( date );
00165 //  kdDebug() << "contains looking for " << date.toString() << " at range " << i << endl;
00166   if ( i == mDates->count() )
00167     return false;
00168 
00169   QPair<QDate,QDate>* item = mDates->at( i );
00170   // kdDebug() << "contains looking at range " << item->first.toString() << " -- " << item->second.toString() << endl;
00171   return ( item->first <= date );
00172 }
00173 
00174 // returns true if and only if the whole range is in the set
00175 bool DateSet::contains( QDate const& from, QDate const& to )
00176 {
00177   if (mDates->isEmpty()) {
00178     return false;
00179   } 
00180 
00181   uint i = find( from );
00182   if ( i == mDates->count() )
00183     return false;
00184 
00185   QPair<QDate,QDate>* item = mDates->at( i );
00186 
00187   return ( from >= item->first && to <= item->second );
00188 }
00189 
00190 // Finds the index in mDates of the range containing date, if it
00191 // exists. Else, return the index of the range following the date.
00192 // If mDates is empty, return 0.
00193 // If date is later than the last item in mDates, return mDates->count()
00194 
00195 int DateSet::find( QDate const& date )
00196 {
00197   if ( mDates->isEmpty() )
00198     return 0;
00199 
00200   int start = 0;
00201   int end = mDates->count();
00202   while ( start < end ) {
00203     int i = start + (end-start) / 2;
00204     // kdDebug() << start << ", " << i << ", " << end << endl;
00205     QPair<QDate,QDate> *item = mDates->at( i );
00206     if ( item->first <= date && date <= item->second )
00207       return i;
00208     if ( date > item->second ) {
00209       start = i+1;
00210     } else { // this means date < item->first
00211       end = i;
00212     }
00213   }
00214 
00215   // kdDebug() << "Found for date " << date.toString() << " range " << end << endl;
00216   return end;
00217 /*
00218   // Now either start==end or start+1 == end
00219   if ( mDates->at( end )->second < date )
00220     return end+1;
00221   else if (mDates->at( start )->first > date )
00222     return start;
00223   else
00224     return end;
00225 */
00226 }
00227 
00228 void DateSet::print()
00229 {
00230   for( uint i=0; i<mDates->count(); i++ )
00231   {
00232     QDate start = mDates->at( i )->first;
00233     QDate end = mDates->at( i )->second;
00234     if (start == end)
00235       kdDebug() << start.toString() << endl;
00236     else
00237       kdDebug() << "(" << start.toString() << " , " << end.toString() << ")" << endl;
00238   }
00239 }
00240 
00241 // Try and merge range i with range i+1
00242 // NOT TRUE preconditions: range i starts before range i+1, but MAY end later!
00243 // preconditions: range i starts before or in range i+1
00244 bool DateSet::tryMerge( int i )
00245 {
00246   if ( i < 0 || i+1 >= mDates->count() )
00247     return false;
00248 
00249   QPair<QDate,QDate>* item1 = mDates->at( i );
00250   QPair<QDate,QDate>* item2 = mDates->at( i+1 );
00251 
00252   // First case: item1 starts before or on the same date as item2
00253   if ( item1->first <= item2->first ) {
00254     // Check for overlap
00255     if ( item1->second >= item2->first ||
00256          item1->second.daysTo( item2->first ) == 1 ) {
00257       kdDebug() << "Merging items " << i << " and " << (i+1) << endl;
00258       if (item1->second < item2->second) item1->second = item2->second;
00259       mDates->remove( i+1 );
00260       return true;
00261     }
00262     return false;
00263   }
00264 
00265   // Second case: item1 starts later than item2 (but at the latest on
00266   // the last day of item2, see preconditions!)
00267   
00268   // Check for overlap
00269   if ( item1->second >= item2->first ||
00270        item1->second.daysTo( item2->first ) == 1 ) {
00271     kdDebug() << "Merging items " << i << " and " << (i+1) << endl;
00272     if (item1->second < item2->second) item1->second = item2->second;
00273     item1->first = item2->first;
00274     mDates->remove( i+1 );
00275     return true;
00276   }
00277   return false;
00278 }
00279 
00280 
KDE Logo
This file is part of the documentation for libkpimexchange Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:38:09 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003