Skip to content

Commit

Permalink
[nemo-qml-plugin-calendar] Refactor plugin to use DB thread
Browse files Browse the repository at this point in the history
No changes to the public API.
  • Loading branch information
Petri M. Gerdt committed Apr 17, 2014
1 parent cf4e189 commit 322eb59
Show file tree
Hide file tree
Showing 13 changed files with 220 additions and 612 deletions.
1 change: 1 addition & 0 deletions rpm/nemo-qml-plugin-calendar-qt5.spec
Expand Up @@ -18,6 +18,7 @@ Source0: %{name}-%{version}.tar.bz2
Source100: nemo-qml-plugin-calendar-qt5.yaml
BuildRequires: pkgconfig(Qt5Core)
BuildRequires: pkgconfig(Qt5Qml)
BuildRequires: pkgconfig(Qt5Concurrent)
BuildRequires: pkgconfig(libmkcal-qt5)
BuildRequires: pkgconfig(libkcalcoren-qt5)
BuildRequires: pkgconfig(libical)
Expand Down
88 changes: 33 additions & 55 deletions src/calendaragendamodel.cpp
Expand Up @@ -30,28 +30,23 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/

// Qt
#include <QDebug>

// mkcal
#include <event.h>

#include "calendareventcache.h"
#include "calendaragendamodel.h"

#include "calendarevent.h"
#include "calendareventoccurrence.h"
#include "calendardb.h"
#include "calendarmanager.h"

NemoCalendarAgendaModel::NemoCalendarAgendaModel(QObject *parent)
: QAbstractListModel(parent), mIsComplete(true)
{
connect(NemoCalendarEventCache::instance(), SIGNAL(modelReset()), this, SLOT(refresh()));
connect(NemoCalendarManager::instance(), SIGNAL(storageModified()), this, SLOT(refresh()));
connect(NemoCalendarManager::instance(), SIGNAL(dataUpdated()), this, SLOT(refresh()));
}

NemoCalendarAgendaModel::~NemoCalendarAgendaModel()
{
NemoCalendarEventCache::instance()->cancelAgendaRefresh(this);
qDeleteAll(mEvents);
NemoCalendarManager::instance()->cancelAgendaRefresh(this);
}

QHash<int, QByteArray> NemoCalendarAgendaModel::roleNames() const
Expand Down Expand Up @@ -100,70 +95,56 @@ void NemoCalendarAgendaModel::refresh()
if (!mIsComplete)
return;

NemoCalendarEventCache::instance()->scheduleAgendaRefresh(this);
NemoCalendarManager::instance()->scheduleAgendaRefresh(this);
}

static bool eventsEqual(const mKCal::ExtendedCalendar::ExpandedIncidence &e1,
const mKCal::ExtendedCalendar::ExpandedIncidence &e2)
static bool eventsEqual(const NemoCalendarEventOccurrence *e1,
const NemoCalendarEventOccurrence *e2)
{
return e1.first.dtStart == e2.first.dtStart &&
e1.first.dtEnd == e2.first.dtEnd &&
(e1.second == e2.second || (e1.second && e2.second && e1.second->uid() == e2.second->uid()));
return e1->startTime() == e2->startTime() &&
e1->endTime() == e2->endTime() &&
(e1->eventObject() && e2->eventObject() && e1->eventObject()->uniqueId() == e2->eventObject()->uniqueId());
}

static bool eventsLessThan(const mKCal::ExtendedCalendar::ExpandedIncidence &e1,
const mKCal::ExtendedCalendar::ExpandedIncidence &e2)
static bool eventsLessThan(const NemoCalendarEventOccurrence *e1,
const NemoCalendarEventOccurrence *e2)
{
if (e1.second.isNull() != e2.second.isNull()) {
return e1.second.data() < e2.second.data();
} else if (e1.first.dtStart == e2.first.dtStart) {
int cmp = QString::compare(e1.second->summary(), e2.second->summary(), Qt::CaseInsensitive);
if (cmp == 0) return QString::compare(e1.second->uid(), e2.second->uid()) < 0;
else return cmp < 0;
if (e1->startTime() == e2->startTime()) {
int cmp = QString::compare(e1->eventObject()->displayLabel(),
e2->eventObject()->displayLabel(),
Qt::CaseInsensitive);
if (cmp == 0)
return QString::compare(e1->eventObject()->uniqueId(), e2->eventObject()->uniqueId()) < 0;
else
return cmp < 0;
} else {
return e1.first.dtStart < e2.first.dtStart;
return e1->startTime() < e2->startTime();
}
}

void NemoCalendarAgendaModel::doRefresh(mKCal::ExtendedCalendar::ExpandedIncidenceList newEvents, bool reset)
void NemoCalendarAgendaModel::doRefresh(QList<NemoCalendarEventOccurrence *> newEvents)
{
// Filter out excluded notebooks
for (int ii = 0; ii < newEvents.count(); ++ii) {
if (!NemoCalendarEventCache::instance()->notebooks().contains(NemoCalendarDb::calendar()->notebook(newEvents.at(ii).second))) {
newEvents.remove(ii);
--ii;
}
}

qSort(newEvents.begin(), newEvents.end(), eventsLessThan);

int oldEventCount = mEvents.count();

if (reset) {
beginResetModel();
qDeleteAll(mEvents);
mEvents.clear();
}

QList<NemoCalendarEventOccurrence *> events = mEvents;
QList<NemoCalendarEventOccurrence *> skippedEvents;

int oldEventCount = mEvents.count();
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()
|| eventsLessThan(events.at(eventsCounter + removeCount)->expandedEvent(),
|| eventsLessThan(events.at(eventsCounter + removeCount),
newEvents.at(newEventsCounter)))) {
removeCount++;
}

if (removeCount) {
Q_ASSERT(false == reset);
beginRemoveRows(QModelIndex(), mEventsIndex, mEventsIndex + removeCount - 1);
mEvents.erase(mEvents.begin() + mEventsIndex, mEvents.begin() + mEventsIndex + removeCount);
endRemoveRows();
Expand All @@ -174,8 +155,8 @@ void NemoCalendarAgendaModel::doRefresh(mKCal::ExtendedCalendar::ExpandedInciden

// Skip matching events
while (eventsCounter < events.count() && newEventsCounter < newEvents.count() &&
eventsEqual(newEvents.at(newEventsCounter), events.at(eventsCounter)->expandedEvent())) {
Q_ASSERT(false == reset);
eventsEqual(newEvents.at(newEventsCounter), events.at(eventsCounter))) {
skippedEvents.append(newEvents.at(newEventsCounter));
eventsCounter++;
newEventsCounter++;
mEventsIndex++;
Expand All @@ -185,25 +166,22 @@ void NemoCalendarAgendaModel::doRefresh(mKCal::ExtendedCalendar::ExpandedInciden
int insertCount = 0;
while ((newEventsCounter + insertCount) < newEvents.count()
&& (eventsCounter >= events.count()
|| !(eventsLessThan(events.at(eventsCounter)->expandedEvent(),
|| !(eventsLessThan(events.at(eventsCounter),
newEvents.at(newEventsCounter + insertCount))))) {
insertCount++;
}

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

if (reset)
endResetModel();
qDeleteAll(skippedEvents);

if (oldEventCount != mEvents.count())
emit countChanged();
Expand Down
6 changes: 3 additions & 3 deletions src/calendaragendamodel.h
Expand Up @@ -34,7 +34,6 @@
#define CALENDARAGENDAMODEL_H

#include <QDate>
#include <extendedcalendar.h>
#include <QAbstractListModel>
#include <QQmlParserStatus>

Expand Down Expand Up @@ -67,7 +66,8 @@ class NemoCalendarAgendaModel : public QAbstractListModel, public QQmlParserStat

int count() const;

void doRefresh(mKCal::ExtendedCalendar::ExpandedIncidenceList, bool reset = false);
// NemoCalendarAgendaModel takes ownership of the NemoCalendarEventOccurrence objects
void doRefresh(QList<NemoCalendarEventOccurrence *>);

int rowCount(const QModelIndex &index) const;
QVariant data(const QModelIndex &index, int role) const;
Expand All @@ -90,7 +90,7 @@ private slots:
QDate mEndDate;
QList<NemoCalendarEventOccurrence *> mEvents;

bool mIsComplete:1;
bool mIsComplete;
};

#endif // CALENDARAGENDAMODEL_H
62 changes: 13 additions & 49 deletions src/calendarapi.cpp
Expand Up @@ -32,83 +32,47 @@

#include "calendarapi.h"

#include <QSettings>
#include <QQmlEngine>
#include "calendardb.h"
#include "calendarevent.h"
#include "calendareventcache.h"
#include "calendarmanager.h"

NemoCalendarApi::NemoCalendarApi(QObject *parent)
: QObject(parent)
{
connect(NemoCalendarManager::instance(),
SIGNAL(excludedNotebooksChanged(QStringList)),
this, SIGNAL(excludedNotebooksChanged()));
}

NemoCalendarEvent *NemoCalendarApi::createEvent()
{
return new NemoCalendarEvent;
return NemoCalendarManager::instance()->createEvent();
}

void NemoCalendarApi::remove(const QString &uid)
{
mKCal::ExtendedCalendar::Ptr calendar = NemoCalendarDb::calendar();
KCalCore::Event::Ptr event = calendar->event(uid);
if (!event)
return;
calendar->deleteEvent(event);
NemoCalendarManager::instance()->deleteEvent(uid);

// TODO: this sucks
NemoCalendarDb::storage()->save();
NemoCalendarManager::instance()->save();
}

void NemoCalendarApi::remove(const QString &uid, const QDateTime &time)
{
mKCal::ExtendedCalendar::Ptr calendar = NemoCalendarDb::calendar();
KCalCore::Event::Ptr event = calendar->event(uid);
if (!event)
return;
if (event->recurs())
event->recurrence()->addExDateTime(KDateTime(time, KDateTime::Spec(KDateTime::LocalZone)));
else
calendar->deleteEvent(event);
NemoCalendarManager::instance()->deleteEvent(uid, time);

// TODO: this sucks
NemoCalendarDb::storage()->save();
NemoCalendarManager::instance()->save();
}

QStringList NemoCalendarApi::excludedNotebooks() const
{
mKCal::Notebook::List notebooks = NemoCalendarDb::storage()->notebooks();

QStringList rv;

for (int ii = 0; ii < notebooks.count(); ++ii) {
if (!NemoCalendarEventCache::instance()->notebooks().contains(notebooks.at(ii)->uid()))
rv.append(notebooks.at(ii)->uid());
}

return rv;
return NemoCalendarManager::instance()->excludedNotebooks();
}

void NemoCalendarApi::setExcludedNotebooks(const QStringList &list)
{
QStringList current = excludedNotebooks();
if (list == current)
return;

QSettings settings("nemo", "nemo-qml-plugin-calendar");

for (int ii = 0; ii < current.count(); ++ii) {
QString uid = current.at(ii);
if (!list.contains(uid))
settings.remove("exclude/" + uid);
}

for (int ii = 0; ii < list.count(); ++ii) {
QString uid = list.at(ii);
if (!current.contains(uid))
settings.setValue("exclude/" + uid, true);
}

emit excludedNotebooksChanged();
NemoCalendarEventCache::instance()->load();
NemoCalendarManager::instance()->setExcludedNotebooks(list);
}

QObject *NemoCalendarApi::New(QQmlEngine *e, QJSEngine *)
Expand Down

0 comments on commit 322eb59

Please sign in to comment.