source: src/gui/mainwindow.cpp @ 56307f8

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

Implemented expand/collapse of the event groups. Resolves ticket #31.

  • Property mode set to 100644
File size: 13.5 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    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();
179}
180
181
182void 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();
188}
189
190
191void 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);
198}
199
200
201void 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;}
206
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;}
211    }
212
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;}
217    }
218    // No results were found
219    searchTabContainer->redisplayDate(dayNavigator->curDate());
220}
221
222
223void MainWindow::useConference(int id)
224{
225    if (id == -1)  // in case no conference is active
226    {
227        unsetConference();
228        return;
229    }
230    try {
231        Conference::getById(Conference::activeConference()).update("active",0);
232        Conference new_active = Conference::getById(id);
233        new_active.update("active",1);
234
235        // looks like it does not work at n900
236        setWindowTitle(new_active.title());
237
238        // optimization.
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
243        // 1. at startup
244        // 2. when ConferenceEditor finished
245        // dont forget to protect the calls by try-catch!
246
247        // just in case, clear conference selection instead
248        clearTabs();
249
250        // end of optimization
251        // initTabs();
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
255        return;
256    }
257
258}
259
260void MainWindow::initTabs()
261{
262    int confId = Conference::activeConference();
263    if (confId != -1)   // only init tabs if a conference is active
264    {
265        Conference active = Conference::getById(confId);
266        QDate startDate = active.start();
267        QDate endDate = active.end();
268
269        // 'dayNavigator' emits signal 'dateChanged' after setting valid START:END dates
270        dayNavigator->setDates(startDate, endDate);
271    }
272}
273
274void MainWindow::clearTabs()
275{
276    dayTabContainer->clearModel();
277    tracksTabContainer->clearModel();
278    roomsTabContainer->clearModel();
279    favsTabContainer->clearModel();
280    searchTabContainer->clearModel();
281}
282
283void MainWindow::unsetConference()
284{
285    clearTabs();
286    dayNavigator->unsetDates();
287    setWindowTitle(saved_title);
288}
289
290void MainWindow::on_settingsAction_triggered()
291{
292    SettingsDialog dialog;
293    dialog.loadDialogData();
294    if (dialog.exec() == QDialog::Accepted) {
295        dialog.saveDialogData();
296        QNetworkProxy proxy(
297                AppSettings::isDirectConnection() ? QNetworkProxy::NoProxy : QNetworkProxy::HttpProxy,
298                AppSettings::proxyAddress(),
299                AppSettings::proxyPort(),
300                PROXY_USERNAME,
301                PROXY_PASSWD);
302        QNetworkProxy::setApplicationProxy(proxy);
303    }
304}
305
306/** Create and run ConferenceEditor dialog, making required connections for it.
307
308This method manages, which classes actually perform changes in conference list.
309
310There are several classes that modify the conferences:
311this:
312 deletion and URL update.
313this, mXmlParser and mNetworkAccessManager:
314 addition and refresh.
315*/
316void MainWindow::on_conferencesAction_triggered()
317{
318    ConferenceEditor dialog(conferenceModel, this);
319
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&)));
325
326    connect(&dialog, SIGNAL(haveConferenceSelected(int)), SLOT(useConference(int)));
327    connect(&dialog, SIGNAL(noneConferenceSelected()), SLOT(unsetConference()));
328
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&)));
332
333    connect(this, SIGNAL(conferenceRemoved()), &dialog, SLOT(conferenceRemoved()));
334
335    dialog.exec();
336
337    // optimization, see useConference() code
338    try {
339        initTabs();
340    } catch (OrmException) {
341        clearTabs();
342    }
343}
344
345void MainWindow::networkQueryFinished(QNetworkReply *aReply) {
346    if (aReply->error() != QNetworkReply::NoError) {
347        error_message(QString("Error occured during download: ") + aReply->errorString());
348    } else {
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
354            } else {
355                error_message(QString("Error: Cyclic redirection from %1 to itself.").arg(redirectUrl.toString()));
356            }
357        } else {
358            importData(aReply->readAll(), aReply->url().toEncoded());
359        }
360    }
361    setEnabled(true);
362}
363
364void MainWindow::importData(const QByteArray &aData, const QString& url)
365{
366    mXmlParser->parseData(aData, url);
367}
368
369void MainWindow::importFromNetwork(const QString& url)
370{
371    QNetworkRequest request;
372    request.setUrl(QUrl(url));
373
374    mNetworkAccessManager->setProxy(QNetworkProxy::applicationProxy());
375    mNetworkAccessManager->get(request);
376}
377
378void MainWindow::importFromFile(const QString& filename)
379{
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())));
384    }
385
386    importData(file.readAll(), "");
387}
388
389void MainWindow::removeConference(int id)
390{
391    Conference::deleteConference(id);
392    conferenceModel->conferenceRemoved();
393
394    emit conferenceRemoved();
395}
396
397void MainWindow::changeConferenceUrl(int id, const QString& url)
398{
399    Conference::getById(id).setUrl(url);
400}
401
Note: See TracBrowser for help on using the repository browser.