restore viewing of conference map
[toast/confclerk.git] / src / gui / mainwindow.cpp
index 552224a..2cee85c 100644 (file)
@@ -21,6 +21,8 @@
 #include <QTreeView>
 #include <QFile>
 #include <QNetworkProxy>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
 
 #include <sqlengine.h>
 
 
 #include <QDialog>
 #include <QMessageBox>
+
 #include "ui_about.h"
 #include <eventdialog.h>
 #include "daynavigatorwidget.h"
-#include "importschedulewidget.h"
-#include "mapwindow.h"
 #include "settingsdialog.h"
+#include "conferenceeditor.h"
+#include "schedulexmlparser.h"
+#include "errormessage.h"
 
 #include <tabcontainer.h>
 #include <appsettings.h>
@@ -47,9 +51,14 @@ const QString PROXY_PASSWD;
 
 MainWindow::MainWindow(int aEventId, QWidget *aParent)
     : QMainWindow(aParent)
+    , conferenceModel(new ConferenceModel(this))
+    , mXmlParser(new ScheduleXmlParser(this))
+    , mNetworkAccessManager(new QNetworkAccessManager(this))
 {
     setupUi(this);
 
+    saved_title = windowTitle();
+
 #ifdef N810
     tabWidget->setTabText(1,"Favs");
     //tabWidget->setTabText(2,"Day");
@@ -71,10 +80,6 @@ MainWindow::MainWindow(int aEventId, QWidget *aParent)
             PROXY_PASSWD);
     QNetworkProxy::setApplicationProxy(proxy);
 
-    int confId = Conference::activeConference();
-
-    connect(importScheduleWidget, SIGNAL(scheduleImported(int)), SLOT(scheduleImported(int)));
-
     // event details have changed
     connect(dayTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
     connect(favsTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
@@ -83,44 +88,24 @@ MainWindow::MainWindow(int aEventId, QWidget *aParent)
     connect(nowTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
     connect(searchTabContainer, SIGNAL(eventHasChanged(int,bool)), SLOT(eventHasChanged(int,bool)));
 
-    // event conference map button clicked
-    connect(showMapButton, SIGNAL(clicked()), SLOT(conferenceMapClicked()));
-
     connect(aboutAction, SIGNAL(triggered()), SLOT(aboutApp()));
     connect(settingsAction, SIGNAL(triggered()), SLOT(setup()));
-
-    selectConference->setDuplicatesEnabled(false);
-    int confCount = Conference::getAll().count();
-    if(confCount)
-    {
-        initTabs();
-        fillAndShowConferenceHeader();
-        setWindowTitle(Conference::getById(confId).title());
-
-        if(confCount==1) // don't have to show 'selectConference' widget, if there is only one conference in the DB
-            selectConferenceWidget->hide();
-        else
-        {
-            // have to fill comboBox with available conferences
-            QList<Conference> confs = Conference::getAll();
-            QListIterator<Conference> i(confs);
-            while(i.hasNext())
-            {
-                Conference conf = i.next();
-                selectConference->addItem(conf.title(),conf.id());
-            }
-            int idx = selectConference->findText(Conference::getById(Conference::activeConference()).title());
-            selectConference->setCurrentIndex(idx);
-        }
-        connect(selectConference, SIGNAL(currentIndexChanged(int)), SLOT(conferenceChanged(int)));
+    connect(conferencesAction, SIGNAL(triggered()), SLOT(showConferences()));
+
+    useConference(Conference::activeConference());
+    // optimization, see useConference() code
+    try {
+       initTabs();
+    } catch (OrmException) {
+       clearTabs();
     }
-    else
-    {
-        conferenceHeader->hide();
-        selectConferenceWidget->hide();
-        // go to the 'conferenceTab', so the user can import the schedule
+
+    // TODO: open conferences at startup?
+    #if 0
+    if(!confCount)
         tabWidget->setCurrentIndex(6); // 6 - conference tab
     }
+    #endif
 
     // open dialog for given Event ID
     // this is used in case Alarm Dialog request application to start
@@ -134,30 +119,11 @@ MainWindow::MainWindow(int aEventId, QWidget *aParent)
         catch(OrmNoObjectException&) {} // just start application
         catch(...) {} // just start application
     }
-}
-
-void MainWindow::scheduleImported(int aConfId)
-{
-    Q_UNUSED(aConfId);
-
-    Conference conf = Conference::getById(aConfId);
-    if( selectConference->findText(conf.title()) < 0 ) // item doesn't exist
-    {
-        disconnect(selectConference, SIGNAL(currentIndexChanged(int)), this, SLOT(conferenceChanged(int)));
-        selectConference->addItem(conf.title(),conf.id());
-        connect(selectConference, SIGNAL(currentIndexChanged(int)), SLOT(conferenceChanged(int)));
-    }
-    int confCount = Conference::getAll().count();
-    if(confCount)
-    {
-        int idx = selectConference->findText(conf.title());
-        selectConference->setCurrentIndex(idx);
 
-        if(confCount>1)
-            selectConferenceWidget->show();
+    connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply*)), SLOT(networkQueryFinished(QNetworkReply*)));
 
-        conferenceChanged(idx);
-    }
+    connect(mXmlParser, SIGNAL(parsingScheduleBegin()), conferenceModel, SLOT(newConferenceBegin()));
+    connect(mXmlParser, SIGNAL(parsingScheduleEnd(const QString&)), conferenceModel, SLOT(newConferenceEnd(const QString&)));
 }
 
 void MainWindow::aboutApp()
@@ -171,19 +137,6 @@ void MainWindow::aboutApp()
     dialog.exec();
 }
 
-void MainWindow::conferenceMapClicked()
-{
-    QString mapPath = QString(":/maps/campus.png");
-    if(!QFile::exists(mapPath))
-        mapPath = QString(":/maps/rooms/not-available.png");
-
-    QString roomName;
-
-    QPixmap map(mapPath);
-    MapWindow window(map,roomName,this);
-    window.exec();
-}
-
 void MainWindow::eventHasChanged(int aEventId, bool aReloadModel)
 {
     dayTabContainer->updateTreeViewModel(aEventId);
@@ -194,24 +147,44 @@ void MainWindow::eventHasChanged(int aEventId, bool aReloadModel)
     searchTabContainer->updateTreeViewModel(aEventId);
 }
 
-void MainWindow::fillAndShowConferenceHeader()
+void MainWindow::useConference(int id)
 {
-    int confId = Conference::activeConference();
-    conferenceTitle->setText(Conference::getById(confId).title());
-    conferenceSubtitle->setText(Conference::getById(confId).subtitle());
-    conferenceWhere->setText(Conference::getById(confId).city() + ", " + Conference::getById(confId).venue());
-    conferenceWhen->setText(
-            Conference::getById(confId).start().toString("dd-MM-yyyy")
-            + ", " +
-            Conference::getById(confId).end().toString("dd-MM-yyyy"));
-    conferenceHeader->show();
+    try {
+        Conference::getById(Conference::activeConference()).update("active",0);
+        Conference new_active = Conference::getById(id);
+        new_active.update("active",1);
+
+       // looks like it does not work at n900
+        setWindowTitle(new_active.title());
+
+        // optimization.
+       // dont run initTabs() here
+        // it takes much CPU, making travelling between conferences in ConferenceEditor longer
+        // and is not seen in maemo WM anyway
+       // instead run it explicitly
+        // 1. at startup
+        // 2. when ConferenceEditor finished
+        // dont forget to protect the calls by try-catch!
+
+        // just in case, clear conference selection instead
+        clearTabs();
+
+        // end of optimization
+        // initTabs();
+    } catch (OrmException& e) {
+        // cannon set an active conference
+        unsetConference();
+        return;
+    }
+
 }
 
 void MainWindow::initTabs()
 {
     int confId = Conference::activeConference();
-    QDate startDate = Conference::getById(confId).start();
-    QDate endDate = Conference::getById(confId).end();
+    Conference active = Conference::getById(confId);
+    QDate startDate = active.start();
+    QDate endDate = active.end();
 
     // 'dayNavigator' emits signal 'dateChanged' after setting valid START:END dates
     dayTabContainer->setDates(startDate, endDate);
@@ -223,14 +196,21 @@ void MainWindow::initTabs()
     nowTabContainer->updateTreeView(QDate::currentDate());
 }
 
-void MainWindow::conferenceChanged(int aIndex)
+void MainWindow::clearTabs()
 {
-    Conference::getById(Conference::activeConference()).update("active",0);
-    Conference::getById(selectConference->itemData(aIndex).toInt()).update("active",1);
+    dayTabContainer->clearModel();
+    tracksTabContainer->clearModel();
+    roomsTabContainer->clearModel();
+    favsTabContainer->clearModel();
+    searchTabContainer->clearModel();
+    searchTabContainer->searchAgainClicked();
+    nowTabContainer->clearModel();
+}
 
-    initTabs();
-    fillAndShowConferenceHeader();
-    setWindowTitle(Conference::getById(Conference::activeConference()).title());
+void MainWindow::unsetConference()
+{
+    clearTabs();
+    setWindowTitle(saved_title);
 }
 
 void MainWindow::setup()
@@ -247,3 +227,96 @@ void MainWindow::setup()
             PROXY_PASSWD);
     QNetworkProxy::setApplicationProxy(proxy);
 }
+
+/** Create and run ConferenceEditor dialog, making required connections for it.
+
+This method manages, which classes actually perform changes in conference list.
+
+There are several classes that modify the conferences:
+this:
+ deletion and URL update.
+this, mXmlParser and mNetworkAccessManager:
+ addition and refresh.
+*/
+void MainWindow::showConferences()
+{
+    ConferenceEditor dialog(conferenceModel, this);
+
+    connect(&dialog, SIGNAL(haveConferenceUrl(const QString&)), SLOT(importFromNetwork(const QString&)));
+    connect(&dialog, SIGNAL(haveConferenceFile(const QString&)), SLOT(importFromFile(const QString&)));
+    connect(&dialog, SIGNAL(removeConferenceRequested(int)), SLOT(removeConference(int)));
+    connect(&dialog, SIGNAL(changeUrlRequested(int, const QString&)),
+                    SLOT(changeConferenceUrl(int, const QString&)));
+
+    connect(&dialog, SIGNAL(haveConferenceSelected(int)), SLOT(useConference(int)));
+    connect(&dialog, SIGNAL(noneConferenceSelected()), SLOT(unsetConference()));
+
+    connect(mXmlParser, SIGNAL(parsingScheduleBegin()), &dialog, SLOT(importStarted()));
+    connect(mXmlParser, SIGNAL(progressStatus(int)), &dialog, SLOT(showParsingProgress(int)));
+    connect(mXmlParser, SIGNAL(parsingScheduleEnd(const QString&)), &dialog, SLOT(importFinished(const QString&)));
+
+    connect(this, SIGNAL(conferenceRemoved()), &dialog, SLOT(conferenceRemoved()));
+
+    dialog.exec();
+
+    // optimization, see useConference() code
+    try {
+        initTabs();
+    } catch (OrmException) {
+        clearTabs();
+    }
+}
+
+void MainWindow::networkQueryFinished(QNetworkReply *aReply)
+{
+    if ( aReply->error() != QNetworkReply::NoError )
+    {
+        error_message(QString("Error occured during download: ") + aReply->errorString());
+    }
+    else
+    {
+        qDebug() << __PRETTY_FUNCTION__ << ": have data";
+        importData(aReply->readAll(), aReply->url().toEncoded());
+    }
+}
+
+void MainWindow::importData(const QByteArray &aData, const QString& url)
+{
+    mXmlParser->parseData(aData, url);
+}
+
+void MainWindow::importFromNetwork(const QString& url)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    QNetworkRequest request;
+    request.setUrl(QUrl(url));
+
+    mNetworkAccessManager->setProxy(QNetworkProxy::applicationProxy());
+    mNetworkAccessManager->get(request);
+}
+
+void MainWindow::importFromFile(const QString& filename)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    QFile file(filename);
+    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {    
+        static const QString format("Cannot read \"%1\": error %2");
+        error_message(format.arg(filename, QString::number(file.error())));
+    }
+
+    importData(file.readAll(), "");
+}
+
+void MainWindow::removeConference(int id)
+{
+    Conference::deleteConference(id);
+    conferenceModel->conferenceRemoved();
+
+    emit conferenceRemoved();
+}
+
+void MainWindow::changeConferenceUrl(int id, const QString& url)
+{
+    Conference::getById(id).setUrl(url);
+}
+