Included application version in the about dialog. This closes ticket #9.
[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     ui.labelVersion->setText(ui.labelVersion->text().arg(qApp->applicationVersion()));
137 #ifdef N810
138     dialog.setFixedWidth(width());
139 #endif
140     dialog.exec();
141 }
142
143 void MainWindow::eventHasChanged(int aEventId, bool aReloadModel)
144 {
145     dayTabContainer->updateTreeViewModel(aEventId);
146     favsTabContainer->updateTreeViewModel(aEventId,aReloadModel);
147     tracksTabContainer->updateTreeViewModel(aEventId);
148     nowTabContainer->updateTreeViewModel(aEventId);
149     roomsTabContainer->updateTreeViewModel(aEventId);
150     searchTabContainer->updateTreeViewModel(aEventId);
151 }
152
153 void MainWindow::useConference(int id)
154 {
155     try {
156         Conference::getById(Conference::activeConference()).update("active",0);
157         Conference new_active = Conference::getById(id);
158         new_active.update("active",1);
159
160         // looks like it does not work at n900
161         setWindowTitle(new_active.title());
162
163         // optimization.
164         // dont run initTabs() here
165         // it takes much CPU, making travelling between conferences in ConferenceEditor longer
166         // and is not seen in maemo WM anyway
167         // instead run it explicitly
168         // 1. at startup
169         // 2. when ConferenceEditor finished
170         // dont forget to protect the calls by try-catch!
171
172         // just in case, clear conference selection instead
173         clearTabs();
174
175         // end of optimization
176         // initTabs();
177     } catch (OrmException& e) {
178         // cannon set an active conference
179         unsetConference();
180         return;
181     }
182
183 }
184
185 void MainWindow::initTabs()
186 {
187     int confId = Conference::activeConference();
188     Conference active = Conference::getById(confId);
189     QDate startDate = active.start();
190     QDate endDate = active.end();
191
192     // 'dayNavigator' emits signal 'dateChanged' after setting valid START:END dates
193     dayTabContainer->setDates(startDate, endDate);
194     tracksTabContainer->setDates(startDate, endDate);
195     roomsTabContainer->setDates(startDate, endDate);
196     favsTabContainer->setDates(startDate, endDate);
197     searchTabContainer->setDates(startDate, endDate);
198     searchTabContainer->searchAgainClicked();
199     nowTabContainer->updateTreeView(QDate::currentDate());
200 }
201
202 void MainWindow::clearTabs()
203 {
204     dayTabContainer->clearModel();
205     tracksTabContainer->clearModel();
206     roomsTabContainer->clearModel();
207     favsTabContainer->clearModel();
208     searchTabContainer->clearModel();
209     searchTabContainer->searchAgainClicked();
210     nowTabContainer->clearModel();
211 }
212
213 void MainWindow::unsetConference()
214 {
215     clearTabs();
216     setWindowTitle(saved_title);
217 }
218
219 void MainWindow::setup()
220 {
221     SettingsDialog dialog;
222     dialog.exec();
223
224     qDebug() << "Setting-up proxy: " << AppSettings::proxyAddress() << ":" << AppSettings::proxyPort();
225     QNetworkProxy proxy(
226             AppSettings::isDirectConnection() ? QNetworkProxy::NoProxy : QNetworkProxy::HttpProxy,
227             AppSettings::proxyAddress(),
228             AppSettings::proxyPort(),
229             PROXY_USERNAME,
230             PROXY_PASSWD);
231     QNetworkProxy::setApplicationProxy(proxy);
232 }
233
234 /** Create and run ConferenceEditor dialog, making required connections for it.
235
236 This method manages, which classes actually perform changes in conference list.
237
238 There are several classes that modify the conferences:
239 this:
240  deletion and URL update.
241 this, mXmlParser and mNetworkAccessManager:
242  addition and refresh.
243 */
244 void MainWindow::showConferences()
245 {
246     ConferenceEditor dialog(conferenceModel, this);
247
248     connect(&dialog, SIGNAL(haveConferenceUrl(const QString&)), SLOT(importFromNetwork(const QString&)));
249     connect(&dialog, SIGNAL(haveConferenceFile(const QString&)), SLOT(importFromFile(const QString&)));
250     connect(&dialog, SIGNAL(removeConferenceRequested(int)), SLOT(removeConference(int)));
251     connect(&dialog, SIGNAL(changeUrlRequested(int, const QString&)),
252                     SLOT(changeConferenceUrl(int, const QString&)));
253
254     connect(&dialog, SIGNAL(haveConferenceSelected(int)), SLOT(useConference(int)));
255     connect(&dialog, SIGNAL(noneConferenceSelected()), SLOT(unsetConference()));
256
257     connect(mXmlParser, SIGNAL(parsingScheduleBegin()), &dialog, SLOT(importStarted()));
258     connect(mXmlParser, SIGNAL(progressStatus(int)), &dialog, SLOT(showParsingProgress(int)));
259     connect(mXmlParser, SIGNAL(parsingScheduleEnd(const QString&)), &dialog, SLOT(importFinished(const QString&)));
260
261     connect(this, SIGNAL(conferenceRemoved()), &dialog, SLOT(conferenceRemoved()));
262
263     dialog.exec();
264
265     // optimization, see useConference() code
266     try {
267         initTabs();
268     } catch (OrmException) {
269         clearTabs();
270     }
271 }
272
273 void MainWindow::networkQueryFinished(QNetworkReply *aReply)
274 {
275     if ( aReply->error() != QNetworkReply::NoError )
276     {
277         error_message(QString("Error occured during download: ") + aReply->errorString());
278     }
279     else
280     {
281         qDebug() << __PRETTY_FUNCTION__ << ": have data";
282         importData(aReply->readAll(), aReply->url().toEncoded());
283     }
284 }
285
286 void MainWindow::importData(const QByteArray &aData, const QString& url)
287 {
288     mXmlParser->parseData(aData, url);
289 }
290
291 void MainWindow::importFromNetwork(const QString& url)
292 {
293     qDebug() << __PRETTY_FUNCTION__;
294     QNetworkRequest request;
295     request.setUrl(QUrl(url));
296
297     mNetworkAccessManager->setProxy(QNetworkProxy::applicationProxy());
298     mNetworkAccessManager->get(request);
299 }
300
301 void MainWindow::importFromFile(const QString& filename)
302 {
303     qDebug() << __PRETTY_FUNCTION__;
304     QFile file(filename);
305     if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {    
306         static const QString format("Cannot read \"%1\": error %2");
307         error_message(format.arg(filename, QString::number(file.error())));
308     }
309
310     importData(file.readAll(), "");
311 }
312
313 void MainWindow::removeConference(int id)
314 {
315     Conference::deleteConference(id);
316     conferenceModel->conferenceRemoved();
317
318     emit conferenceRemoved();
319 }
320
321 void MainWindow::changeConferenceUrl(int id, const QString& url)
322 {
323     Conference::getById(id).setUrl(url);
324 }
325