source: src/mvc/eventmodel.cpp @ 6bf226b

qt5
Last change on this file since 6bf226b was 6bf226b, checked in by Philipp Spitzer <philipp@…>, 10 years ago

Philipp's comments to r1444.

  • Property mode set to 100644
File size: 10.2 KB
Line 
1/*
2 * Copyright (C) 2010 Ixonos Plc.
3 * Copyright (C) 2011-2012 Philipp Spitzer, gregor herrmann
4 *
5 * This file is part of ConfClerk.
6 *
7 * ConfClerk is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation, either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * ConfClerk is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * ConfClerk.  If not, see <http://www.gnu.org/licenses/>.
19 */
20#include "eventmodel.h"
21#include <conference.h>
22#include <track.h>
23#include <room.h>
24
25const QString EventModel::COMMA_SEPARATOR = ", ";
26
27EventModel::EventModel()
28{ }
29
30
31void EventModel::Group::setTitle(const QList<Event>& mEvents) {
32    QTime startTime = mEvents.at(mFirstEventIndex).start().time();
33    QTime endTime(0, 0);
34    for (int i = mFirstEventIndex; i != mFirstEventIndex + mChildCount; ++i) {
35        endTime = qMax(mEvents.at(i).start().time().addSecs(mEvents.at(i).duration()), endTime);
36    }
37    mTitle = QString("%1 - %2").arg(startTime.toString("HH:mm")).arg(endTime.toString("HH:mm"));
38}
39
40
41// We want to group the events into "time slots/time groups" that
42// should start at full hours and have the duration of either
43// one hour or (if less than 3 events are in one time slot)
44// multiple of one hour.
45void EventModel::createTimeGroups()
46{
47    mGroups.clear();
48    mParents.clear();
49    if (mEvents.empty()) return;
50
51    const int minTimeSpan = 3600; // one hour // minimum duration of a group
52    const int minChildCount = 3;  // minimum number of events in one group
53
54    // Create the first time group. The events have to be sorted by start time at this point!
55    //    Remarks for the following non-comment line:
56    //    * As it is right now it could be written as
57    //      QDateTime groupStartDateTime = mEvents.first().start();
58    //    * Before r1444 the minutes were set to zero so that the time groups started at
59    //      whole hours.
60
61    // QDateTime groupStartDateTime(mEvents.first().start().date(), QTime(mEvents.first().start().time().hour(), 0));
62    QDateTime groupStartDateTime = mEvents.first().start();
63    QDateTime groupEndDateTime = groupStartDateTime.addSecs(mEvents.first().duration());
64    mGroups << EventModel::Group("", 0);
65    int timeSpan = minTimeSpan;
66
67    for (int i = 0; i != mEvents.count(); ++i) {
68        QDateTime eventStartDateTime = mEvents.at(i).start();
69        QDateTime eventEndDateTime = eventStartDateTime.addSecs(mEvents.at(i).duration());
70
71        if (eventStartDateTime >= groupStartDateTime.addSecs(timeSpan)) {
72            // a new group could be necessary
73            if (mGroups.last().mChildCount < minChildCount) {
74                // too few events in the group => no new group
75                // except a gap in time would occur that is longer than minTimeSpan
76                QDateTime prevEventStartDateTime = mEvents.at(i).start();
77                if (i > 0 && qMax(prevEventStartDateTime.addSecs(mEvents.at(i-1).duration()), groupEndDateTime).secsTo(eventStartDateTime) < minTimeSpan) {
78                    timeSpan += minTimeSpan;
79                    --i;
80                    continue; // repeat with the same event
81                }
82            }
83
84            // a new group is necessary
85            mGroups.last().setTitle(mEvents);
86            groupStartDateTime = groupStartDateTime.addSecs(timeSpan);
87            groupEndDateTime = groupStartDateTime.addSecs(mEvents.at(i).duration());
88            mGroups << EventModel::Group("", i);
89            timeSpan = minTimeSpan;
90        }
91
92        // insert event into current group
93        mParents[mEvents.at(i).id()] = mGroups.count() - 1;
94        mGroups.last().mChildCount += 1;
95        groupEndDateTime = qMax(eventEndDateTime, groupEndDateTime);
96    }
97
98    // the last group needs a title as well
99    mGroups.last().setTitle(mEvents);
100
101    reset();
102}
103
104void EventModel::createTrackGroups() {
105    mGroups.clear();
106    mParents.clear();
107    if (mEvents.empty())
108    {
109        return;
110    }
111    int trackId = mEvents.first().trackId();
112
113    mGroups << EventModel::Group(Track::retrieveTrackName(trackId), 0);
114    int nextTrackId = trackId;
115
116    for (int i=0; i<mEvents.count(); i++)
117    {
118        trackId = mEvents.at(i).trackId();
119        if (nextTrackId != trackId)
120        {
121            mGroups.last().mChildCount = i - mGroups.last().mFirstEventIndex;
122            mGroups << EventModel::Group(Track::retrieveTrackName(trackId), i);
123            nextTrackId = trackId;
124        }
125        // add parent-child relation
126        mParents[mEvents.at(i).id()] = mGroups.count() - 1;
127    }
128    mGroups.last().mChildCount = mEvents.count() - mGroups.last().mFirstEventIndex;
129}
130
131void EventModel::createRoomGroups()
132{
133    mGroups.clear();
134    mParents.clear();
135    if (mEvents.empty())
136    {
137        return;
138    }
139    int roomId = mEvents.first().roomId();
140
141    mGroups << EventModel::Group(Room::retrieveRoomName(roomId), 0);
142    int nextRoomId = roomId;
143
144    QList<Event>::iterator event = mEvents.begin();
145    int i = 0;
146    while (event != mEvents.end())
147    {
148        roomId = event->roomId();
149        if (nextRoomId != roomId)
150        {
151            mGroups.last().mChildCount = i - mGroups.last().mFirstEventIndex;
152            mGroups << EventModel::Group(Room::retrieveRoomName(roomId), i);
153            nextRoomId = roomId;
154        }
155        mParents[event->id()] = mGroups.count() - 1;
156        event++;
157        i++;
158    }
159    mGroups.last().mChildCount = mEvents.count() - mGroups.last().mFirstEventIndex;
160}
161
162QVariant EventModel::data(const QModelIndex& index, int role) const
163{
164    if (index.isValid() && role == Qt::DisplayRole)
165    {
166        if (index.internalId() == 0)
167        {
168            return mGroups.at(index.row()).mTitle;
169        }
170        else //event data
171        {
172            return static_cast<Event*>(index.internalPointer())->id();
173        }
174    }
175
176    return QVariant();
177}
178
179QModelIndex EventModel::index(int row, int column, const QModelIndex& parent) const
180{
181    // TODO: add checks for out of range rows
182
183    if (!parent.isValid())
184    {
185        return createIndex(row, column, 0);
186    }
187    else if (parent.internalId() == 0)
188    {
189        const Group& group = mGroups.at(parent.row());
190        Event* event = const_cast<Event*>(&mEvents.at(row + group.mFirstEventIndex));
191        return createIndex(row, column, reinterpret_cast<void*>(event));
192    }
193    else
194    {
195        return QModelIndex();
196    }
197}
198
199QModelIndex EventModel::parent(const QModelIndex & index) const
200{
201    if (index.isValid())
202    {
203        if (index.internalId() == 0)
204        {
205            return QModelIndex();
206        }
207
208        Event * event = static_cast<Event*>(index.internalPointer());
209
210        return createIndex(mParents[event->id()], 0, 0);
211    }
212
213    return QModelIndex();
214}
215
216int EventModel::columnCount(const QModelIndex & parent) const
217{
218    Q_UNUSED(parent);
219    return 1;
220}
221
222int EventModel::rowCount (const QModelIndex & parent) const
223{
224    if (!parent.isValid())
225    {
226        return mGroups.count();
227    }
228
229    if (parent.internalId() == 0)
230    {
231        return mGroups.at(parent.row()).mChildCount;
232    }
233
234    return 0;
235}
236
237void EventModel::clearModel()
238{
239    mGroups.clear();
240    mEvents.clear();
241    mParents.clear();
242
243    reset();
244}
245
246void EventModel::loadEvents(const QDate &aDate, int aConferenceId)
247{
248    clearModel();
249    // check for existence of the conference in the DB
250    if(Conference::getAll().count())
251    {
252        mEvents = Event::getByDate(QDate(aDate.year(), aDate.month(), aDate.day()), aConferenceId, "start, duration");
253    }
254    createTimeGroups();
255}
256
257void EventModel::loadFavEvents(const QDate &aDate, int aConferenceId)
258{
259    clearModel();
260    // check for existence of the conference in the DB
261    if(Conference::getAll().count())
262    {
263        mEvents = Event::getFavByDate(QDate(aDate.year(), aDate.month(), aDate.day()), aConferenceId);
264    }
265    createTimeGroups();
266}
267
268int EventModel::loadSearchResultEvents(const QDate &aDate, int aConferenceId)
269{
270    clearModel();
271    // check for existence of the conference in the DB
272    if(Conference::getAll().count())
273    {
274        try{
275            mEvents = Event::getSearchResultByDate(QDate(aDate.year(), aDate.month(), aDate.day()), aConferenceId, "start, duration");
276        }
277        catch( OrmException &e  ){
278            qDebug() << "Event::getSearchResultByDate failed: " << e.text();
279        }
280        catch(...){
281            qDebug() << "Event::getSearchResultByDate failed";
282        }
283
284    }
285
286    createTimeGroups();
287
288    return mEvents.count();
289}
290
291void EventModel::loadEventsByTrack(const QDate &aDate, int aConferenceId)
292{
293    clearModel();
294    if (Conference::getAll().count())
295    {
296        mEvents = Event::getByDate(QDate(aDate.year(), aDate.month(), aDate.day()), aConferenceId, "xid_track, start, duration");
297    }
298    createTrackGroups();
299}
300
301void EventModel::loadEventsByRoom(const QDate &aDate, int aConferenceId)
302{
303    clearModel();
304    if (Conference::getAll().count())
305    {
306        mEvents = Event::getByDateAndRoom(QDate(aDate.year(), aDate.month(), aDate.day()), aConferenceId);
307    }
308    createRoomGroups();
309}
310
311
312void EventModel::loadConflictEvents(int aEventId, int aConferenceId) {
313    clearModel();
314    // check for existence of the conference in the DB
315    if(Conference::getAll().count())
316    {
317        mEvents = Event::conflictEvents(aEventId, aConferenceId);
318    }
319    createTimeGroups();
320}
321
322void EventModel::updateModel(int aEventId)
323{
324    for(int i=0; i<mEvents.count(); i++)
325    {
326        if(mEvents[i].id() == aEventId)
327            mEvents[i] = Event::getById(aEventId,Conference::activeConference());
328    }
329
330    // find the ModelIndex for given aEventId
331    for(int i=0; i<mGroups.count(); i++)
332    {
333        QModelIndex groupIndex = index(i,0,QModelIndex());
334        for(int j=0; j<mGroups[i].mChildCount; j++)
335        {
336            QModelIndex eventIndex = index(j,0,groupIndex);
337            if(static_cast<Event*>(eventIndex.internalPointer())->id() == aEventId)
338            {
339                emit(dataChanged(groupIndex,groupIndex));
340                emit(dataChanged(eventIndex,eventIndex));
341            }
342        }
343    }
344}
345
Note: See TracBrowser for help on using the repository browser.