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