source: confclerk_git/src/gui/mainwindow.cpp @ 8bd618c

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

We added the conferenceId to some alarm related methods (ticket #41).

  • 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    }
260}
261
262void MainWindow::clearTabs()
263{
264    dayTabContainer->clearModel();
265    tracksTabContainer->clearModel();
266    roomsTabContainer->clearModel();
267    favsTabContainer->clearModel();
268    searchTabContainer->clearModel();
269}
270
271void MainWindow::unsetConference()
272{
273    clearTabs();
274    dayNavigator->unsetDates();
275    setWindowTitle(saved_title);
276}
277
278
279void MainWindow::showError(const QString& message) {
280    error_message(message);
281}
282
283
284void MainWindow::on_settingsAction_triggered()
285{
286    SettingsDialog dialog;
287    dialog.loadDialogData();
288    if (dialog.exec() == QDialog::Accepted) {
289        dialog.saveDialogData();
290        QNetworkProxy proxy(
291                AppSettings::isDirectConnection() ? QNetworkProxy::NoProxy : QNetworkProxy::HttpProxy,
292                AppSettings::proxyAddress(),
293                AppSettings::proxyPort(),
294                PROXY_USERNAME,
295                PROXY_PASSWD);
296        QNetworkProxy::setApplicationProxy(proxy);
297    }
298}
299
300/** Create and run ConferenceEditor dialog, making required connections for it.
301
302This method manages, which classes actually perform changes in conference list.
303
304There are several classes that modify the conferences:
305this:
306 deletion and URL update.
307this, mXmlParser and mNetworkAccessManager:
308 addition and refresh.
309*/
310void MainWindow::on_conferencesAction_triggered()
311{
312    ConferenceEditor dialog(conferenceModel, this);
313
314    connect(&dialog, SIGNAL(haveConferenceUrl(const QString&, int)), SLOT(importFromNetwork(const QString&, int)));
315    connect(&dialog, SIGNAL(haveConferenceFile(const QString&, int)), SLOT(importFromFile(const QString&, int)));
316    connect(&dialog, SIGNAL(removeConferenceRequested(int)), SLOT(removeConference(int)));
317    connect(&dialog, SIGNAL(changeUrlRequested(int, const QString&)),
318                    SLOT(changeConferenceUrl(int, const QString&)));
319
320    connect(&dialog, SIGNAL(haveConferenceSelected(int)), SLOT(useConference(int)));
321    connect(&dialog, SIGNAL(noneConferenceSelected()), SLOT(unsetConference()));
322
323    connect(mXmlParser, SIGNAL(parsingScheduleBegin()), &dialog, SLOT(importStarted()));
324    connect(mXmlParser, SIGNAL(progressStatus(int)), &dialog, SLOT(showParsingProgress(int)));
325    connect(mXmlParser, SIGNAL(parsingScheduleEnd(int)), &dialog, SLOT(importFinished(int)));
326
327    connect(this, SIGNAL(conferenceRemoved()), &dialog, SLOT(conferenceRemoved()));
328
329    dialog.exec();
330
331    // optimization, see useConference() code
332    try {
333        initTabs();
334    } catch (OrmException) {
335        clearTabs();
336    }
337}
338
339void MainWindow::networkQueryFinished(QNetworkReply *aReply) {
340    if (aReply->error() != QNetworkReply::NoError) {
341        error_message(QString("Error occured during download: ") + aReply->errorString());
342    } else {
343        QUrl redirectUrl = aReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
344        if (!redirectUrl.isEmpty()) {
345            if (redirectUrl != aReply->request().url()) {
346                importFromNetwork(redirectUrl.toString(), aReply->request().attribute(QNetworkRequest::User).toInt());
347                return; // don't enable controls
348            } else {
349                error_message(QString("Error: Cyclic redirection from %1 to itself.").arg(redirectUrl.toString()));
350            }
351        } else {
352            importData(aReply->readAll(), aReply->url().toEncoded(), aReply->request().attribute(QNetworkRequest::User).toInt());
353        }
354    }
355    setEnabled(true);
356}
357
358void MainWindow::importData(const QByteArray &aData, const QString& url, int conferenceId)
359{
360    mXmlParser->parseData(aData, url, conferenceId);
361}
362
363void MainWindow::importFromNetwork(const QString& url, int conferenceId)
364{
365    QNetworkRequest request;
366    request.setUrl(QUrl(url));
367    request.setAttribute(QNetworkRequest::User, conferenceId);
368
369    mNetworkAccessManager->setProxy(QNetworkProxy::applicationProxy());
370    mNetworkAccessManager->get(request);
371}
372
373void MainWindow::importFromFile(const QString& filename, int conferenceId)
374{
375    QFile file(filename);
376    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {   
377        static const QString format("Cannot read \"%1\": error %2");
378        error_message(format.arg(filename, QString::number(file.error())));
379    }
380
381    importData(file.readAll(), "", conferenceId);
382}
383
384
385void MainWindow::removeConference(int id) {
386    sqlEngine->deleteConference(id);
387    conferenceModel->conferenceRemoved();
388    emit conferenceRemoved();
389}
390
391
392void MainWindow::changeConferenceUrl(int id, const QString& url) {
393    Conference::getById(id).setUrl(url);
394}
395
Note: See TracBrowser for help on using the repository browser.