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