Skip to content

Commit

Permalink
[nemo-qml-plugin-calendar] Give AgendaModel an endDate
Browse files Browse the repository at this point in the history
Also merges the events when the start or end dates are changed,
rather than resetting the model.  This allows for more elegant
views.
  • Loading branch information
Aaron Kennedy committed Jun 27, 2013
1 parent 91980e3 commit be7777d
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 18 deletions.
151 changes: 134 additions & 17 deletions src/calendaragendamodel.cpp
Expand Up @@ -42,7 +42,8 @@
#include "calendardb.h"

NemoCalendarAgendaModel::NemoCalendarAgendaModel(QObject *parent)
: NemoCalendarAbstractModel(parent)
: NemoCalendarAbstractModel(parent), mBuffer(0), mRefreshingModel(false),
mRerefreshNeeded(false)
{
mRoleNames[EventObjectRole] = "event";
mRoleNames[SectionBucketRole] = "sectionBucket";
Expand All @@ -52,8 +53,7 @@ NemoCalendarAgendaModel::NemoCalendarAgendaModel(QObject *parent)
setRoleNames(mRoleNames);
#endif

connect(this, SIGNAL(startDateChanged()), this, SLOT(load()));
connect(NemoCalendarEventCache::instance(), SIGNAL(modelReset()), this, SLOT(load()));
connect(NemoCalendarEventCache::instance(), SIGNAL(modelReset()), this, SLOT(refresh()));
}

NemoCalendarAgendaModel::~NemoCalendarAgendaModel()
Expand All @@ -80,30 +80,128 @@ void NemoCalendarAgendaModel::setStartDate(const QDate &startDate)

mStartDate = startDate;
emit startDateChanged();

refresh();
}

void NemoCalendarAgendaModel::load()
QDate NemoCalendarAgendaModel::endDate() const
{
// TODO: we really need a centralised event cache
KCalCore::Event::List eventList = NemoCalendarDb::calendar()->rawEventsForDate(mStartDate, KDateTime::Spec(KDateTime::LocalZone), KCalCore::EventSortStartDate, KCalCore::SortDirectionAscending);
qDebug() << Q_FUNC_INFO << "Loaded " << eventList.count() << " events for " << mStartDate;
return mEndDate;
}

beginResetModel();
qDeleteAll(mEvents);
void NemoCalendarAgendaModel::setEndDate(const QDate &endDate)
{
if (mEndDate == endDate)
return;

mEndDate = endDate;
emit endDateChanged();

refresh();
}

void NemoCalendarAgendaModel::refresh()
{
if (mRefreshingModel) {
mRerefreshNeeded = true;
return;
}

int oldSize = mEvents.size();
mRefreshingModel = true;
doRefresh();
mRefreshingModel = false;
if (mRerefreshNeeded) {
mRerefreshNeeded = false;
refresh();
}
}

mEvents.clear();
mEvents.reserve(eventList.size());
static bool eventsEqual(const KCalCore::Event::Ptr &e1, const KCalCore::Event::Ptr &e2)
{
return e1 == e2 || e1->uid() == e2->uid();
}

foreach (const KCalCore::Event::Ptr &evt, eventList) {
NemoCalendarEvent *event = new NemoCalendarEvent(evt);
mEvents.append(event);
static bool eventsLessThan(const KCalCore::Event::Ptr &e1, const KCalCore::Event::Ptr &e2)
{
const KDateTime d1 = e1->dtStart();
KDateTime::Comparison res = d1.compare(e2->dtStart());
if (res == KDateTime::Equal) {
int cmp = QString::compare(e1->summary(), e2->summary(), Qt::CaseInsensitive);
if (cmp == 0) return QString::compare(e1->uid(), e2->uid()) < 0;
else return cmp < 0;
} else {
return (res & KDateTime::Before || res & KDateTime::AtStart);
}
}

void NemoCalendarAgendaModel::doRefresh()
{
mKCal::ExtendedCalendar::Ptr calendar = NemoCalendarDb::calendar();

// Sorting function
bool (*lessThan)(const KCalCore::Event::Ptr &e1, const KCalCore::Event::Ptr &e2);
lessThan = eventsLessThan;

// Matching function
bool (*equal)(const KCalCore::Event::Ptr &e1, const KCalCore::Event::Ptr &e2);
equal = eventsEqual;

endResetModel();

if (oldSize != mEvents.size())
KCalCore::Event::List newEvents = calendar->rawEvents(mStartDate, mEndDate.isValid()?mEndDate:mStartDate,
KDateTime::Spec(KDateTime::LocalZone));
qSort(newEvents.begin(), newEvents.end(), lessThan);

QList<NemoCalendarEvent *> events = mEvents;

int newEventsCounter = 0;
int eventsCounter = 0;

int mEventsIndex = 0;

while (newEventsCounter < newEvents.count() || eventsCounter < events.count()) {
// Remove old events
int removeCount = 0;
while ((eventsCounter + removeCount) < events.count() &&
(newEventsCounter >= newEvents.count() ||
lessThan(events.at(eventsCounter + removeCount)->event(), newEvents.at(newEventsCounter))))
removeCount++;

if (removeCount) {
beginRemoveRows(QModelIndex(), mEventsIndex, mEventsIndex + removeCount - 1);
mEvents.erase(mEvents.begin() + mEventsIndex, mEvents.begin() + mEventsIndex + removeCount);
endRemoveRows();
for (int ii = eventsCounter; ii < eventsCounter + removeCount; ++ii)
delete events.at(ii);
eventsCounter += removeCount;
}

// Skip matching events
while (eventsCounter < events.count() && newEventsCounter < newEvents.count() &&
equal(newEvents.at(newEventsCounter), events.at(eventsCounter)->event())) {
eventsCounter++;
newEventsCounter++;
mEventsIndex++;
}

// Insert new events
int insertCount = 0;
while ((newEventsCounter + insertCount) < newEvents.count() &&
(eventsCounter >= events.count() ||
lessThan(newEvents.at(newEventsCounter + insertCount), events.at(eventsCounter)->event())))
insertCount++;

if (insertCount) {
beginInsertRows(QModelIndex(), mEventsIndex, mEventsIndex + insertCount - 1);
for (int ii = 0; ii < insertCount; ++ii) {
NemoCalendarEvent *event = new NemoCalendarEvent(newEvents.at(newEventsCounter + ii));
mEvents.insert(mEventsIndex++, event);
}
newEventsCounter += insertCount;
endInsertRows();
}
}

if (events.count() != mEvents.count())
emit countChanged();
}

Expand All @@ -112,6 +210,25 @@ int NemoCalendarAgendaModel::count() const
return mEvents.size();
}

int NemoCalendarAgendaModel::minimumBuffer() const
{
return mBuffer;
}

void NemoCalendarAgendaModel::setMinimumBuffer(int b)
{
if (mBuffer == b)
return;

mBuffer = b;
emit minimumBufferChanged();
}

int NemoCalendarAgendaModel::startDateIndex() const
{
return 0;
}

int NemoCalendarAgendaModel::rowCount(const QModelIndex &index) const
{
if (index != QModelIndex())
Expand Down
24 changes: 23 additions & 1 deletion src/calendaragendamodel.h
Expand Up @@ -43,6 +43,10 @@ class NemoCalendarAgendaModel : public NemoCalendarAbstractModel
Q_OBJECT
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(QDate startDate READ startDate WRITE setStartDate NOTIFY startDateChanged)
Q_PROPERTY(QDate endDate READ endDate WRITE setEndDate NOTIFY endDateChanged)

Q_PROPERTY(int minimumBuffer READ minimumBuffer WRITE setMinimumBuffer NOTIFY minimumBufferChanged)
Q_PROPERTY(int startDateIndex READ startDateIndex NOTIFY startDateIndexChanged)

public:
enum {
Expand All @@ -57,27 +61,45 @@ class NemoCalendarAgendaModel : public NemoCalendarAbstractModel
QDate startDate() const;
void setStartDate(const QDate &startDate);

QDate endDate() const;
void setEndDate(const QDate &endDate);

int count() const;

int minimumBuffer() const;
void setMinimumBuffer(int);

int startDateIndex() const;

int rowCount(const QModelIndex &index) const;
QVariant data(const QModelIndex &index, int role) const;

signals:
void countChanged();
void startDateChanged();
void minimumBufferChanged();
void startDateIndexChanged();
void endDateChanged();

#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
protected:
virtual QHash<int, QByteArray> roleNames() const;
#endif

private slots:
void load();
void refresh();

private:
void doRefresh();

QDate mStartDate;
QDate mEndDate;
int mBuffer;
QList<NemoCalendarEvent *> mEvents;
QHash<int,QByteArray> mRoleNames;

bool mRefreshingModel:1;
bool mRerefreshNeeded:1;
};

#endif // CALENDARAGENDAMODEL_H
1 change: 1 addition & 0 deletions src/calendarevent.cpp
Expand Up @@ -123,6 +123,7 @@ void NemoCalendarEvent::save()
mEvent->setRevision(mEvent->revision() + 1);
}

//
// TODO: this sucks
NemoCalendarDb::storage()->save();
}
12 changes: 12 additions & 0 deletions src/calendarevent.h
Expand Up @@ -69,6 +69,8 @@ class NemoCalendarEvent : public QObject

Q_INVOKABLE void save();

inline KCalCore::Event::Ptr &event();
inline const KCalCore::Event::Ptr &event() const;
signals:
void displayLabelChanged();
void descriptionChanged();
Expand All @@ -80,4 +82,14 @@ class NemoCalendarEvent : public QObject
KCalCore::Event::Ptr mEvent;
};

KCalCore::Event::Ptr &NemoCalendarEvent::event()
{
return mEvent;
}

const KCalCore::Event::Ptr &NemoCalendarEvent::event() const
{
return mEvent;
}

#endif // CALENDAREVENT_H

0 comments on commit be7777d

Please sign in to comment.