source: src/gui/mainwindow.cpp @ 3720891

qt5
Last change on this file since 3720891 was 3720891, checked in by Philipp Spitzer <philipp@…>, 10 years ago

Current day is used now when starting the program or loading a conference (ticket #44).

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