ca1d17d38c67f01c1fe14ce1dde95a01157fcfca
[toast/confclerk.git] / src / gui / mainwindow.cpp
1 #include "mainwindow.h"
2 #include <appsettings.h>
3
4 #include <QTreeView>
5 #include <QDirModel>
6
7 #include <sqlengine.h>
8
9 #include <track.h>
10 #include <eventmodel.h>
11 #include <delegate.h>
12
13 #include <conference.h>
14
15 #include <QDialog>
16 #include <QMessageBox>
17 #include <QTimer>
18 #include "ui_about.h"
19 #include "eventdialog.h"
20 #include "daynavigatorwidget.h"
21 #include "importschedulewidget.h"
22 #include "mapwindow.h"
23
24 MainWindow::MainWindow(int aEventId, QWidget *aParent)
25     : QMainWindow(aParent)
26 {
27     setupUi(this);
28
29     // create "SQLITE" DB instance/connection
30     // opens DB connection (needed for EventModel)
31     mSqlEngine = new SqlEngine(this);
32     mSqlEngine->initialize();
33     importScheduleWidget->setSqlEngine(mSqlEngine);
34
35     // Sanity check for existence of any Conference in the DB
36     // it AppSettings::confId() is 0, but there are any Conference(s) in the DB
37     // set the confId in the AppSettings for the ID of the first conference in the DB
38     QList<Conference> confs = Conference::getAll();
39     if(!confs.count()) // no conference(s) in the DB
40     {
41         AppSettings::setConfId(0); // no conference in the DB
42     }
43     else
44     {
45         if(AppSettings::confId() == 0)
46             AppSettings::setConfId(confs[0].id());
47     }
48
49     connect(importScheduleWidget, SIGNAL(scheduleImported(int)), SLOT(scheduleImported(int)));
50
51     connect(dayNavigator, SIGNAL(dateChanged(const QDate &)), SLOT(updateDayView(const QDate &)));
52     connect(trackDayNavigator, SIGNAL(dateChanged(const QDate &)), SLOT(updateTracksView(const QDate &)));
53     connect(favouriteDayNavigator, SIGNAL(dateChanged(const QDate &)), SLOT(updateFavouritesView(const QDate &)));
54     connect(searchDayNavigator, SIGNAL(dateChanged(const QDate &)), SLOT(updateSearchView(const QDate &)));
55     connect(roomDayNavigator, SIGNAL(dateChanged(const QDate &)), SLOT(updateRoomView(const QDate &)));
56
57     // DAY EVENTS View
58     dayTreeView->setHeaderHidden(true);
59     dayTreeView->setRootIsDecorated(false);
60     dayTreeView->setIndentation(0);
61     dayTreeView->setAnimated(true);
62     dayTreeView->setModel(new EventModel());
63     dayTreeView->setItemDelegate(new Delegate(dayTreeView));
64
65     // FAVOURITIES View
66     favTreeView->setHeaderHidden(true);
67     favTreeView->setRootIsDecorated(false);
68     favTreeView->setIndentation(0);
69     favTreeView->setAnimated(true);
70     favTreeView->setModel(new EventModel());
71     favTreeView->setItemDelegate(new Delegate(favTreeView));
72
73     // TRACKS View
74     trackTreeView->setHeaderHidden(true);
75     trackTreeView->setRootIsDecorated(false);
76     trackTreeView->setIndentation(0);
77     trackTreeView->setAnimated(true);
78     trackTreeView->setModel(new EventModel());
79     trackTreeView->setItemDelegate(new Delegate(trackTreeView));
80
81     // SEARCH EVENTS View
82         searchTreeView->setHeaderHidden(true);
83         searchTreeView->setRootIsDecorated(false);
84         searchTreeView->setIndentation(0);
85         searchTreeView->setAnimated(true);
86         searchTreeView->setModel(new EventModel());
87         searchTreeView->setItemDelegate(new Delegate(searchTreeView));
88
89     // NOW View
90         nowTreeView->setHeaderHidden(true);
91         nowTreeView->setRootIsDecorated(false);
92         nowTreeView->setIndentation(0);
93         nowTreeView->setAnimated(true);
94         nowTreeView->setModel(new EventModel());
95         nowTreeView->setItemDelegate(new Delegate(nowTreeView));
96
97         // NOW View refresh timer
98     QTimer *timer = new QTimer( this );
99     connect( timer, SIGNAL(timeout()), SLOT(timerUpdateNowView()) );
100     timer->start( 30000); // 30 seconds timer
101
102     // ROOMS View
103     roomTreeView->setHeaderHidden(true);
104     roomTreeView->setRootIsDecorated(false);
105     roomTreeView->setIndentation(0);
106     roomTreeView->setAnimated(true);
107     roomTreeView->setModel(new EventModel());
108     roomTreeView->setItemDelegate(new Delegate(roomTreeView));
109
110     // event details have changed
111     connect(dayTreeView, SIGNAL(eventHasChanged(int)), SLOT(eventHasChanged(int)));
112     connect(favTreeView, SIGNAL(eventHasChanged(int)), SLOT(eventHasChanged(int)));
113     connect(trackTreeView, SIGNAL(eventHasChanged(int)), SLOT(eventHasChanged(int)));
114     connect(searchTreeView, SIGNAL(eventHasChanged(int)), SLOT(eventHasChanged(int)));
115     connect(nowTreeView, SIGNAL(eventHasChanged(int)), SLOT(eventHasChanged(int)));
116     connect(roomTreeView, SIGNAL(eventHasChanged(int)), SLOT(eventHasChanged(int)));
117
118     // event clicked
119     connect(dayTreeView, SIGNAL(clicked(const QModelIndex &)), SLOT(itemClicked(const QModelIndex &)));
120     connect(favTreeView, SIGNAL(clicked(const QModelIndex &)), SLOT(itemClicked(const QModelIndex &)));
121     connect(trackTreeView, SIGNAL(clicked(const QModelIndex &)), SLOT(itemClicked(const QModelIndex &)));
122     connect(searchTreeView, SIGNAL(clicked(const QModelIndex &)), SLOT(itemClicked(const QModelIndex &)));
123     connect(nowTreeView, SIGNAL(clicked(const QModelIndex &)), SLOT(itemClicked(const QModelIndex &)));
124     connect(roomTreeView, SIGNAL(clicked(const QModelIndex &)), SLOT(itemClicked(const QModelIndex &)));
125     // request for map to be displayed
126     connect(dayTreeView, SIGNAL(requestForMap(const QModelIndex &)), SLOT(displayMap(const QModelIndex &)));
127     connect(favTreeView, SIGNAL(requestForMap(const QModelIndex &)), SLOT(displayMap(const QModelIndex &)));
128     connect(trackTreeView, SIGNAL(requestForMap(const QModelIndex &)), SLOT(displayMap(const QModelIndex &)));
129     connect(searchTreeView, SIGNAL(requestForMap(const QModelIndex &)), SLOT(displayMap(const QModelIndex &)));
130     connect(nowTreeView, SIGNAL(requestForMap(const QModelIndex &)), SLOT(displayMap(const QModelIndex &)));
131     connect(roomTreeView, SIGNAL(requestForMap(const QModelIndex &)), SLOT(displayMap(const QModelIndex &)));
132     // request for warning to be displayed
133     connect(dayTreeView, SIGNAL(requestForWarning(const QModelIndex &)), SLOT(displayWarning(const QModelIndex &)));
134     connect(favTreeView, SIGNAL(requestForWarning(const QModelIndex &)), SLOT(displayWarning(const QModelIndex &)));
135     connect(trackTreeView, SIGNAL(requestForWarning(const QModelIndex &)), SLOT(displayWarning(const QModelIndex &)));
136     connect(searchTreeView, SIGNAL(requestForWarning(const QModelIndex &)), SLOT(displayWarning(const QModelIndex &)));
137     connect(nowTreeView, SIGNAL(requestForWarning(const QModelIndex &)), SLOT(displayWarning(const QModelIndex &)));
138     connect(roomTreeView, SIGNAL(requestForWarning(const QModelIndex &)), SLOT(displayWarning(const QModelIndex &)));
139     // event search button clicked
140     connect(searchButton, SIGNAL(clicked()), SLOT(searchClicked()));
141     connect(searchAgainButton, SIGNAL(clicked()), SLOT(searchAgainClicked()));
142     // event conference map button clicked
143     connect(showMapButton, SIGNAL(clicked()), SLOT(conferenceMapClicked()));
144     //
145     connect(tabWidget, SIGNAL(currentChanged(int)), SLOT(tabHasChanged(int)));
146     connect(tabWidget, SIGNAL(infoIconClicked()), SLOT(aboutApp()));
147
148     if(!Conference::getAll().count()) // no conference(s) in the DB
149     {
150         dayNavigator->hide(); // hide DayNavigatorWidget
151         trackDayNavigator->hide();
152         roomDayNavigator->hide();
153     }
154     else
155     {
156         QDate aStartDate = Conference::getById(AppSettings::confId()).start();
157         QDate aEndDate = Conference::getById(AppSettings::confId()).end();
158         dayNavigator->setDates(aStartDate, aEndDate);
159         trackDayNavigator->setDates(aStartDate, aEndDate);
160         favouriteDayNavigator->setDates(aStartDate, aEndDate);
161         searchDayNavigator->setDates(aStartDate, aEndDate);
162         roomDayNavigator->setDates(aStartDate, aEndDate);
163         //
164         conferenceTitle->setText(Conference::getById(AppSettings::confId()).title());
165         conferenceSubtitle->setText(Conference::getById(AppSettings::confId()).subtitle());
166         conferenceWhere->setText(Conference::getById(AppSettings::confId()).city() + ", " + Conference::getById(AppSettings::confId()).venue());
167         conferenceWhen->setText(
168                 Conference::getById(AppSettings::confId()).start().toString("dd-MM-yyyy")
169                 + ", " +
170                 Conference::getById(AppSettings::confId()).end().toString("dd-MM-yyyy"));
171     }
172
173     searchTreeView->hide();
174     searchVerticalWidget->hide();
175     searchHead->show();
176
177     // open dialog for given Event ID
178     // this is used in case Alarm Dialog request application to start
179     if(aEventId)
180     {
181         try
182         {
183             EventDialog dialog(aEventId,this);
184             dialog.exec();
185         }
186         catch(OrmNoObjectException&) {} // just start application
187         catch(...) {} // just start application
188     }
189 }
190
191 MainWindow::~MainWindow()
192 {
193     if(mSqlEngine)
194     {
195         delete mSqlEngine;
196         mSqlEngine = NULL;
197     }
198 }
199
200 void MainWindow::scheduleImported(int aConfId)
201 {
202     Q_UNUSED(aConfId);
203
204     QList<Conference> confs = Conference::getAll();
205     if(!confs.count()) // no conference(s) in the DB
206     {
207         AppSettings::setConfId(0); // no conference in the DB
208     }
209     else
210     {
211         if(AppSettings::confId() == 0)
212             AppSettings::setConfId(confs[0].id());
213
214         // 'dayNavigator' emits signal 'dateChanged' after setting valid START:END dates
215         QDate aStartDate = Conference::getById(AppSettings::confId()).start();
216         QDate aEndDate = Conference::getById(AppSettings::confId()).end();
217         dayNavigator->setDates(aStartDate, aEndDate);
218         trackDayNavigator->setDates(aStartDate, aEndDate);
219         roomDayNavigator->setDates(aStartDate, aEndDate);
220     }
221 }
222
223 void MainWindow::aboutApp()
224 {
225     QDialog dialog(this);
226     Ui::AboutDialog ui;
227     ui.setupUi(&dialog);
228     dialog.exec();
229 }
230
231 void MainWindow::updateDayView(const QDate &aDate)
232 {
233     static_cast<EventModel*>(dayTreeView->model())->loadEvents(aDate,AppSettings::confId());
234     dayTreeView->reset();
235     dayNavigator->show();
236 }
237
238 void MainWindow::updateTracksView(const QDate &aDate)
239 {
240     static_cast<EventModel*>(trackTreeView->model())->loadEventsByTrack(aDate, AppSettings::confId());
241     trackTreeView->reset();
242     trackDayNavigator->show();
243 }
244
245 void MainWindow::updateFavouritesView(const QDate &aDate)
246 {
247     static_cast<EventModel*>(favTreeView->model())->loadFavEvents(aDate,AppSettings::confId());
248     favTreeView->reset();
249     favouriteDayNavigator->show();
250 }
251
252 void MainWindow::updateSearchView(const QDate &aDate)
253 {
254     qDebug() << "MainWindow::updateSearchView(), aDate: " << aDate.toString() ;
255     searchTreeView->reset();
256     int eventsCount = static_cast<EventModel*>(searchTreeView->model())->loadSearchResultEvents(aDate,AppSettings::confId());
257     if( eventsCount ||
258             searchDayNavigator->getCurrentDate() != Conference::getById(AppSettings::confId()).start() ){
259         searchVerticalWidget->show();
260         //searchAgainButton->show();
261         searchTreeView->show();
262         searchHead->hide();
263     }
264     else{
265         searchTreeView->hide();
266         searchVerticalWidget->hide();
267         searchHead->show();
268     }
269 }
270
271 void MainWindow::updateNowView()
272 {
273     EventModel *model = static_cast<EventModel*>(nowTreeView->model());
274     model->loadNowEvents(AppSettings::confId());
275     nowTreeView->reset();
276     nowTreeView->setAllExpanded(true);
277 }
278
279 void MainWindow::updateRoomView(const QDate &aDate)
280 {
281     static_cast<EventModel*>(roomTreeView->model())->loadEventsByRoom(aDate, AppSettings::confId());
282     roomTreeView->reset();
283     roomDayNavigator->show();
284 }
285
286 void MainWindow::itemClicked(const QModelIndex &aIndex)
287 {
288     // have to handle only events, not time-groups
289     if(!aIndex.parent().isValid()) // time-group
290         return;
291
292     EventDialog dialog(static_cast<Event*>(aIndex.internalPointer())->id(),this);
293     dialog.exec();
294 }
295
296 void MainWindow::displayMap(const QModelIndex &aIndex)
297 {
298     Event *event = static_cast<Event*>(aIndex.internalPointer());
299
300     // room names are stored in lower-case format
301     // room names are stored without dots in the name, eg. "aw.1124.png" -> "aw1124.png"
302     QString mapPath = QString(":/maps/rooms/%1.png").arg(event->room().toLower().remove("."));
303     if(!QFile::exists(mapPath))
304         mapPath = QString(":/maps/rooms/not-available.png");
305
306     QString roomName;
307     if(mapPath.contains("not-available", Qt::CaseInsensitive))
308         roomName = QString("Map is not available: %1").arg(event->room());
309     else
310         roomName = event->room();
311
312     QPixmap map(mapPath);
313     MapWindow window(map,roomName,this);
314     window.exec();
315 }
316
317 void MainWindow::searchClicked()
318 {
319     QHash<QString,QString> columns;
320
321     if( searchTitle->isChecked() )
322         columns.insertMulti("EVENT", "title");
323     if( searchAbstract->isChecked() )
324         columns.insertMulti("EVENT", "abstract");
325     if( searchTag->isChecked() )
326         columns.insertMulti("EVENT", "tag");
327     if( searchSpeaker->isChecked() )
328         columns["PERSON"] = "name";
329     if( searchRoom->isChecked() )
330         columns["ROOM"] = "name";
331
332     QString keyword = searchEdit->text().replace( QString("%"), QString("\\%") );
333     qDebug() << "\nKeyword to search: " << keyword;
334     mSqlEngine->searchEvent( AppSettings::confId(), columns, keyword );
335
336     QDate aStartDate = Conference::getById(AppSettings::confId()).start();
337     QDate aEndDate = Conference::getById(AppSettings::confId()).end();
338     searchDayNavigator->setDates(aStartDate, aEndDate);
339     updateSearchView( Conference::getById(AppSettings::confId()).start() );
340 }
341
342 void MainWindow::searchAgainClicked()
343 {
344     searchHead->show();
345     //searchAgainButton->hide();
346     searchVerticalWidget->hide();
347     searchTreeView->hide();
348
349 }
350
351 void MainWindow::conferenceMapClicked()
352 {
353
354     QString mapPath = QString(":/maps/campus.png");
355     if(!QFile::exists(mapPath))
356         mapPath = QString(":/maps/rooms/not-available.png");
357
358     QString roomName;
359
360     QPixmap map(mapPath);
361     MapWindow window(map,roomName,this);
362     window.exec();
363 }
364
365 void MainWindow::displayWarning(const QModelIndex &aIndex)
366 {
367     Q_UNUSED(aIndex);
368
369     QMessageBox::warning(
370     this,
371     tr("Time Conflict Warning"),
372     tr("This event happens at the same time than another one of your favourites.") );
373 }
374
375 void MainWindow::eventHasChanged(int aEventId)
376 {
377     static_cast<EventModel*>(dayTreeView->model())->updateModel(aEventId);
378     static_cast<EventModel*>(favTreeView->model())->updateModel(aEventId);
379     static_cast<EventModel*>(trackTreeView->model())->updateModel(aEventId);
380     static_cast<EventModel*>(searchTreeView->model())->updateModel(aEventId);
381     static_cast<EventModel*>(nowTreeView->model())->updateModel(aEventId);
382     static_cast<EventModel*>(roomTreeView->model())->updateModel(aEventId);
383 }
384
385 void MainWindow::tabHasChanged(int aIndex)
386 {
387     Q_UNUSED(aIndex);
388
389     // TODO: only if it changed to favourities tab
390     updateFavouritesView(favouriteDayNavigator->getCurrentDate());
391     // TODO: only if it changed to now tab
392     updateNowView();
393 }
394
395 void MainWindow::timerUpdateNowView()
396 {
397         QWidget * pCurrentWidget = tabWidget->widget(tabWidget->currentIndex());
398
399         if( pCurrentWidget != NULL )
400         {
401                 if( pCurrentWidget == tab )
402                     updateNowView();
403         }
404 }