summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--bin/kdepim/WhatsNew.txt1
-rw-r--r--korganizer/calendarview.cpp72
-rw-r--r--libkcal/event.cpp20
-rw-r--r--libkcal/event.h1
4 files changed, 71 insertions, 23 deletions
diff --git a/bin/kdepim/WhatsNew.txt b/bin/kdepim/WhatsNew.txt
index 1f06f1e..c0d63e5 100644
--- a/bin/kdepim/WhatsNew.txt
+++ b/bin/kdepim/WhatsNew.txt
@@ -1,39 +1,40 @@
Info about the changes in new versions of KDE-Pim/Pi
********** VERSION 2.1.16 ************
Fixed a problem with the menu bar in KO/Pi and using the "Menu" hardware key on the Zaurus.
Added columns for datetime in todo view: Last modified, created and last modified subtodo
Fixed a bug in agenda view displaying recurring multiday events which are longer than two days.
+Made conflict detection up to 4 times faster.
********** VERSION 2.1.15 ************
Fixed two layout problems on the Z:
Made the with of the newly added buttons on the Quick-Todo smaller.
Made listweek layout in 2 columns on the Z760 in portait screen and full menubar visible.
********** VERSION 2.1.14 ************
Added some buttons to the KO/Pi Quick-todo line to make it possible to quickly access some todo view layout settings like display all flat/open/close and hide/show running/done.
Added a button to add a subtodo quickly.
Added a possibility to search for conflicting events. (In the Action menu. Keyboard shortcut "q", shift+q or ctrl +q ).
Added an option to change the layout of the list week to column mode.
Fixed some usability problems in pi-sync mode by adding some progress information about file transfer.
Fixed pi-sync problems with the new multi calendar feature.
Now pi-sync behaviour should be:
1) Local sends file request ( as usual )
2) Remote sends file which contains data of all enabled ( the calendar where the "eye" column is checked ) calendars.
3) Local syncs with data, adds new entries to default calendar and sends file back ( as usual ).
If the data which local receives contains entries which are on disabled calendars on local this entries are updated and not added as duplicates to the default calendar.
4) Remote updates the data and adds new entries to default calendar. Readonly entries are not changed on remote.
If the data which remote receives contains entries which are on disabled calendars on remote this entries are updated and not added as duplicates to the default calendar.
Summary:
No new item ( new created after the last sync ) in a disabled calendar is propagated to the sync partner. Readonly items are synced and added/changed on the sync partner if it is not readonly on the sync partner.
If you have different calendars on remote and local and some of them disabled you may get some "strange" bahaviour.
Well, the syncing has become quite complicated ... you should have no problems if you enable all calendars.
diff --git a/korganizer/calendarview.cpp b/korganizer/calendarview.cpp
index a9e402e..427d71b 100644
--- a/korganizer/calendarview.cpp
+++ b/korganizer/calendarview.cpp
@@ -630,133 +630,150 @@ void CalendarView::init()
connect( mSuspendTimer, SIGNAL( timeout () ), SLOT( suspendAlarm() ) );
connect( mAlarmTimer, SIGNAL( timeout () ), SLOT( timerAlarm() ) );
mAlarmDialog = new AlarmDialog( this );
connect( mAlarmDialog, SIGNAL( addAlarm(const QDateTime &, const QString & ) ), SLOT( addSuspendAlarm(const QDateTime &, const QString & ) ) );
mAlarmDialog->setServerNotification( false );
mAlarmDialog->setSuspendTime( KOPrefs::instance()->mAlarmSuspendTime );
#ifndef DESKTOP_VERSION
//US listen for arriving address resultsets
connect(ExternalAppHandler::instance(), SIGNAL(receivedBirthdayListEvent(const QString&, const QStringList&, const QStringList&, const QStringList&, const QStringList&, const QStringList&, const QStringList&)),
this, SLOT(insertBirthdays(const QString&, const QStringList&, const QStringList&, const QStringList&, const QStringList&, const QStringList&, const QStringList&)));
#endif
mDateNavigator->setCalendar( mCalendar );
}
CalendarView::~CalendarView()
{
// kdDebug() << "~CalendarView()" << endl;
//qDebug("CalendarView::~CalendarView() ");
delete mDialogManager;
delete mViewManager;
delete mStorage;
delete mDateFrame ;
delete mEventViewerDialog;
//kdDebug() << "~CalendarView() done" << endl;
}
void CalendarView::nextConflict( bool all, bool allday )
{
-
+ static bool block = false;
+ if ( block ) return;
+ block = true;
QPtrList<Event> testlist = mCalendar->events();
Event * test = testlist.first();
while ( test ) {
test->setTagged( false );
test = testlist.next();
}
QTime st ( 0,0,0);
if ( mViewManager->currentView() == mViewManager->agendaView() )
st = mViewManager->agendaView()->agenda()->getEndTime();
//qDebug("time %s ", st.toString().latin1());
QDateTime startDT = QDateTime (mNavigator->selectedDates().first(),st);
QDateTime conflict;
QDateTime retVal;
bool found = false;
Event * cE = 0;
Event * cE2 = 0;
QPtrList<Event> testlist2 = testlist;
test = testlist.first();
bool skip = false;
topLevelWidget()->setCaption( i18n("Checking conflicts ... please wait") );
+ //QTime tm;
+ //tm.start();
while ( test ) {
qApp->processEvents();
skip = false;
if ( !all ) skip = ( allday != test->doesFloat() );
if ( !skip ) {
+ if ( found )
+ skip = !test->matchTime( &startDT, &conflict );
+ else
+ skip = !test->matchTime( &startDT, 0 );
+ }
+ if ( !skip ) {
Event * test2 = testlist2.first();
while ( test2 ) {
- skip = false;
- if ( !all ) skip = ( allday != test2->doesFloat() );
+ skip = test2->isTagged();
+ if ( !skip && !all ) skip = ( allday != test2->doesFloat() );
+ if ( !skip ) {
+ if ( found )
+ skip = !test2->matchTime( &startDT, &conflict );
+ else
+ skip = !test2->matchTime( &startDT, 0 );
+ }
if ( !skip ) {
- if ( !test2->isTagged() ) {
- if ( test->isOverlapping ( test2, &retVal, &startDT ) ) {
- //qDebug("overlap ");
- if ( ! found ) {
- if ( retVal >= startDT ) {
- conflict = retVal;
- cE = test;
- cE2 = test2;
- found = true;
- }
- } else {
- if ( retVal >= startDT && retVal < conflict ) {
- conflict = retVal;
- cE = test;
- cE2 = test2;
- }
+ if ( test->isOverlapping ( test2, &retVal, &startDT ) ) {
+ //qDebug("overlap ");
+ if ( ! found ) {
+ if ( retVal >= startDT ) {
+ conflict = retVal;
+ cE = test;
+ cE2 = test2;
+ found = true;
+ }
+ } else {
+ if ( retVal >= startDT && retVal < conflict ) {
+ conflict = retVal;
+ cE = test;
+ cE2 = test2;
}
}
}
}
test2 = testlist2.next();
}
}
test->setTagged( true );
test = testlist.next();
}
+ //qDebug("Search time : %d", tm.elapsed());
if ( found ) {
if ( mViewManager->currentView() != mViewManager->agendaView() || mNavigator->selectedDates().count() > 1 )
mViewManager->showDayView();
mNavigator->slotDaySelect( conflict.date() );
int hour = conflict.time().hour();
mViewManager->agendaView()->setStartHour( hour );
topLevelWidget()->setCaption( i18n("Conflict %1 <-> %2"). arg( cE->summary().left( 20 ) ).arg( cE2->summary().left( 20 ) ) );
+ block = false;
return;
}
topLevelWidget()->setCaption( i18n("No conflict found") );
qDebug("No conflict found ");
+ block = false;
return;
}
void CalendarView::conflictAll()
{
nextConflict ( true, true );
}
void CalendarView::conflictAllday()
{
nextConflict ( false, true );
}
void CalendarView::conflictNotAll()
{
nextConflict ( false, false );
}
void CalendarView::setCalReadOnly( int id, bool readO )
{
if ( readO ) {
emit save();
}
mCalendar->setReadOnly( id, readO );
}
void CalendarView::setScrollBarStep(int val )
{
#ifdef DESKTOP_VERSION
mDateScrollBar->setLineStep ( val );
#endif
}
void CalendarView::scrollBarValue(int val )
{
#ifdef DESKTOP_VERSION
@@ -2743,75 +2760,84 @@ void CalendarView::changeEventDisplay(Event *which, int action)
static bool clearallviews = false;
if ( KOPrefs::instance()->mGlobalUpdateDisabled ) {
if ( clearallviews ) {
clearAllViews();
clearallviews = false;
}
return;
}
clearallviews = true;
mDateNavigator->updateView();
//mDialogManager->updateSearchDialog();
if (which) {
// If there is an event view visible update the display
mViewManager->currentView()->changeEventDisplay(which,action);
// TODO: check, if update needed
// if (which->getTodoStatus()) {
mTodoList->updateView();
if ( action != KOGlobals::EVENTDELETED ) {
mConflictingEvent = which ;
QTimer::singleShot( 1000, this, SLOT ( checkConflictForEvent() ) );
}
// }
} else {
mViewManager->currentView()->updateView();
}
}
void CalendarView::checkConflictForEvent()
{
if (!KOPrefs::instance()->mConfirm)
return;
if ( ! mConflictingEvent ) return;
- topLevelWidget()->setCaption( i18n("Checking conflicts ... please wait") );
+ QDateTime current = QDateTime::currentDateTime();
+ if ( ! mConflictingEvent->matchTime( &current, 0 ) ) {
+ mConflictingEvent = 0;
+ return;
+ }
QPtrList<Event> testlist = mCalendar->events();
Event * test = testlist.first();
QDateTime conflict;
QDateTime retVal;
bool found = false;
Event * cE = 0;
- QDateTime current = QDateTime::currentDateTime();
+ topLevelWidget()->setCaption( i18n("Checking conflicts ... please wait") );
while ( test ) {
- qApp->processEvents();
- if ( !test->doesFloat() ) {
+ qApp->processEvents();
+ bool skip = false;
+ if ( found )
+ skip = !test->matchTime( &current, &conflict );
+ else
+ skip = !test->matchTime( &current, 0 );
+ if ( !skip && !test->doesFloat() ) {
if ( mConflictingEvent->isOverlapping ( test, &retVal, &current ) ) {
if ( ! found ) {
conflict = retVal;
cE = test;
} else {
if ( retVal < conflict ) {
conflict = retVal;
cE = test;
}
}
found = true;
}
}
test = testlist.next();
}
if ( found ) {
QString mess = i18n("The event\n%1\nconflicts with event\n%2\nat date\n%3.\n").arg(KGlobal::formatMessage ( mConflictingEvent->summary(),0 ) ).arg( KGlobal::formatMessage ( cE->summary(),0 )).arg(KGlobal::locale()->formatDate(conflict.date()) ) ;
qApp->processEvents();
int km = KMessageBox::warningContinueCancel(this,mess,
i18n("KO/Pi Conflict delected"),i18n("Show date"),i18n("No problem!"));
if ( km != KMessageBox::Continue )
return;
if ( mViewManager->currentView() != mViewManager->agendaView() || mNavigator->selectedDates().count() > 1 )
mViewManager->showDayView();
mNavigator->slotDaySelect( conflict.date() );
int hour = conflict.time().hour();
mViewManager->agendaView()->setStartHour( hour );
topLevelWidget()->setCaption( i18n("Conflict %1 <-> %2"). arg( mConflictingEvent->summary().left( 20 ) ).arg( cE->summary().left( 20 ) ) );
} else
topLevelWidget()->setCaption( i18n("No conflict found") );
mConflictingEvent = 0;
diff --git a/libkcal/event.cpp b/libkcal/event.cpp
index 5285559..ad66639 100644
--- a/libkcal/event.cpp
+++ b/libkcal/event.cpp
@@ -142,64 +142,84 @@ void Event::setHasEndDate(bool b)
{
mHasEndDate = b;
}
bool Event::hasEndDate() const
{
return mHasEndDate;
}
bool Event::isMultiDay() const
{
bool multi = !(dtStart().date() == dtEnd().date());
return multi;
}
void Event::setTransparency(Event::Transparency transparency)
{
if (mReadOnly) return;
mTransparency = transparency;
updated();
}
Event::Transparency Event::transparency() const
{
return mTransparency;
}
void Event::setDuration(int seconds)
{
setHasEndDate(false);
Incidence::setDuration(seconds);
}
+bool Event::matchTime(QDateTime*startDT, QDateTime* endDT)
+{
+ if ( ! doesRecur() ) {
+ if ( doesFloat() ) {
+ if ( mDtEnd.addDays( 1 ) < *startDT)
+ return false;
+ if ( endDT && mDtStart > * endDT)
+ return false;
+ } else {
+ if ( mDtEnd < *startDT )
+ return false;
+ if ( endDT && mDtStart > * endDT)
+ return false;
+ }
+ } else {
+ if ( endDT && mDtStart > * endDT)
+ return false;
+ }
+ return true;
+}
bool Event::isOverlapping ( Event* testEvent, QDateTime* overlapDT, QDateTime* startDT )
{
if ( testEvent == this )
return false;
if ( ! doesRecur() && !testEvent->doesRecur() ) {
QDateTime te;
if ( testEvent->doesFloat() )
te = testEvent->mDtEnd.addDays( 1 );
else
te = testEvent->mDtEnd;
QDateTime e;
if ( doesFloat() )
e = mDtEnd.addDays( 1 );
else
e = mDtEnd;
if ( mDtStart < te && testEvent->mDtStart < e ) {
if ( mDtStart < testEvent->mDtStart )
*overlapDT = testEvent->mDtStart;
else
*overlapDT = mDtStart;
if ( startDT )
return (*overlapDT >= *startDT );
return true;
}
return false;
}
if ( !doesFloat() && !testEvent->doesFloat() && !isMultiDay() && !testEvent->isMultiDay() ) {
if ( mDtStart.time() >= testEvent->mDtEnd.time() || testEvent->mDtStart.time() >= mDtEnd.time() ) {
// no need to test. times mismatch
//fprintf(stderr,"timi ");
return false;
}
diff --git a/libkcal/event.h b/libkcal/event.h
index e6055a5..2da9770 100644
--- a/libkcal/event.h
+++ b/libkcal/event.h
@@ -9,64 +9,65 @@
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
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 EVENT_H
#define EVENT_H
//
// Event component, representing a VEVENT object
//
#include "incidence.h"
namespace KCal {
/**
This class provides an Event in the sense of RFC2445.
*/
class Event : public Incidence
{
public:
enum Transparency { Opaque, Transparent };
typedef ListBase<Event> List;
Event();
Event(const Event &);
~Event();
+ bool matchTime(QDateTime*startDT, QDateTime* endDT);
QCString type() const { return "Event"; }
IncTypeID typeID() const { return eventID; }
Incidence *clone();
QDateTime getNextAlarmDateTime( bool * ok, int * offset ,QDateTime start_dt ) const;
/** for setting an event's ending date/time with a QDateTime. */
void setDtEnd(const QDateTime &dtEnd);
/** Return the event's ending date/time as a QDateTime. */
virtual QDateTime dtEnd() const;
/** returns an event's end time as a string formatted according to the
users locale settings */
QString dtEndTimeStr() const;
/** returns an event's end date as a string formatted according to the
users locale settings */
QString dtEndDateStr(bool shortfmt=true) const;
/** returns an event's end date and time as a string formatted according
to the users locale settings */
QString dtEndStr(bool shortfmt=true) const;
void setHasEndDate(bool);
/** Return whether the event has an end date/time. */
bool hasEndDate() const;
/** Return true if the event spans multiple days, otherwise return false. */
bool isMultiDay() const;
/** set the event's time transparency level. */
void setTransparency(Transparency transparency);
/** get the event's time transparency level. */
Transparency transparency() const;