2 * Copyright (C) 2010 Ixonos Plc.
3 * Copyright (C) 2011-2012 Philipp Spitzer, gregor herrmann, Stefan Stahl
5 * This file is part of ConfClerk.
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)
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
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/>.
20 #include "mainwindow.h"
24 #include <QNetworkProxy>
25 #include <QNetworkAccessManager>
26 #include <QNetworkReply>
28 #include <sqlengine.h>
31 #include <eventmodel.h>
34 #include <conference.h>
37 #include <QMessageBox>
40 #include <eventdialog.h>
41 #include "daynavigatorwidget.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);
73 if(AppSettings::isDirectConnection())
75 qDebug() << "Setting-up proxy: " << AppSettings::proxyAddress() << ":" << AppSettings::proxyPort();
79 AppSettings::isDirectConnection() ? QNetworkProxy::NoProxy : QNetworkProxy::HttpProxy,
80 AppSettings::proxyAddress(),
81 AppSettings::proxyPort(),
84 QNetworkProxy::setApplicationProxy(proxy);
86 // event details have changed
87 connect(dayTabContainer, SIGNAL(eventChanged(int,bool)), SLOT(onEventChanged(int,bool)));
88 connect(favsTabContainer, SIGNAL(eventChanged(int,bool)), SLOT(onEventChanged(int,bool)));
89 connect(tracksTabContainer, SIGNAL(eventChanged(int,bool)), SLOT(onEventChanged(int,bool)));
90 connect(roomsTabContainer, SIGNAL(eventChanged(int,bool)), SLOT(onEventChanged(int,bool)));
91 connect(searchTabContainer, SIGNAL(eventChanged(int,bool)), SLOT(onEventChanged(int,bool)));
94 connect(dayNavigator, SIGNAL(dateChanged(QDate)), dayTabContainer, SLOT(redisplayDate(QDate)));
95 connect(dayNavigator, SIGNAL(dateChanged(QDate)), favsTabContainer, SLOT(redisplayDate(QDate)));
96 connect(dayNavigator, SIGNAL(dateChanged(QDate)), tracksTabContainer, SLOT(redisplayDate(QDate)));
97 connect(dayNavigator, SIGNAL(dateChanged(QDate)), roomsTabContainer, SLOT(redisplayDate(QDate)));
98 connect(dayNavigator, SIGNAL(dateChanged(QDate)), searchTabContainer, SLOT(redisplayDate(QDate)));
100 // search result has changed
101 connect(searchTabContainer, SIGNAL(searchResultChanged()), SLOT(onSearchResultChanged()));
104 useConference(Conference::activeConference());
105 // optimization, see useConference() code
108 } catch (const OrmException& e) {
109 qDebug() << "OrmException:" << e.text();
113 // open dialog for given Event ID
114 // this is used in case Alarm Dialog request application to start
119 EventDialog dialog(aEventId,this);
122 catch(OrmNoObjectException&) {} // just start application
123 catch(...) {} // just start application
126 connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply*)), SLOT(networkQueryFinished(QNetworkReply*)));
128 connect(mXmlParser, SIGNAL(parsingScheduleBegin()), conferenceModel, SLOT(newConferenceBegin()));
129 connect(mXmlParser, SIGNAL(parsingScheduleEnd(const QString&)), conferenceModel, SLOT(newConferenceEnd(const QString&)));
132 void MainWindow::on_aboutAction_triggered()
134 QDialog dialog(this);
137 ui.labDescription->setText(ui.labDescription->text().arg(qApp->applicationVersion()));
139 dialog.setFixedWidth(width());
145 void MainWindow::on_reloadAction_triggered() {
146 int confId = Conference::activeConference();
147 if (confId== -1) return;
148 Conference active = Conference::getById(confId);
149 if (active.url().isEmpty()) return;
150 importFromNetwork(active.url());
155 void MainWindow::on_nowAction_triggered() {
156 int confId = Conference::activeConference();
157 if (confId== -1) return;
158 dayNavigator->setCurDate(QDate::currentDate());
159 dayTabContainer->expandTimeGroup(QTime::currentTime(), confId);
163 void MainWindow::on_searchAction_triggered() {
164 if (tabWidget->currentWidget() == searchTab)
165 searchTabContainer->showSearchDialog(!searchTabContainer->searchDialogIsVisible());
167 tabWidget->setCurrentWidget(searchTab);
168 searchTabContainer->showSearchDialog();
173 void MainWindow::on_expandAllAction_triggered() {
174 if (tabWidget->currentWidget() == favouritesTab) favsTabContainer->treeView->expandAll();
175 if (tabWidget->currentWidget() == dayViewTab) dayTabContainer->treeView->expandAll();
176 if (tabWidget->currentWidget() == tracksTab) tracksTabContainer->treeView->expandAll();
177 if (tabWidget->currentWidget() == roomsTab) roomsTabContainer->treeView->expandAll();
178 if (tabWidget->currentWidget() == searchTab) searchTabContainer->treeView->expandAll();
182 void MainWindow::on_collapseAllAction_triggered() {
183 if (tabWidget->currentWidget() == favouritesTab) favsTabContainer->treeView->collapseAll();
184 if (tabWidget->currentWidget() == dayViewTab) dayTabContainer->treeView->collapseAll();
185 if (tabWidget->currentWidget() == tracksTab) tracksTabContainer->treeView->collapseAll();
186 if (tabWidget->currentWidget() == roomsTab) roomsTabContainer->treeView->collapseAll();
187 if (tabWidget->currentWidget() == searchTab) searchTabContainer->treeView->collapseAll();
191 void MainWindow::onEventChanged(int aEventId, bool favouriteChanged) {
192 dayTabContainer->redisplayEvent(aEventId);
193 if (favouriteChanged) favsTabContainer->redisplayDate(dayNavigator->curDate());
194 else favsTabContainer->redisplayEvent(aEventId);
195 tracksTabContainer->redisplayEvent(aEventId);
196 roomsTabContainer->redisplayEvent(aEventId);
197 searchTabContainer->redisplayEvent(aEventId);
201 void MainWindow::onSearchResultChanged() {
202 // Are results found on the current date?
203 QDate date = dayNavigator->curDate();
204 int count = searchTabContainer->searchResultCount(date);
205 if (count > 0) {searchTabContainer->redisplayDate(date); return;}
207 // Are results found in the future?
208 for (date = date.addDays(1); date <= dayNavigator->endDate(); date = date.addDays(1)) {
209 int count = searchTabContainer->searchResultCount(date);
210 if (count > 0) {dayNavigator->setCurDate(date); return;}
213 // Are results found in the past?
214 for (date = dayNavigator->startDate(); date < dayNavigator->curDate(); date = date.addDays(1)) {
215 int count = searchTabContainer->searchResultCount(date);
216 if (count > 0) {dayNavigator->setCurDate(date); return;}
218 // No results were found
219 searchTabContainer->redisplayDate(dayNavigator->curDate());
223 void MainWindow::useConference(int id)
225 if (id == -1) // in case no conference is active
231 Conference::getById(Conference::activeConference()).update("active",0);
232 Conference new_active = Conference::getById(id);
233 new_active.update("active",1);
235 // looks like it does not work at n900
236 setWindowTitle(new_active.title());
239 // dont run initTabs() here
240 // it takes much CPU, making travelling between conferences in ConferenceEditor longer
241 // and is not seen in maemo WM anyway
242 // instead run it explicitly
244 // 2. when ConferenceEditor finished
245 // dont forget to protect the calls by try-catch!
247 // just in case, clear conference selection instead
250 // end of optimization
252 } catch (OrmException& e) {
253 // cannon set an active conference
254 unsetConference(); // TODO: as no active conference is now correctly managed this should be handled as a fatal error
260 void MainWindow::initTabs()
262 int confId = Conference::activeConference();
263 if (confId != -1) // only init tabs if a conference is active
265 Conference active = Conference::getById(confId);
266 QDate startDate = active.start();
267 QDate endDate = active.end();
269 // 'dayNavigator' emits signal 'dateChanged' after setting valid START:END dates
270 dayNavigator->setDates(startDate, endDate);
274 void MainWindow::clearTabs()
276 dayTabContainer->clearModel();
277 tracksTabContainer->clearModel();
278 roomsTabContainer->clearModel();
279 favsTabContainer->clearModel();
280 searchTabContainer->clearModel();
283 void MainWindow::unsetConference()
286 dayNavigator->unsetDates();
287 setWindowTitle(saved_title);
290 void MainWindow::on_settingsAction_triggered()
292 SettingsDialog dialog;
293 dialog.loadDialogData();
294 if (dialog.exec() == QDialog::Accepted) {
295 dialog.saveDialogData();
297 AppSettings::isDirectConnection() ? QNetworkProxy::NoProxy : QNetworkProxy::HttpProxy,
298 AppSettings::proxyAddress(),
299 AppSettings::proxyPort(),
302 QNetworkProxy::setApplicationProxy(proxy);
306 /** Create and run ConferenceEditor dialog, making required connections for it.
308 This method manages, which classes actually perform changes in conference list.
310 There are several classes that modify the conferences:
312 deletion and URL update.
313 this, mXmlParser and mNetworkAccessManager:
314 addition and refresh.
316 void MainWindow::on_conferencesAction_triggered()
318 ConferenceEditor dialog(conferenceModel, this);
320 connect(&dialog, SIGNAL(haveConferenceUrl(const QString&)), SLOT(importFromNetwork(const QString&)));
321 connect(&dialog, SIGNAL(haveConferenceFile(const QString&)), SLOT(importFromFile(const QString&)));
322 connect(&dialog, SIGNAL(removeConferenceRequested(int)), SLOT(removeConference(int)));
323 connect(&dialog, SIGNAL(changeUrlRequested(int, const QString&)),
324 SLOT(changeConferenceUrl(int, const QString&)));
326 connect(&dialog, SIGNAL(haveConferenceSelected(int)), SLOT(useConference(int)));
327 connect(&dialog, SIGNAL(noneConferenceSelected()), SLOT(unsetConference()));
329 connect(mXmlParser, SIGNAL(parsingScheduleBegin()), &dialog, SLOT(importStarted()));
330 connect(mXmlParser, SIGNAL(progressStatus(int)), &dialog, SLOT(showParsingProgress(int)));
331 connect(mXmlParser, SIGNAL(parsingScheduleEnd(const QString&)), &dialog, SLOT(importFinished(const QString&)));
333 connect(this, SIGNAL(conferenceRemoved()), &dialog, SLOT(conferenceRemoved()));
337 // optimization, see useConference() code
340 } catch (OrmException) {
345 void MainWindow::networkQueryFinished(QNetworkReply *aReply) {
346 if (aReply->error() != QNetworkReply::NoError) {
347 error_message(QString("Error occured during download: ") + aReply->errorString());
349 QUrl redirectUrl = aReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
350 if (!redirectUrl.isEmpty()) {
351 if (redirectUrl != aReply->request().url()) {
352 importFromNetwork(redirectUrl.toString());
353 return; // don't enable controls
355 error_message(QString("Error: Cyclic redirection from %1 to itself.").arg(redirectUrl.toString()));
358 importData(aReply->readAll(), aReply->url().toEncoded());
364 void MainWindow::importData(const QByteArray &aData, const QString& url)
366 mXmlParser->parseData(aData, url);
369 void MainWindow::importFromNetwork(const QString& url)
371 QNetworkRequest request;
372 request.setUrl(QUrl(url));
374 mNetworkAccessManager->setProxy(QNetworkProxy::applicationProxy());
375 mNetworkAccessManager->get(request);
378 void MainWindow::importFromFile(const QString& filename)
380 QFile file(filename);
381 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
382 static const QString format("Cannot read \"%1\": error %2");
383 error_message(format.arg(filename, QString::number(file.error())));
386 importData(file.readAll(), "");
389 void MainWindow::removeConference(int id)
391 Conference::deleteConference(id);
392 conferenceModel->conferenceRemoved();
394 emit conferenceRemoved();
397 void MainWindow::changeConferenceUrl(int id, const QString& url)
399 Conference::getById(id).setUrl(url);