the (svn)ChangeLog should long be gone
[debian/fosdem-schedule.git] / src / mvc / eventmodel.cpp
1 /*
2  * Copyright (C) 2010 Ixonos Plc.
3  *
4  * This file is part of fosdem-schedule.
5  *
6  * fosdem-schedule is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation, either version 2 of the License, or (at your option)
9  * any later version.
10  *
11  * fosdem-schedule is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * fosdem-schedule.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 #include "eventmodel.h"
20 #include <conference.h>
21 #include <track.h>
22 #include <room.h>
23
24 const QString EventModel::COMMA_SEPARATOR = ", ";
25
26 EventModel::EventModel()
27 {
28     mEvents.clear();
29 }
30
31 void EventModel::createTimeGroups()
32 {
33     mGroups.clear();
34     mParents.clear();
35
36     if (mEvents.empty())
37     {
38         return;
39     }
40
41     const int timeSpan = 5400;
42
43     QTime startTime = mEvents.first().start().time();
44     mGroups << EventModel::Group(QString("%1 - %2").arg(startTime.toString("HH:mm"),
45         startTime.addSecs(timeSpan).toString("HH:mm")), 0);
46     QTime nextGroupTime = mEvents.first().start().time().addSecs(timeSpan);
47
48     for (int i=0; i<mEvents.count(); i++)
49     {
50         QTime eventTime = mEvents.at(i).start().time();
51
52         if (nextGroupTime <= eventTime)
53         {
54             mGroups.last().mChildCount = i - mGroups.last().mFirstEventIndex;
55             mGroups << EventModel::Group(QString("%1 - %2").arg(nextGroupTime.toString("HH:mm"),
56                 nextGroupTime.addSecs(timeSpan).toString("HH:mm")), i);
57             nextGroupTime = nextGroupTime.addSecs(timeSpan);
58         }
59
60         // add parent-child relation
61         mParents[mEvents.at(i).id()] = mGroups.count() - 1;
62     }
63
64     mGroups.last().mChildCount = mEvents.count() - mGroups.last().mFirstEventIndex;
65 }
66
67 void EventModel::createTrackGroups() {
68     mGroups.clear();
69     mParents.clear();
70     if (mEvents.empty())
71     {
72         return;
73     }
74     int trackId = mEvents.first().trackId();
75
76     mGroups << EventModel::Group(Track::retrieveTrackName(trackId), 0);
77     int nextTrackId = trackId;
78
79     for (int i=0; i<mEvents.count(); i++)
80     {
81         trackId = mEvents.at(i).trackId();
82         if (nextTrackId != trackId)
83         {
84             mGroups.last().mChildCount = i - mGroups.last().mFirstEventIndex;
85             mGroups << EventModel::Group(Track::retrieveTrackName(trackId), i);
86             nextTrackId = trackId;
87         }
88         // add parent-child relation
89         mParents[mEvents.at(i).id()] = mGroups.count() - 1;
90     }
91     mGroups.last().mChildCount = mEvents.count() - mGroups.last().mFirstEventIndex;
92 }
93
94 void EventModel::createRoomGroups()
95 {
96     mGroups.clear();
97     mParents.clear();
98     if (mEvents.empty())
99     {
100         return;
101     }
102     int roomId = mEvents.first().roomId();
103
104     mGroups << EventModel::Group(Room::retrieveRoomName(roomId), 0);
105     int nextRoomId = roomId;
106
107     QList<Event>::iterator event = mEvents.begin();
108     int i = 0;
109     while (event != mEvents.end())
110     {
111         roomId = event->roomId();
112         if (nextRoomId != roomId)
113         {
114             mGroups.last().mChildCount = i - mGroups.last().mFirstEventIndex;
115             mGroups << EventModel::Group(Room::retrieveRoomName(roomId), i);
116             nextRoomId = roomId;
117         }
118         mParents[event->id()] = mGroups.count() - 1;
119         event++;
120         i++;
121     }
122     mGroups.last().mChildCount = mEvents.count() - mGroups.last().mFirstEventIndex;
123 }
124
125 QVariant EventModel::data(const QModelIndex& index, int role) const
126 {
127     if (index.isValid() && role == Qt::DisplayRole)
128     {
129         if (index.internalId() == 0)
130         {
131             return mGroups.at(index.row()).mTitle;
132         }
133         else //event data
134         {
135             return static_cast<Event*>(index.internalPointer())->id();
136         }
137     }
138
139     return QVariant();
140 }
141
142 QModelIndex EventModel::index(int row, int column, const QModelIndex& parent) const
143 {
144     // TODO: add checks for out of range rows
145
146     if (!parent.isValid())
147     {
148         return createIndex(row, column, 0);
149     }
150     else if (parent.internalId() == 0)
151     {
152         const Group& group = mGroups.at(parent.row());
153         Event* event = const_cast<Event*>(&mEvents.at(row + group.mFirstEventIndex));
154         return createIndex(row, column, reinterpret_cast<void*>(event));
155     }
156     else
157     {
158         return QModelIndex();
159     }
160 }
161
162 QModelIndex EventModel::parent(const QModelIndex & index) const
163 {
164     if (index.isValid())
165     {
166         if (index.internalId() == 0)
167         {
168             return QModelIndex();
169         }
170
171         Event * event = static_cast<Event*>(index.internalPointer());
172
173         return createIndex(mParents[event->id()], 0, 0);
174     }
175
176     return QModelIndex();
177 }
178
179 int EventModel::columnCount(const QModelIndex & parent) const
180 {
181     Q_UNUSED(parent);
182     return 1;
183 }
184
185 int EventModel::rowCount (const QModelIndex & parent) const
186 {
187     if (!parent.isValid())
188     {
189         return mGroups.count();
190     }
191
192     if (parent.internalId() == 0)
193     {
194         return mGroups.at(parent.row()).mChildCount;
195     }
196
197     return 0;
198 }
199
200 void EventModel::clearModel()
201 {
202     for(int i = 0;i < mGroups.count();i++){
203         QModelIndex idx = index(i, 0);
204         Group group = mGroups[i];
205         beginRemoveRows(idx, 0, group.mChildCount - 1);
206         /*bool ok =*/ removeRows(0, group.mChildCount, idx);
207         endRemoveRows();
208         //qDebug() << "removing " << group.mChildCount << " events from group:" << i << idx.data() << ":" << ok;
209     }
210     mEvents.clear();
211 }
212
213 void EventModel::loadEvents(const QDate &aDate, int aConferenceId)
214 {
215     clearModel();
216     // check for existence of the conference in the DB
217     if(Conference::getAll().count())
218     {
219         qDebug() << "Loading Conference Data: [" << Conference::getById(aConferenceId).title() << "] " << aDate;
220         mEvents = Event::getByDate(QDate(aDate.year(), aDate.month(), aDate.day()), aConferenceId, "start");
221     }
222     createTimeGroups();
223 }
224
225 void EventModel::loadFavEvents(const QDate &aDate, int aConferenceId)
226 {
227     clearModel();
228     // check for existence of the conference in the DB
229     if(Conference::getAll().count())
230     {
231         qDebug() << "Loading FAV Conference Data: [" << Conference::getById(aConferenceId).title() << "] " << aDate;
232         mEvents = Event::getFavByDate(QDate(aDate.year(), aDate.month(), aDate.day()), aConferenceId);
233     }
234     createTimeGroups();
235 }
236
237 int EventModel::loadSearchResultEvents(const QDate &aDate, int aConferenceId)
238 {
239     clearModel();
240     // check for existence of the conference in the DB
241     if(Conference::getAll().count())
242     {
243         qDebug() << "Loading search result Data: [" << Conference::getById(aConferenceId).title() << "] " << aDate;
244         try{
245             mEvents = Event::getSearchResultByDate(QDate(aDate.year(), aDate.month(), aDate.day()), aConferenceId, "start");
246         }
247         catch( OrmException &e  ){
248             qDebug() << "Event::getSearchResultByDate failed: " << e.text();
249         }
250         catch(...){
251             qDebug() << "Event::getSearchResultByDate failed";
252         }
253
254     }
255
256     createTimeGroups();
257
258     return mEvents.count();
259 }
260
261 void EventModel::loadEventsByTrack(const QDate &aDate, int aConferenceId)
262 {
263     clearModel();
264     if (Conference::getAll().count())
265     {
266         qDebug() << "Loading Conference Data (by Track): [" << Conference::getById(aConferenceId).title() << "] " << aDate;
267         mEvents = Event::getByDate(QDate(aDate.year(), aDate.month(), aDate.day()), aConferenceId, "xid_track, start");
268     }
269     createTrackGroups();
270 }
271
272 void EventModel::loadEventsByRoom(const QDate &aDate, int aConferenceId)
273 {
274     clearModel();
275     if (Conference::getAll().count())
276     {
277         qDebug() << "Loading Conference Data (by Room): [" << Conference::getById(aConferenceId).title() << "] " << aDate;
278         mEvents = Event::getByDateAndRoom(QDate(aDate.year(), aDate.month(), aDate.day()), aConferenceId);
279     }
280     createRoomGroups();
281 }
282
283 void EventModel::loadNowEvents(int aConferenceId)
284 {
285     clearModel();
286     // check for existence of the conference in the DB
287     if(Conference::getAll().count())
288     {
289         qDebug() << "Loading Conference Data: [" << Conference::getById(aConferenceId).title() << "] scheduled NOW";
290         mEvents = Event::nowEvents(aConferenceId, "start");
291     }
292     createTimeGroups();
293 }
294
295 void EventModel::loadConflictEvents(int aEventId, int aConferenceId)
296 {
297     clearModel();
298     // check for existence of the conference in the DB
299     if(Conference::getAll().count())
300     {
301         qDebug() << "Loading Conference Data: [" << Conference::getById(aConferenceId).title() << "] in conflict with " << aEventId;
302         mEvents = Event::conflictEvents(aEventId, aConferenceId);
303     }
304     createTimeGroups();
305 }
306
307 void EventModel::updateModel(int aEventId)
308 {
309     for(int i=0; i<mEvents.count(); i++)
310     {
311         if(mEvents[i].id() == aEventId)
312             mEvents[i] = Event::getById(aEventId,Conference::activeConference());
313     }
314
315     // find the ModelIndex for given aEventId
316     for(int i=0; i<mGroups.count(); i++)
317     {
318         QModelIndex groupIndex = index(i,0,QModelIndex());
319         for(int j=0; j<mGroups[i].mChildCount; j++)
320         {
321             QModelIndex eventIndex = index(j,0,groupIndex);
322             if(static_cast<Event*>(eventIndex.internalPointer())->id() == aEventId)
323             {
324                 emit(dataChanged(groupIndex,groupIndex));
325                 emit(dataChanged(eventIndex,eventIndex));
326             }
327         }
328     }
329 }
330