2cee85cd38410b210ee231660e262fa5531ebbe7
[toast/confclerk.git] / src / gui / mainwindow.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 "mainwindow.h"
20
21 #include <QTreeView>
22 #include <QFile>
23 #include <QNetworkProxy>
24 #include <QNetworkAccessManager>
25 #include <QNetworkReply>
26
27 #include <sqlengine.h>
28
29 #include <track.h>
30 #include <eventmodel.h>
31 #include <delegate.h>
32
33 #include <conference.h>
34
35 #include <QDialog>
36 #include <QMessageBox>
37
38 #include "ui_about.h"
39 #include <eventdialog.h>
40 #include "daynavigatorwidget.h"
41 #include "settingsdialog.h"
42 #include "conferenceeditor.h"
43 #include "schedulexmlparser.h"
44 #include "errormessage.h"
45
46 #include <tabcontainer.h>
47 #include <appsettings.h>
48
49 const QString PROXY_USERNAME;
50 const QString PROXY_PASSWD;
51
52 MainWindow::MainWindow(int aEventId, QWidget *aParent)
53     : QMainWindow(aParent)
54     , conferenceModel(new ConferenceModel(this))
55     , mXmlParser(new ScheduleXmlParser(this))
56     , mNetworkAccessManager(new QNetworkAccessManager(this))
57 {
58     setupUi(this);
59
60     saved_title = windowTitle();
61
62 #ifdef N810
63     tabWidget->setTabText(1,"Favs");
64     //tabWidget->setTabText(2,"Day");
65 #endif
66
67     // first time run aplication: -> let's have it direct connection in this case
68     if(!AppSettings::contains("proxyIsDirectConnection"))
69         AppSettings::setDirectConnection(true);
70
71     if(AppSettings::isDirectConnection())
72     {
73         qDebug() << "Setting-up proxy: " << AppSettings::proxyAddress() << ":" << AppSettings::proxyPort();
74     }
75     QNetworkProxy proxy(
76             AppSettings::isDirectConnection() ? QNetworkProxy::NoProxy : QNetworkProxy::HttpProxy,
77             AppSettings::proxyAddress(),
78             AppSettings::proxyPort(),
79             PROXY_USERNAME,
80             PROXY_PASSWD);
81     QNetworkProxy::setApplicationProxy(proxy);
82
83     // event details have changed
84     connect(dayTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
85     connect(favsTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
86     connect(tracksTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
87     connect(roomsTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
88     connect(nowTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
89     connect(searchTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
90
91     connect(aboutAction, SIGNAL(triggered()), SLOT(aboutApp()));
92     connect(settingsAction, SIGNAL(triggered()), SLOT(setup()));
93     connect(conferencesAction, SIGNAL(triggered()), SLOT(showConferences()));
94
95     useConference(Conference::activeConference());
96     // optimization, see useConference() code
97     try {
98         initTabs();
99     } catch (OrmException) {
100         clearTabs();
101     }
102
103     // TODO: open conferences at startup?
104     #if 0
105     if(!confCount)
106         tabWidget->setCurrentIndex(6); // 6 - conference tab
107     }
108     #endif
109
110     // open dialog for given Event ID
111     // this is used in case Alarm Dialog request application to start
112     if(aEventId)
113     {
114         try
115         {
116             EventDialog dialog(aEventId,this);
117             dialog.exec();
118         }
119         catch(OrmNoObjectException&) {} // just start application
120         catch(...) {} // just start application
121     }
122
123     connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply*)), SLOT(networkQueryFinished(QNetworkReply*)));
124
125     connect(mXmlParser, SIGNAL(parsingScheduleBegin()), conferenceModel, SLOT(newConferenceBegin()));
126     connect(mXmlParser, SIGNAL(parsingScheduleEnd(const QString&)), conferenceModel, SLOT(newConferenceEnd(const QString&)));
127 }
128
129 void MainWindow::aboutApp()
130 {
131     QDialog dialog(this);
132     Ui::AboutDialog ui;
133     ui.setupUi(&dialog);
134 #ifdef N810
135     dialog.setFixedWidth(width());
136 #endif
137     dialog.exec();
138 }
139
140 void MainWindow::eventHasChanged(int aEventId, bool aReloadModel)
141 {
142     dayTabContainer->updateTreeViewModel(aEventId);
143     favsTabContainer->updateTreeViewModel(aEventId,aReloadModel);
144     tracksTabContainer->updateTreeViewModel(aEventId);
145     nowTabContainer->updateTreeViewModel(aEventId);
146     roomsTabContainer->updateTreeViewModel(aEventId);
147     searchTabContainer->updateTreeViewModel(aEventId);
148 }
149
150 void MainWindow::useConference(int id)
151 {
152     try {
153         Conference::getById(Conference::activeConference()).update("active",0);
154         Conference new_active = Conference::getById(id);
155         new_active.update("active",1);
156
157         // looks like it does not work at n900
158         setWindowTitle(new_active.title());
159
160         // optimization.
161         // dont run initTabs() here
162         // it takes much CPU, making travelling between conferences in ConferenceEditor longer
163         // and is not seen in maemo WM anyway
164         // instead run it explicitly
165         // 1. at startup
166         // 2. when ConferenceEditor finished
167         // dont forget to protect the calls by try-catch!
168
169         // just in case, clear conference selection instead
170         clearTabs();
171
172         // end of optimization
173         // initTabs();
174     } catch (OrmException& e) {
175         // cannon set an active conference
176         unsetConference();
177         return;
178     }
179
180 }
181
182 void MainWindow::initTabs()
183 {
184     int confId = Conference::activeConference();
185     Conference active = Conference::getById(confId);
186     QDate startDate = active.start();
187     QDate endDate = active.end();
188
189     // 'dayNavigator' emits signal 'dateChanged' after setting valid START:END dates
190     dayTabContainer->setDates(startDate, endDate);
191     tracksTabContainer->setDates(startDate, endDate);
192     roomsTabContainer->setDates(startDate, endDate);
193     favsTabContainer->setDates(startDate, endDate);
194     searchTabContainer->setDates(startDate, endDate);
195     searchTabContainer->searchAgainClicked();
196     nowTabContainer->updateTreeView(QDate::currentDate());
197 }
198
199 void MainWindow::clearTabs()
200 {
201     dayTabContainer->clearModel();
202     tracksTabContainer->clearModel();
203     roomsTabContainer->clearModel();
204     favsTabContainer->clearModel();
205     searchTabContainer->clearModel();
206     searchTabContainer->searchAgainClicked();
207     nowTabContainer->clearModel();
208 }
209
210 void MainWindow::unsetConference()
211 {
212     clearTabs();
213     setWindowTitle(saved_title);
214 }
215
216 void MainWindow::setup()
217 {
218     SettingsDialog dialog;
219     dialog.exec();
220
221     qDebug() << "Setting-up proxy: " << AppSettings::proxyAddress() << ":" << AppSettings::proxyPort();
222     QNetworkProxy proxy(
223             AppSettings::isDirectConnection() ? QNetworkProxy::NoProxy : QNetworkProxy::HttpProxy,
224             AppSettings::proxyAddress(),
225             AppSettings::proxyPort(),
226             PROXY_USERNAME,
227             PROXY_PASSWD);
228     QNetworkProxy::setApplicationProxy(proxy);
229 }
230
231 /** Create and run ConferenceEditor dialog, making required connections for it.
232
233 This method manages, which classes actually perform changes in conference list.
234
235 There are several classes that modify the conferences:
236 this:
237  deletion and URL update.
238 this, mXmlParser and mNetworkAccessManager:
239  addition and refresh.
240 */
241 void MainWindow::showConferences()
242 {
243     ConferenceEditor dialog(conferenceModel, this);
244
245     connect(&dialog, SIGNAL(haveConferenceUrl(const QString&)), SLOT(importFromNetwork(const QString&)));
246     connect(&dialog, SIGNAL(haveConferenceFile(const QString&)), SLOT(importFromFile(const QString&)));
247     connect(&dialog, SIGNAL(removeConferenceRequested(int)), SLOT(removeConference(int)));
248     connect(&dialog, SIGNAL(changeUrlRequested(int, const QString&)),
249                     SLOT(changeConferenceUrl(int, const QString&)));
250
251     connect(&dialog, SIGNAL(haveConferenceSelected(int)), SLOT(useConference(int)));
252     connect(&dialog, SIGNAL(noneConferenceSelected()), SLOT(unsetConference()));
253
254     connect(mXmlParser, SIGNAL(parsingScheduleBegin()), &dialog, SLOT(importStarted()));
255     connect(mXmlParser, SIGNAL(progressStatus(int)), &dialog, SLOT(showParsingProgress(int)));
256     connect(mXmlParser, SIGNAL(parsingScheduleEnd(const QString&)), &dialog, SLOT(importFinished(const QString&)));
257
258     connect(this, SIGNAL(conferenceRemoved()), &dialog, SLOT(conferenceRemoved()));
259
260     dialog.exec();
261
262     // optimization, see useConference() code
263     try {
264         initTabs();
265     } catch (OrmException) {
266         clearTabs();
267     }
268 }
269
270 void MainWindow::networkQueryFinished(QNetworkReply *aReply)
271 {
272     if ( aReply->error() != QNetworkReply::NoError )
273     {
274         error_message(QString("Error occured during download: ") + aReply->errorString());
275     }
276     else
277     {
278         qDebug() << __PRETTY_FUNCTION__ << ": have data";
279         importData(aReply->readAll(), aReply->url().toEncoded());
280     }
281 }
282
283 void MainWindow::importData(const QByteArray &aData, const QString& url)
284 {
285     mXmlParser->parseData(aData, url);
286 }
287
288 void MainWindow::importFromNetwork(const QString& url)
289 {
290     qDebug() << __PRETTY_FUNCTION__;
291     QNetworkRequest request;
292     request.setUrl(QUrl(url));
293
294     mNetworkAccessManager->setProxy(QNetworkProxy::applicationProxy());
295     mNetworkAccessManager->get(request);
296 }
297
298 void MainWindow::importFromFile(const QString& filename)
299 {
300     qDebug() << __PRETTY_FUNCTION__;
301     QFile file(filename);
302     if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {    
303         static const QString format("Cannot read \"%1\": error %2");
304         error_message(format.arg(filename, QString::number(file.error())));
305     }
306
307     importData(file.readAll(), "");
308 }
309
310 void MainWindow::removeConference(int id)
311 {
312     Conference::deleteConference(id);
313     conferenceModel->conferenceRemoved();
314
315     emit conferenceRemoved();
316 }
317
318 void MainWindow::changeConferenceUrl(int id, const QString& url)
319 {
320     Conference::getById(id).setUrl(url);
321 }
322