2 * Copyright (C) 2010 Ixonos Plc.
4 * This file is part of fosdem-schedule.
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)
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
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/>.
19 #include "mainwindow.h"
23 #include <QNetworkProxy>
24 #include <QNetworkAccessManager>
25 #include <QNetworkReply>
27 #include <sqlengine.h>
30 #include <eventmodel.h>
33 #include <conference.h>
36 #include <QMessageBox>
39 #include <eventdialog.h>
40 #include "daynavigatorwidget.h"
41 #include "mapwindow.h"
42 #include "settingsdialog.h"
43 #include "conferenceeditor.h"
44 #include "schedulexmlparser.h"
45 #include "errormessage.h"
47 #include <tabcontainer.h>
48 #include <appsettings.h>
50 const QString PROXY_USERNAME;
51 const QString PROXY_PASSWD;
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))
61 saved_title = windowTitle();
64 tabWidget->setTabText(1,"Favs");
65 //tabWidget->setTabText(2,"Day");
68 // first time run aplication: -> let's have it direct connection in this case
69 if(!AppSettings::contains("proxyIsDirectConnection"))
70 AppSettings::setDirectConnection(true);
72 if(AppSettings::isDirectConnection())
74 qDebug() << "Setting-up proxy: " << AppSettings::proxyAddress() << ":" << AppSettings::proxyPort();
77 AppSettings::isDirectConnection() ? QNetworkProxy::NoProxy : QNetworkProxy::HttpProxy,
78 AppSettings::proxyAddress(),
79 AppSettings::proxyPort(),
82 QNetworkProxy::setApplicationProxy(proxy);
85 // list of conferences must be maintained by ConferenceEditor
86 // here must be one of the signals from the closing ConferenceEditor (or model):
87 // selectedConf(conference), noConf()
88 connect(importScheduleWidget, SIGNAL(scheduleImported(int)), SLOT(scheduleImported(int)));
89 connect(importScheduleWidget, SIGNAL(scheduleDeleted(const QString&)), SLOT(scheduleDeleted(const QString&)));
92 // event details have changed
93 connect(dayTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
94 connect(favsTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
95 connect(tracksTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
96 connect(roomsTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
97 connect(nowTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
98 connect(searchTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
100 // event conference map button clicked
102 // TODO: think about it when return to maps
103 connect(showMapButton, SIGNAL(clicked()), SLOT(conferenceMapClicked()));
106 connect(aboutAction, SIGNAL(triggered()), SLOT(aboutApp()));
107 connect(settingsAction, SIGNAL(triggered()), SLOT(setup()));
108 connect(conferencesAction, SIGNAL(triggered()), SLOT(showConferences()));
110 useConference(Conference::activeConference());
111 // optimization, see useConference() code
114 } catch (OrmException) {
120 // initialisation of model and pick active conference from there and call conferenceChanged()
121 // selectConference->setDuplicatesEnabled(false);
122 int confCount = Conference::getAll().count();
126 // fillAndShowConferenceHeader();
127 setWindowTitle(Conference::getById(confId).title());
129 QList<Conference> confs = Conference::getAll();
130 QListIterator<Conference> i(confs);
133 Conference conf = i.next();
135 // selectConference->addItem(conf.title(),conf.id());
138 // int idx = selectConference->findText(Conference::getById(Conference::activeConference()).title());
139 // selectConference->setCurrentIndex(idx);
140 // connect(selectConference, SIGNAL(currentIndexChanged(int)), SLOT(conferenceChanged(int)));
141 // conferenceChanged(idx);
146 // conferenceHeader->hide();
147 // selectConferenceWidget->hide();
148 // // go to the 'conferenceTab', so the user can import the schedule
149 // tabWidget->setCurrentIndex(6); // 6 - conference tab
153 // open dialog for given Event ID
154 // this is used in case Alarm Dialog request application to start
159 EventDialog dialog(aEventId,this);
162 catch(OrmNoObjectException&) {} // just start application
163 catch(...) {} // just start application
166 connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply*)), SLOT(networkQueryFinished(QNetworkReply*)));
168 connect(mXmlParser, SIGNAL(parsingScheduleBegin()), conferenceModel, SLOT(newConferenceBegin()));
169 connect(mXmlParser, SIGNAL(parsingScheduleEnd(const QString&)), conferenceModel, SLOT(newConferenceEnd(const QString&)));
172 void MainWindow::scheduleImported(int aConfId)
176 // TODO: this all goes to ConferenceEditor and model of conferences
179 Conference conf = Conference::getById(aConfId);
180 if( selectConference->findText(conf.title()) < 0 ) // item doesn't exist
182 disconnect(selectConference, SIGNAL(currentIndexChanged(int)), this, SLOT(conferenceChanged(int)));
183 selectConference->addItem(conf.title(),conf.id());
184 connect(selectConference, SIGNAL(currentIndexChanged(int)), SLOT(conferenceChanged(int)));
186 int confCount = Conference::getAll().count();
189 int idx = selectConference->findText(conf.title());
190 selectConference->setCurrentIndex(idx);
192 selectConferenceWidget->show();
194 conferenceChanged(idx);
199 void MainWindow::scheduleDeleted(const QString& title)
202 // TODO: this all goes to ConferenceEditor and model of conferences
204 int idx = selectConference->findText(title);
208 qWarning() << __PRETTY_FUNCTION__ << "removed non-existent item:" << title;
209 // this happens when you remove the only conference (the list is not ptoperly inited in this case)
210 // now make sure that conferencet
211 if (selectConference->count() > 0) {
212 selectConference->setCurrentIndex(0);
213 conferenceChanged(0);
215 conferenceChanged(-1);
218 // will it signal "changed"?
219 selectConference->removeItem(idx);
224 void MainWindow::aboutApp()
226 QDialog dialog(this);
230 dialog.setFixedWidth(width());
235 void MainWindow::conferenceMapClicked()
237 QString mapPath = QString(":/maps/campus.png");
238 if(!QFile::exists(mapPath))
239 mapPath = QString(":/maps/rooms/not-available.png");
243 QPixmap map(mapPath);
244 MapWindow window(map,roomName,this);
248 void MainWindow::eventHasChanged(int aEventId, bool aReloadModel)
250 dayTabContainer->updateTreeViewModel(aEventId);
251 favsTabContainer->updateTreeViewModel(aEventId,aReloadModel);
252 tracksTabContainer->updateTreeViewModel(aEventId);
253 nowTabContainer->updateTreeViewModel(aEventId);
254 roomsTabContainer->updateTreeViewModel(aEventId);
255 searchTabContainer->updateTreeViewModel(aEventId);
258 void MainWindow::useConference(int id)
261 Conference::getById(Conference::activeConference()).update("active",0);
262 Conference new_active = Conference::getById(id);
263 new_active.update("active",1);
265 // looks like it does not work at n900
266 setWindowTitle(new_active.title());
269 // dont run initTabs() here
270 // it takes much CPU, making travelling between conferences in ConferenceEditor longer
271 // and is not seen in maemo WM anyway
272 // instead run it explicitly where needed
273 // dont forget to protect the calls by try-catch!
275 // just in case, clear conference selection instead
278 // end of optimization
280 } catch (OrmException& e) {
281 // cannon set an active conference
288 void MainWindow::initTabs()
290 int confId = Conference::activeConference();
291 Conference active = Conference::getById(confId);
292 QDate startDate = active.start();
293 QDate endDate = active.end();
295 // 'dayNavigator' emits signal 'dateChanged' after setting valid START:END dates
296 dayTabContainer->setDates(startDate, endDate);
297 tracksTabContainer->setDates(startDate, endDate);
298 roomsTabContainer->setDates(startDate, endDate);
299 favsTabContainer->setDates(startDate, endDate);
300 searchTabContainer->setDates(startDate, endDate);
301 searchTabContainer->searchAgainClicked();
302 nowTabContainer->updateTreeView(QDate::currentDate());
305 void MainWindow::clearTabs()
307 dayTabContainer->clearModel();
308 tracksTabContainer->clearModel();
309 roomsTabContainer->clearModel();
310 favsTabContainer->clearModel();
311 searchTabContainer->clearModel();
312 searchTabContainer->searchAgainClicked();
313 nowTabContainer->clearModel();
316 void MainWindow::unsetConference()
319 setWindowTitle(saved_title);
322 void MainWindow::setup()
324 SettingsDialog dialog;
327 qDebug() << "Setting-up proxy: " << AppSettings::proxyAddress() << ":" << AppSettings::proxyPort();
329 AppSettings::isDirectConnection() ? QNetworkProxy::NoProxy : QNetworkProxy::HttpProxy,
330 AppSettings::proxyAddress(),
331 AppSettings::proxyPort(),
334 QNetworkProxy::setApplicationProxy(proxy);
337 /** Create and run ConferenceEditor dialog, making required connections for it.
339 This method manages, which classes actually perform changes in conference list.
341 There are several classes that modify the conferences:
343 deletion and URL update.
344 this, mXmlParser and mNetworkAccessManager:
345 addition and refresh.
347 void MainWindow::showConferences()
349 ConferenceEditor dialog(conferenceModel, this);
351 // TODO: connect signals about progress of network and parsing
353 connect(&dialog, SIGNAL(haveConferenceUrl(const QString&)), SLOT(importFromNetwork(const QString&)));
354 connect(&dialog, SIGNAL(haveConferenceFile(const QString&)), SLOT(importFromFile(const QString&)));
355 connect(&dialog, SIGNAL(removeConferenceRequested(int)), SLOT(removeConference(int)));
356 connect(&dialog, SIGNAL(changeUrlRequested(int, const QString&)),
357 SLOT(changeConferenceUrl(int, const QString&)));
359 connect(&dialog, SIGNAL(haveConferenceSelected(int)), SLOT(useConference(int)));
360 connect(&dialog, SIGNAL(noneConferenceSelected()), SLOT(unsetConference()));
362 connect(mXmlParser, SIGNAL(parsingScheduleBegin()), &dialog, SLOT(importStarted()));
363 connect(mXmlParser, SIGNAL(progressStatus(int)), &dialog, SLOT(showParsingProgress(int)));
364 connect(mXmlParser, SIGNAL(parsingScheduleEnd(const QString&)), &dialog, SLOT(importFinished(const QString&)));
366 connect(this, SIGNAL(conferenceRemoved()), &dialog, SLOT(conferenceRemoved()));
370 // optimization, see useConference() code
373 } catch (OrmException) {
378 void MainWindow::networkQueryFinished(QNetworkReply *aReply)
380 if ( aReply->error() != QNetworkReply::NoError )
382 error_message(QString("Error occured during download: ") + aReply->errorString());
386 qDebug() << __PRETTY_FUNCTION__ << ": have data";
387 importData(aReply->readAll(), aReply->url().toEncoded());
391 void MainWindow::importData(const QByteArray &aData, const QString& url)
394 // instead send signals to the child dialog
399 // proxySettings->hide();
402 int confId = mXmlParser->parseData(aData, url);
408 // proxySettings->show();
409 importScheduleLabel->setText("Schedule:");
413 emit(scheduleImported(confId));
417 void MainWindow::importFromNetwork(const QString& url)
419 qDebug() << __PRETTY_FUNCTION__;
420 QNetworkRequest request;
421 request.setUrl(QUrl(url));
423 mNetworkAccessManager->setProxy(QNetworkProxy::applicationProxy());
424 mNetworkAccessManager->get(request);
427 void MainWindow::importFromFile(const QString& filename)
429 qDebug() << __PRETTY_FUNCTION__;
430 QFile file(filename);
431 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
432 static const QString format("Cannot read \"%1\": error %2");
433 error_message(format.arg(filename, QString::number(file.error())));
436 importData(file.readAll(), "");
439 void MainWindow::removeConference(int id)
441 Conference::deleteConference(id);
442 conferenceModel->conferenceRemoved();
444 emit conferenceRemoved();
447 void MainWindow::changeConferenceUrl(int id, const QString& url)
449 Conference::getById(id).setUrl(url);