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