source: confclerk_git/src/gui/mainwindow.cpp @ 097e1f4

qt5
Last change on this file since 097e1f4 was 097e1f4, checked in by gregor herrmann <gregoa@…>, 9 years ago

extend comment re systrayicon position

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