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