source: confclerk_git/src/gui/mainwindow.cpp @ 1ba9324

qt5
Last change on this file since 1ba9324 was 1ba9324, checked in by gregor herrmann <gregoa@…>, 10 years ago

Handle redirects when importing schedules over the network.

Fixes: #39

  • Property mode set to 100644
File size: 12.6 KB
Line 
1/*
2 * Copyright (C) 2010 Ixonos Plc.
3 * Copyright (C) 2011-2012 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
50const QString PROXY_USERNAME;
51const QString PROXY_PASSWD;
52
53MainWindow::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(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)));
92
93    // date has changed
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)));
99
100    // search result has changed
101    connect(searchTabContainer, SIGNAL(searchResultChanged()), SLOT(onSearchResultChanged()));
102
103
104    useConference(Conference::activeConference());
105    // optimization, see useConference() code
106    try {
107        initTabs();
108    } catch (const OrmException& e) {
109        qDebug() << "OrmException:" << e.text();
110        clearTabs();
111    }
112
113    // open dialog for given Event ID
114    // this is used in case Alarm Dialog request application to start
115    if(aEventId)
116    {
117        try
118        {
119            EventDialog dialog(aEventId,this);
120            dialog.exec();
121        }
122        catch(OrmNoObjectException&) {} // just start application
123        catch(...) {} // just start application
124    }
125
126    connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply*)), SLOT(networkQueryFinished(QNetworkReply*)));
127
128    connect(mXmlParser, SIGNAL(parsingScheduleBegin()), conferenceModel, SLOT(newConferenceBegin()));
129    connect(mXmlParser, SIGNAL(parsingScheduleEnd(const QString&)), conferenceModel, SLOT(newConferenceEnd(const QString&)));
130}
131
132void MainWindow::on_aboutAction_triggered()
133{
134    QDialog dialog(this);
135    Ui::AboutDialog ui;
136    ui.setupUi(&dialog);
137    ui.labDescription->setText(ui.labDescription->text().arg(qApp->applicationVersion()));
138#ifdef N810
139    dialog.setFixedWidth(width());
140#endif
141    dialog.exec();
142}
143
144
145void 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());
151    setEnabled(false);
152}
153
154
155void 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);
160}
161
162
163void MainWindow::on_searchAction_triggered() {
164    if (tabWidget->currentWidget() == searchTab)
165        searchTabContainer->showSearchDialog(!searchTabContainer->searchDialogIsVisible());
166    else {
167        tabWidget->setCurrentWidget(searchTab);
168        searchTabContainer->showSearchDialog();
169    }
170}
171
172
173void MainWindow::on_expandAllAction_triggered() {
174
175}
176
177
178void MainWindow::on_collapseAllAction_triggered() {
179
180}
181
182
183void MainWindow::onEventChanged(int aEventId, bool favouriteChanged) {
184    dayTabContainer->redisplayEvent(aEventId);
185    if (favouriteChanged) favsTabContainer->redisplayDate(dayNavigator->curDate());
186    else favsTabContainer->redisplayEvent(aEventId);
187    tracksTabContainer->redisplayEvent(aEventId);
188    roomsTabContainer->redisplayEvent(aEventId);
189    searchTabContainer->redisplayEvent(aEventId);
190}
191
192
193void MainWindow::onSearchResultChanged() {
194    // Are results found on the current date?
195    QDate date = dayNavigator->curDate();
196    int count = searchTabContainer->searchResultCount(date);
197    if (count > 0) {searchTabContainer->redisplayDate(date); return;}
198
199    // Are results found in the future?
200    for (date = date.addDays(1); date <= dayNavigator->endDate(); date = date.addDays(1)) {
201        int count = searchTabContainer->searchResultCount(date);
202        if (count > 0) {dayNavigator->setCurDate(date); return;}
203    }
204
205    // Are results found in the past?
206    for (date = dayNavigator->startDate(); date < dayNavigator->curDate(); date = date.addDays(1)) {
207        int count = searchTabContainer->searchResultCount(date);
208        if (count > 0) {dayNavigator->setCurDate(date); return;}
209    }
210    // No results were found
211    searchTabContainer->redisplayDate(dayNavigator->curDate());
212}
213
214
215void MainWindow::useConference(int id)
216{
217    if (id == -1)  // in case no conference is active
218    {
219        unsetConference();
220        return;
221    }
222    try {
223        Conference::getById(Conference::activeConference()).update("active",0);
224        Conference new_active = Conference::getById(id);
225        new_active.update("active",1);
226
227        // looks like it does not work at n900
228        setWindowTitle(new_active.title());
229
230        // optimization.
231        // dont run initTabs() here
232        // it takes much CPU, making travelling between conferences in ConferenceEditor longer
233        // and is not seen in maemo WM anyway
234        // instead run it explicitly
235        // 1. at startup
236        // 2. when ConferenceEditor finished
237        // dont forget to protect the calls by try-catch!
238
239        // just in case, clear conference selection instead
240        clearTabs();
241
242        // end of optimization
243        // initTabs();
244    } catch (OrmException& e) {
245        // cannon set an active conference
246        unsetConference();   // TODO: as no active conference is now correctly managed this should be handled as a fatal error
247        return;
248    }
249
250}
251
252void MainWindow::initTabs()
253{
254    int confId = Conference::activeConference();
255    if (confId != -1)   // only init tabs if a conference is active
256    {
257        Conference active = Conference::getById(confId);
258        QDate startDate = active.start();
259        QDate endDate = active.end();
260
261        // 'dayNavigator' emits signal 'dateChanged' after setting valid START:END dates
262        dayNavigator->setDates(startDate, endDate);
263    }
264}
265
266void MainWindow::clearTabs()
267{
268    dayTabContainer->clearModel();
269    tracksTabContainer->clearModel();
270    roomsTabContainer->clearModel();
271    favsTabContainer->clearModel();
272    searchTabContainer->clearModel();
273}
274
275void MainWindow::unsetConference()
276{
277    clearTabs();
278    dayNavigator->unsetDates();
279    setWindowTitle(saved_title);
280}
281
282void MainWindow::on_settingsAction_triggered()
283{
284    SettingsDialog dialog;
285    dialog.loadDialogData();
286    if (dialog.exec() == QDialog::Accepted) {
287        dialog.saveDialogData();
288        QNetworkProxy proxy(
289                AppSettings::isDirectConnection() ? QNetworkProxy::NoProxy : QNetworkProxy::HttpProxy,
290                AppSettings::proxyAddress(),
291                AppSettings::proxyPort(),
292                PROXY_USERNAME,
293                PROXY_PASSWD);
294        QNetworkProxy::setApplicationProxy(proxy);
295    }
296}
297
298/** Create and run ConferenceEditor dialog, making required connections for it.
299
300This method manages, which classes actually perform changes in conference list.
301
302There are several classes that modify the conferences:
303this:
304 deletion and URL update.
305this, mXmlParser and mNetworkAccessManager:
306 addition and refresh.
307*/
308void MainWindow::on_conferencesAction_triggered()
309{
310    ConferenceEditor dialog(conferenceModel, this);
311
312    connect(&dialog, SIGNAL(haveConferenceUrl(const QString&)), SLOT(importFromNetwork(const QString&)));
313    connect(&dialog, SIGNAL(haveConferenceFile(const QString&)), SLOT(importFromFile(const QString&)));
314    connect(&dialog, SIGNAL(removeConferenceRequested(int)), SLOT(removeConference(int)));
315    connect(&dialog, SIGNAL(changeUrlRequested(int, const QString&)),
316                    SLOT(changeConferenceUrl(int, const QString&)));
317
318    connect(&dialog, SIGNAL(haveConferenceSelected(int)), SLOT(useConference(int)));
319    connect(&dialog, SIGNAL(noneConferenceSelected()), SLOT(unsetConference()));
320
321    connect(mXmlParser, SIGNAL(parsingScheduleBegin()), &dialog, SLOT(importStarted()));
322    connect(mXmlParser, SIGNAL(progressStatus(int)), &dialog, SLOT(showParsingProgress(int)));
323    connect(mXmlParser, SIGNAL(parsingScheduleEnd(const QString&)), &dialog, SLOT(importFinished(const QString&)));
324
325    connect(this, SIGNAL(conferenceRemoved()), &dialog, SLOT(conferenceRemoved()));
326
327    dialog.exec();
328
329    // optimization, see useConference() code
330    try {
331        initTabs();
332    } catch (OrmException) {
333        clearTabs();
334    }
335}
336
337void MainWindow::networkQueryFinished(QNetworkReply *aReply) {
338    if (aReply->error() != QNetworkReply::NoError) {
339        error_message(QString("Error occured during download: ") + aReply->errorString());
340    } else {
341        QUrl redirectUrl = aReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
342        if (!redirectUrl.isEmpty()) {
343            if (redirectUrl != aReply->request().url()) {
344                importFromNetwork(redirectUrl.toString());
345                return; // don't enable controls
346            } else {
347                error_message(QString("Error: Cyclic redirection from %1 to itself.").arg(redirectUrl.toString()));
348            }
349        } else {
350            importData(aReply->readAll(), aReply->url().toEncoded());
351        }
352    }
353    setEnabled(true);
354}
355
356void MainWindow::importData(const QByteArray &aData, const QString& url)
357{
358    mXmlParser->parseData(aData, url);
359}
360
361void MainWindow::importFromNetwork(const QString& url)
362{
363    QNetworkRequest request;
364    request.setUrl(QUrl(url));
365
366    mNetworkAccessManager->setProxy(QNetworkProxy::applicationProxy());
367    mNetworkAccessManager->get(request);
368}
369
370void MainWindow::importFromFile(const QString& filename)
371{
372    QFile file(filename);
373    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {   
374        static const QString format("Cannot read \"%1\": error %2");
375        error_message(format.arg(filename, QString::number(file.error())));
376    }
377
378    importData(file.readAll(), "");
379}
380
381void MainWindow::removeConference(int id)
382{
383    Conference::deleteConference(id);
384    conferenceModel->conferenceRemoved();
385
386    emit conferenceRemoved();
387}
388
389void MainWindow::changeConferenceUrl(int id, const QString& url)
390{
391    Conference::getById(id).setUrl(url);
392}
393
Note: See TracBrowser for help on using the repository browser.