Behave correctly if score contains unknown course
[scorecard] / src / main-window.cpp
index 101b335..ad85c04 100644 (file)
+/*
+ * Copyright (C) 2009 Sakari Poussa
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ */
+
 #include <QtGui>
-#include <QDirModel>
-#include <QTreeView>
-#include <QListView>
-#include <QStandardItemModel>
+#ifdef Q_WS_MAEMO_5
+#include <QMaemo5InformationBox>
+#endif
 
+#include "score-common.h"
 #include "main-window.h"
 #include "score-dialog.h"
 #include "course-dialog.h"
-#include "tree-widget.h"
-#include "xml-parser.h"
+#include "settings-dialog.h"
+#include "stat-model.h"
 #include "xml-dom-parser.h"
 
 QString appName("scorecard");
-QString topDir("/opt/scorecard");
-QString mmcDir("/media/mmc1/scorecard");
-QString dataDirName("/data/");
+QString topDir("/opt");
+QString mmcDir("/media/mmc1");
+QString dataDirName("data");
 QString dataDir;
 QString imgDir(topDir + "/pixmaps");
 QString scoreFileName("score.xml");
 QString scoreFile;
 QString clubFileName("club.xml");
 QString clubFile;
+QString masterFileName("club-master.xml");
+QString masterFile;
 QString logFile("/tmp/scorecard.log");
+QString titleScores("ScoreCard - Scores");
+QString titleCourses("ScoreCard - Courses");
 
 bool dateLessThan(const Score *s1, const Score *s2)
 {
   return (*s1) < (*s2);
 }
 
+bool dateMoreThan(const Score *s1, const Score *s2)
+{
+  return (*s1) > (*s2);
+}
+// Find score based on club and course name
+Score *MainWindow::findScore(QString & clubName, QString & courseName)
+{
+    TRACE;
+    QListIterator<Score *> i(scoreList);
+    Score * s;
+
+    while (i.hasNext()) {
+        s = i.next();
+        if ((s->getClubName() == clubName) &&
+            (s->getCourseName() == courseName))
+            return s;
+    }
+    return 0;
+}
+
+// Find club based on name
+Club *MainWindow::findClub(QString &name)
+{
+    TRACE;
+    QListIterator<Club *> i(clubList);
+    Club *c;
+
+    while (i.hasNext()) {
+        c = i.next();
+        if (c->getName() == name)
+            return c;
+    }
+    return 0;
+}
+
+// Find course based on club & course name
+Course *MainWindow::findCourse(const QString &clubName, 
+                               const QString &courseName)
+{
+    TRACE;
+    QListIterator<Club *> i(clubList);
+    Club *c;
+
+    while (i.hasNext()) {
+        c = i.next();
+        if (c->getName() == clubName) {
+            return c->getCourse(courseName);
+        }
+    }
+    return 0;
+}
+
+// Find course based on current selection on the list
+// TODO: make sure this is only called when course list is the model...
+Course *MainWindow::currentCourse()
+{
+    TRACE;
+    QModelIndex index = selectionModel->currentIndex();
+
+    if (!index.isValid())
+        return 0;
+
+    const QAbstractItemModel *model = selectionModel->model();
+    QString str = model->data(index, Qt::DisplayRole).toString();
+
+    QStringList strList = str.split(", ");
+    if (strList.count() != 2) {
+        showNote(tr("Invalid course selection"));
+        return 0;
+    }
+    return findCourse(strList[0], strList[1]);
+}
+
+// Find score based on current selection on the list
+// TODO: make sure this is only called when score list is the model...
+Score *MainWindow::currentScore()
+{
+    TRACE;
+    QModelIndex index = selectionModel->currentIndex();
+
+    if (!index.isValid())
+        return 0;
+
+    return scoreList.at(index.row());
+}
+
+void MainWindow::flushReadOnlyItems()
+{
+    TRACE;
+    QMutableListIterator<Club *> i(clubList);
+    Club *c;
+
+    while (i.hasNext()) {
+        c = i.next();
+        if (c->isReadOnly()) {
+            qDebug() << "Del:" << c->getName();
+            i.remove();
+        }
+    }
+}
+
+void MainWindow::markHomeClub()
+{
+    TRACE;
+    QListIterator<Club *> i(clubList);
+    Club *c;
+
+    while (i.hasNext()) {
+        c = i.next();
+        if (c->getName() == conf.homeClub)
+            c->setHomeClub(true);
+        else
+            c->setHomeClub(false);
+    }
+}
+
 MainWindow::MainWindow(QMainWindow *parent): QMainWindow(parent)
 {
-  resize(800, 480);
+    resize(800, 480);
 
-  loadSettings();
+#ifdef Q_WS_MAEMO_5
+    setAttribute(Qt::WA_Maemo5StackedWindow);
+#endif
 
-  QWidget *centralWidget = new QWidget(this);
+    loadSettings();
 
-  setCentralWidget(centralWidget);
+    centralWidget = new QWidget(this);
 
-  loadScoreFile(scoreFile, scoreList);
-  loadClubFile(clubFile, clubList);
+    setCentralWidget(centralWidget);
 
-  // Sort the scores based on dates
-  qSort(scoreList.begin(), scoreList.end(), dateLessThan); 
+    loadScoreFile(scoreFile, scoreList);
+    if (conf.defaultCourses == "Yes")
+        loadClubFile(masterFile, clubList, true);
+    loadClubFile(clubFile, clubList);
+    markHomeClub();
+
+    // Sort the scores based on dates
+    qSort(scoreList.begin(), scoreList.end(), dateMoreThan); 
+    createActions();
+    createMenus();
 
-  createTableView(scoreList, clubList);
-  //createTreeView(scoreList, parent);
-  createStatusBar();
+    createListView(scoreList, clubList);
 
-  createLayout(centralWidget);
+    createLayoutList(centralWidget);
 
-  createActions();
-  createMenus();
+    scoreWindow = new ScoreWindow(this);
+    courseWindow = new CourseWindow(this);
 }
 
 void MainWindow::loadSettings(void)
 {
+    TRACE;
   bool external = false;
 
-#ifndef Q_WS_HILDON
-  topDir = ".";
-#endif
-
   QDir mmc(mmcDir);
   if (mmc.exists())
     external = true;
 
+  // TODO: make via user option, automatic will never work
+  external = false;
+
+#ifndef Q_WS_MAEMO_5
+  dataDir = "./" + dataDirName;
+#else
   if (external) {
-    dataDir = mmcDir + dataDirName;
+    dataDir = mmcDir + "/" + appName + "/" + dataDirName;
   }
   else {
-    dataDir = topDir + dataDirName;
+    dataDir = topDir + "/" + appName + "/" + dataDirName;
   }
-  scoreFile = dataDir + scoreFileName;
-  clubFile = dataDir + clubFileName;
+#endif
+  scoreFile = dataDir + "/" + scoreFileName;
+  clubFile = dataDir + "/" + clubFileName;
+  masterFile = dataDir + "/" + masterFileName;
 
   QDir dir(dataDir);
   if (!dir.exists())
-    if (!dir.mkdir(dataDir)) {
-      // TODO: mkdir does not work...
-      qDebug() << "Unable to create: " + dataDir;
+    if (!dir.mkpath(dataDir)) {
+      qWarning() << "Unable to create: " + dataDir;
       return;
     }
-  qDebug() << "Data is at: " + dataDir;
-}
+  qDebug() << "Data is at:" + dataDir;
 
-void MainWindow::createLayout(QWidget *parent)
-{
-  buttonLayout = new QVBoxLayout;
-  //labelLayout->addStretch();
-  buttonLayout->addWidget(nextButton);
-  buttonLayout->addWidget(prevButton);
-  buttonLayout->addWidget(lastButton);
-  buttonLayout->addWidget(firstButton);
+  settings.beginGroup(settingsGroup);
+  conf.hcp = settings.value(settingsHcp);
+  conf.homeClub = settings.value(settingsHomeClub);
+  conf.defaultCourses = settings.value(settingsDefaultCourses);
+  settings.endGroup();
 
-  tableLayout = new QVBoxLayout;
-  tableLayout->addWidget(table);
+  // Use default courses if no settings for that
+  if (!conf.defaultCourses.isValid())
+      conf.defaultCourses = "Yes";
 
-  QHBoxLayout *mainLayout = new QHBoxLayout(parent);
-  mainLayout->addLayout(tableLayout);
-  mainLayout->addLayout(buttonLayout);
-  setLayout(mainLayout);
+  qDebug() << "Settings: " << conf.hcp << conf.homeClub << conf.defaultCourses;
 }
 
-// Setup 'score' tab view
-void MainWindow::createTableView(QList<Score *> &scoreList, QList <Club *> &clubList)
+void MainWindow::saveSettings(void)
 {
-  table = new QTableView;
-
-  nextButton = new QPushButton(tr(">"));
-  prevButton = new QPushButton(tr("<"));
-  firstButton = new QPushButton(tr("<<"));
-  lastButton = new QPushButton(tr(">>"));
-
-  connect(nextButton, SIGNAL(clicked()), this, SLOT(nextButtonClicked()));
-  connect(prevButton, SIGNAL(clicked()), this, SLOT(prevButtonClicked()));
-  connect(firstButton, SIGNAL(clicked()), this, SLOT(firstButtonClicked()));
-  connect(lastButton, SIGNAL(clicked()), this, SLOT(lastButtonClicked()));
-
-  scoreTableModel = new ScoreTableModel();
-  scoreTableModel->setScore(scoreList);
-  scoreTableModel->setClub(clubList);
-
-  table->showGrid();
+    TRACE;
+    settings.beginGroup(settingsGroup);
+    if (conf.hcp.isValid())
+        settings.setValue(settingsHcp, conf.hcp);
+    if (conf.homeClub.isValid())
+        settings.setValue(settingsHomeClub, conf.homeClub);
+    if (conf.defaultCourses.isValid())
+        settings.setValue(settingsDefaultCourses, conf.defaultCourses);
+    settings.endGroup();
+}
 
-  table->setModel(scoreTableModel);
+void MainWindow::createLayoutList(QWidget *parent)
+{
+    TRACE;
+    QVBoxLayout * tableLayout = new QVBoxLayout;
+    tableLayout->addWidget(list);
 
-  // Fill out all the space with the tables
-  table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
-  table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
-  table->horizontalHeader()->hide();
+    QHBoxLayout *mainLayout = new QHBoxLayout(parent);
+    mainLayout->addLayout(tableLayout);
+    parent->setLayout(mainLayout);
 }
 
-// When selection down in 'stat' view, this is called.
-void MainWindow::updateTreeView(const QModelIndex & index)
+void MainWindow::createListView(QList<Score *> &scoreList, 
+                                QList <Club *> &clubList)
 {
-  QString scope("Scope");
-  QString count("Rounds");
-  QString scoreAvg("Score (avg.)");
-  QString scoreBest("Score (best)");
-  QString score("Total");
-  QString scoreIn("Total in");
-  QString scoreOut("Total out");
+    TRACE;
+    list = new QListView(this);
 
-  QVariant str = scoreTreeModel->data(index, Qt::DisplayRole);
-  QVariant type = scoreTreeModel->data(index, ScoreTreeModel::Type);
+    scoreListModel = new ScoreListModel(scoreList, clubList);
+    courseListModel = new CourseListModel(clubList);
 
-  qDebug() << "update(" << index.row() << "/" << index.column() << "):" << str << type;
+    list->setStyleSheet(defaultStyleSheet);
 
-  tableModel->setData(tableModel->index(0, 0, QModelIndex()), scope);
-  tableModel->setData(tableModel->index(0, 1, QModelIndex()), str);
+    list->setSelectionMode(QAbstractItemView::SingleSelection);
+    list->setProperty("FingerScrolling", true);
 
-  if (type == TreeItem::TypeDate) {
-    tableModel->setData(tableModel->index(1, 0, QModelIndex()), count);
-    tableModel->setData(tableModel->index(2, 0, QModelIndex()), scoreAvg);
-    tableModel->setData(tableModel->index(3, 0, QModelIndex()), scoreBest);
-  }    
-  else if (type == TreeItem::TypeScore) {
-    QVariant value = scoreTreeModel->data(index, ScoreTreeModel::Total);
-    tableModel->setData(tableModel->index(1, 0, QModelIndex()), score);
-    tableModel->setData(tableModel->index(1, 1, QModelIndex()), value);
+    // Initial view
+    listScores();
 
-    value = scoreTreeModel->data(index, ScoreTreeModel::TotalOut);
-    tableModel->setData(tableModel->index(2, 0, QModelIndex()), scoreOut);
-    tableModel->setData(tableModel->index(2, 1, QModelIndex()), value);
+    connect(list, SIGNAL(clicked(QModelIndex)),
+            this, SLOT(clickedList(QModelIndex)));
+}
 
-    value = scoreTreeModel->data(index, ScoreTreeModel::TotalIn);
-    tableModel->setData(tableModel->index(3, 0, QModelIndex()), scoreIn);
-    tableModel->setData(tableModel->index(3, 1, QModelIndex()), value);
-  }
+void MainWindow::listScores()
+{
+    TRACE;
+    list->setModel(scoreListModel);
+    selectionModel = list->selectionModel();
+    updateTitleBar(titleScores);
 }
 
-void MainWindow::createStatusBar()
+void MainWindow::listCourses()
 {
-  updateStatusBar();
+    TRACE;
+    list->setModel(courseListModel);
+    selectionModel = list->selectionModel();
+    updateTitleBar(titleCourses);
 }
 
 void MainWindow::createActions()
 {
-  newScoreAct = new QAction(tr("New Score"), this);
-  connect(newScoreAct, SIGNAL(triggered()), this, SLOT(newScore()));
+    TRACE;
+    newScoreAction = new QAction(tr("New Score"), this);
+    connect(newScoreAction, SIGNAL(triggered()), this, SLOT(newScore()));
 
-  newCourseAct = new QAction(tr("New Course"), this);
-  connect(newCourseAct, SIGNAL(triggered()), this, SLOT(newCourse()));
+    newCourseAction = new QAction(tr("New Course"), this);
+    connect(newCourseAction, SIGNAL(triggered()), this, SLOT(newCourse()));
 
-  editScoreAct = new QAction(tr("Edit Score"), this);
-  connect(editScoreAct, SIGNAL(triggered()), this, SLOT(editScore()));
+    statAction = new QAction(tr("Statistics"), this);
+    connect(statAction, SIGNAL(triggered()), this, SLOT(viewStatistics()));
 
-  editCourseAct = new QAction(tr("Edit Course"), this);
-  connect(editCourseAct, SIGNAL(triggered()), this, SLOT(editCourse()));
+    settingsAction = new QAction(tr("Settings"), this);
+    connect(settingsAction, SIGNAL(triggered()), this, SLOT(viewSettings()));
 
-#if 0
-  viewScoreAct = new QAction(tr("&View Scores"), this);
-  connect(viewScoreAct, SIGNAL(triggered()), this, SLOT(viewScore()));
+    // Maemo5 style menu filters
+    filterGroup = new QActionGroup(this);
+    filterGroup->setExclusive(true);
 
-  viewCourseAct = new QAction(tr("&View Courses"), this);
-  connect(viewCourseAct, SIGNAL(triggered()), this, SLOT(viewCourse()));
+    listScoreAction = new QAction(tr("Scores"), filterGroup);
+    listScoreAction->setCheckable(true);
+    listScoreAction->setChecked(true);
+    connect(listScoreAction, SIGNAL(triggered()), this, SLOT(listScores()));
 
-  viewStatisticAct = new QAction(tr("&View Statistics"), this);
-  connect(viewStatisticAct, SIGNAL(triggered()), this, SLOT(viewStatistic()));
-#endif
+    listCourseAction = new QAction(tr("Courses"), filterGroup);
+    listCourseAction->setCheckable(true);
+    connect(listCourseAction, SIGNAL(triggered()), this, SLOT(listCourses()));
 }
 
 void MainWindow::createMenus()
 {
-  menu = menuBar()->addMenu(tr("fremantle"));
-#if 0
-  menu->addAction(viewScoreAct);
-  menu->addAction(viewCourseAct);
-  menu->addAction(viewStatisticAct);
+    TRACE;
+#ifdef Q_WS_MAEMO_5
+    menu = menuBar()->addMenu("");
+#else
+    menu = menuBar()->addMenu("Menu");
 #endif
-  menu->addAction(newScoreAct);
-  menu->addAction(newCourseAct);
-  menu->addAction(editScoreAct);
-  menu->addAction(editCourseAct);
-}
 
-void MainWindow::updateStatusBar()
-{
-  setWindowTitle(scoreTableModel->getInfoText());
+    menu->addAction(newScoreAction);
+    menu->addAction(newCourseAction);
+    menu->addAction(statAction);
+    menu->addAction(settingsAction);
+    menu->addActions(filterGroup->actions());
 }
 
-void MainWindow::firstButtonClicked()
+void MainWindow::updateTitleBar(QString & msg)
 {
-  scoreTableModel->first();
-  updateStatusBar();
+    TRACE;
+    setWindowTitle(msg);
 }
 
-void MainWindow::lastButtonClicked()
+void MainWindow::showNote(QString msg)
 {
-  scoreTableModel->last();
-  updateStatusBar();
+#ifdef Q_WS_MAEMO_5
+    QMaemo5InformationBox::information(this, 
+                                       msg,
+                                       QMaemo5InformationBox::DefaultTimeout);
+#endif
 }
 
-void MainWindow::nextButtonClicked()
+void MainWindow::clickedList(const QModelIndex &index)
 {
-  scoreTableModel->next();
-  updateStatusBar();
+    TRACE;
+    int row = index.row();
+
+    const QAbstractItemModel *m = index.model();
+    if (m == scoreListModel) {
+        if (row < scoreList.count()) {
+            Score * score = scoreList.at(row);
+            Course * course = findCourse(score->getClubName(), score->getCourseName());
+            viewScore(score, course);
+        }
+    }
+    else if (m == courseListModel) {
+        QString str = courseListModel->data(index, Qt::DisplayRole).toString();
+        QStringList strList = str.split(", ");
+
+        if (strList.count() != 2) {
+            showNote(QString("Invalid course selection"));
+            return;
+        }
+        Course * course = findCourse(strList.at(0), strList.at(1));
+        viewCourse(course);
+    }
 }
 
-void MainWindow::prevButtonClicked()
+void MainWindow::viewScore(Score * score, Course * course)
 {
-  scoreTableModel->prev();
-  updateStatusBar();
+    TRACE;
+    qDebug() << score << course;
+    scoreWindow->setup(score, course);
+    scoreWindow->show();
 }
 
-// FIXME: dup code from table-model.cpp
-Club *MainWindow::findClub(QString &name)
+void MainWindow::newScore()
 {
-  QListIterator<Club *> i(clubList);
-  Club *c;
+    TRACE;
+    SelectDialog *selectDialog = new SelectDialog(this);
 
-  while (i.hasNext()) {
-    c = i.next();
-    if (c->getName() == name)
-      return c;
-  }
-  return 0;
+    selectDialog->init(clubList);
+
+    int result = selectDialog->exec();
+    if (result) {
+        QString clubName;
+        QString courseName;
+        QString date;
+
+        selectDialog->results(clubName, courseName, date);
+
+        ScoreDialog *scoreDialog = new ScoreDialog(this);
+        QString title = "New Score: " + courseName + ", " + date;
+        scoreDialog->setWindowTitle(title);
+
+        Club *club = findClub(clubName);
+        if (!club) {
+            showNote(tr("Error: no such club"));
+            return;
+        }
+        Course *course = club->getCourse(courseName);
+        if (!course) {
+            showNote(tr("Error: no such course:"));
+            return;
+        }
+        scoreDialog->init(course);
+        result = scoreDialog->exec();
+        if (result) {
+            QVector<QString> scores(18);
+
+            scoreDialog->results(scores);
+            Score *score = new Score(scores, clubName, courseName, date);
+            scoreList << score;
+
+            // Sort the scores based on dates
+            qSort(scoreList.begin(), scoreList.end(), dateMoreThan); 
+            // Save it
+            saveScoreFile(scoreFile, scoreList);
+            scoreListModel->update(scoreList);
+            list->update();
+        }
+    }
 }
 
-void MainWindow::newCourse()
+void MainWindow::editScore()
 {
-  CourseSelectDialog *selectDialog = new CourseSelectDialog(this);
+    TRACE;
+    Course * course = 0;
+    Score *score = currentScore();
 
-  int result = selectDialog->exec();
-  if (result) {
-    QString clubName;
-    QString courseName;
-    QString date;
+    if (score) 
+        course = findCourse(score->getClubName(), score->getCourseName());
 
-    selectDialog->results(clubName, courseName);
+    if (!course || !score) {
+        qDebug() << "No score/course to edit";
+        return;
+    }
 
-    CourseDialog *courseDialog = new CourseDialog(this);
-    courseDialog->init();
+    QString date = score->getDate();
 
-    QString title = "New Course: " + clubName + "," + courseName;
-    courseDialog->setWindowTitle(title);
+    ScoreDialog *scoreDialog = new ScoreDialog(this);
+    scoreDialog->init(course, score);
+  
+    QString title = "Edit Score: " + course->getName() + ", " + date;
+    scoreDialog->setWindowTitle(title);
 
-    int result = courseDialog->exec();
+    int result = scoreDialog->exec();
     if (result) {
-      QVector<QString> par(18);
-      QVector<QString> hcp(18);
-      QVector<QString> len(18);
-
-      courseDialog->results(par, hcp, len);
-
-      Course *course = 0;
-      Club *club = findClub(clubName);
-      if (club) {
-       course = club->getCourse(courseName);
-       if (course) {
-         qDebug() << "Error: club/course already in the database";
-         return;
-       }
-       else {
-         course = new Course(courseName, par, hcp);
-         club->addCourse(course);
-       }
-      }
-      else {
-       club = new Club(clubName);
-       course = new Course(courseName, par, hcp);
-       club->addCourse(course);
-       clubList << club;
-      }
-      saveClubFile(clubFile, clubList);
-
-      // TODO: does this really work? No mem leaks?
-      scoreTableModel->setClub(clubList);
+        QVector<QString> scores(18);
+
+        scoreDialog->results(scores);
+    
+        score->update(scores);
 
+        // Sort the scores based on dates
+        qSort(scoreList.begin(), scoreList.end(), dateMoreThan); 
+        // Save it
+        saveScoreFile(scoreFile, scoreList);
     }
-  }
+    if (scoreDialog)
+        delete scoreDialog;
 }
 
-void MainWindow::editCourse()
+void MainWindow::deleteScore()
 {
-  Course *course = scoreTableModel->getCourse();
-
-  CourseDialog *courseDialog = new CourseDialog(this);
-  courseDialog->init(course);
-
-  QString title = "Edit Course: " + course->getName();
-  courseDialog->setWindowTitle(title);
-  
-  int result = courseDialog->exec();
-  if (result) {
-    QVector<QString> par(18);
-    QVector<QString> hcp(18);
-    QVector<QString> len(18);
-    
-    courseDialog->results(par, hcp, len);
+    TRACE;
+    if (scoreWindow)
+        scoreWindow->close();
+
+    QModelIndex index = selectionModel->currentIndex();
+    if (!index.isValid()) {
+        qDebug() << "Invalid index";
+        return;
+    }
     
-    course->update(par, hcp, len);
-    saveClubFile(clubFile, clubList);
-  }
+    scoreList.removeAt(index.row());
+    // Save it
+    saveScoreFile(scoreFile, scoreList);
+    scoreListModel->update(scoreList);
+    list->update();
 }
 
-void MainWindow::newScore()
+void MainWindow::viewCourse(Course * course)
 {
-  SelectDialog *selectDialog = new SelectDialog(this);
+    TRACE;
+    courseWindow->setup(course);
+    courseWindow->show();
+}
 
-  selectDialog->init(clubList);
+void MainWindow::newCourse()
+{
+    TRACE;
+    CourseSelectDialog *selectDialog = new CourseSelectDialog(this);
 
-  int result = selectDialog->exec();
-  if (result) {
-    QString clubName;
-    QString courseName;
-    QString date;
+    int result = selectDialog->exec();
+    if (result) {
+        QString clubName;
+        QString courseName;
+        QString date;
+
+        selectDialog->results(clubName, courseName);
+
+        CourseDialog *courseDialog = new CourseDialog(this);
+        courseDialog->init();
+        QString title = "New Course: " + clubName + "," + courseName;
+        courseDialog->setWindowTitle(title);
+
+        int result = courseDialog->exec();
+        if (result) {
+            QVector<QString> par(18);
+            QVector<QString> hcp(18);
+            QVector<QString> len(18);
+
+            courseDialog->results(par, hcp, len);
+
+            Course *course = 0;
+            Club *club = findClub(clubName);
+            if (club) {
+                course = club->getCourse(courseName);
+                if (course) {
+                    showNote(tr("Club/course already in the database"));
+                    return;
+                }
+                else {
+                    course = new Course(courseName, par, hcp);
+                    club->addCourse(course);
+                }
+            }
+            else {
+                // New club and course
+                club = new Club(clubName);
+                course = new Course(courseName, par, hcp);
+                club->addCourse(course);
+                clubList << club;
+            }
+            // Save it
+            saveClubFile(clubFile, clubList);
+            courseListModel->update(clubList);
+            list->update();
+        }
+    }
+}
 
-    selectDialog->results(clubName, courseName, date);
+void MainWindow::editCourse()
+{
+    TRACE;
+    Course *course = currentCourse();
 
-    ScoreDialog *scoreDialog = new ScoreDialog(this);
-    QString title = "New Score: " + courseName + ", " + date;
-    scoreDialog->setWindowTitle(title);
+    if (!course) {
+        showNote(tr("No course on edit"));
+        return;
+    }
 
-    Club *club = findClub(clubName);
-    if (!club) {
-      qDebug() << "Error: no such club: " << clubName;
-      return;
+    CourseDialog *courseDialog = new CourseDialog(this);
+    courseDialog->init(course);
+
+    QString title = "Edit Course: " + course->getName();
+    courseDialog->setWindowTitle(title);
+  
+    int result = courseDialog->exec();
+    if (result) {
+        QVector<QString> par(18);
+        QVector<QString> hcp(18);
+        QVector<QString> len(18);
+    
+        courseDialog->results(par, hcp, len);
+    
+        course->update(par, hcp, len);
+        saveClubFile(clubFile, clubList);
     }
-    Course *course = club->getCourse(courseName);
+    if (courseDialog)
+        delete courseDialog;
+}
+
+void MainWindow::deleteCourse()
+{
+    TRACE;
+    Club *club = 0;
+    Course * course = currentCourse();
+
     if (!course) {
-      qDebug() << "Error: no such course: " << courseName;
-      return;
+        qDebug() << "Invalid course for deletion";
+        return;
     }
-    scoreDialog->init(course);
-    result = scoreDialog->exec();
-    if (result) {
-      QVector<QString> scores(18);
+    club = course->parent();
 
-      scoreDialog->results(scores);
-      Score *score = new Score(scores, clubName, courseName, date);
-      scoreList << score;
+    // Can not delete course if it has scores -- check
+    if (findScore(club->getName(), course->getName()) != 0) {
+        showNote(tr("Can not delete course, delete scores on the course first"));
+        return;
+    }
+    // Close the window
+    if (courseWindow)
+        courseWindow->close();
 
-      // Sort the scores based on dates
-      qSort(scoreList.begin(), scoreList.end(), dateLessThan); 
-      // Save it
-      saveScoreFile(scoreFile, scoreList);
+    club->delCourse(course);
 
-      // TODO: does this really work? No mem leaks?
-      scoreTableModel->setScore(scoreList, score);
-      updateStatusBar();
+    if (club->isEmpty()) {
+        int index = clubList.indexOf(club);
+        if (index != -1)
+            clubList.removeAt(index);
     }
-  }
+
+    // Save it
+    saveClubFile(clubFile, clubList);
+    courseListModel->update(clubList);
+    list->update();
 }
 
-void MainWindow::editScore()
+void MainWindow::viewStatistics()
 {
-  Course *course = scoreTableModel->getCourse();
-  Score *score = scoreTableModel->getScore();
-  QString date = score->getDate();
+    TRACE;
+    QMainWindow *win = new QMainWindow(this);
+    QString title = "Statistics";
+    win->setWindowTitle(title);
+#ifdef Q_WS_MAEMO_5
+    win->setAttribute(Qt::WA_Maemo5StackedWindow);
+#endif
 
-  ScoreDialog *scoreDialog = new ScoreDialog(this);
-  
-  QString title = "Edit Score: " + course->getName() + ", " + date;
-  scoreDialog->setWindowTitle(title);
+    StatModel *model = new StatModel(clubList, scoreList);
 
-  scoreDialog->init(course, score);
+    QTableView *table = new QTableView;
+    table->showGrid();
+    table->setSelectionMode(QAbstractItemView::NoSelection);
+    table->setStyleSheet(statStyleSheet);
+    table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
+    table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
+    table->verticalHeader()->setAutoFillBackground(true);
+    table->setModel(model);
 
-  int result = scoreDialog->exec();
+    QWidget *central = new QWidget(win);
+    win->setCentralWidget(central);
 
-  if (result) {
-    QVector<QString> scores(18);
+    QTextEdit *textEdit = new QTextEdit;
 
-    scoreDialog->results(scores);
-    
-    score->update(scores);
+    textEdit->setReadOnly(true);
 
-    // Sort the scores based on dates
-    qSort(scoreList.begin(), scoreList.end(), dateLessThan); 
-    // Save it
-    saveScoreFile(scoreFile, scoreList);
+    QVBoxLayout *infoLayout = new QVBoxLayout;
+    infoLayout->addWidget(table);
 
-    // TODO: does this really work? No mem leaks?
-    scoreTableModel->setScore(scoreList, score);
-    updateStatusBar();
-  }
+    QHBoxLayout *mainLayout = new QHBoxLayout(central);
+    mainLayout->addLayout(infoLayout);
+    central->setLayout(mainLayout);
+
+    win->show();
+}
+
+void MainWindow::viewSettings()
+{
+    TRACE;
+    SettingsDialog *dlg = new SettingsDialog(this);
+
+    dlg->init(conf, clubList);
+
+    int result = dlg->exec();
+    if (result) {
+        QString oldValue = conf.defaultCourses.toString();
+        dlg->results(conf);
+        QString newValue = conf.defaultCourses.toString();
+        saveSettings();
+
+        // Reload club list, or drop r/o courses from list
+        if (oldValue == "Yes" && newValue == "No") {
+            flushReadOnlyItems();
+            courseListModel->update(clubList);
+            list->update();
+        }
+        else if ((oldValue == "No" || oldValue == "") && newValue == "Yes") {
+            loadClubFile(masterFile, clubList, true);
+            courseListModel->update(clubList);
+            list->update();
+        }
+        markHomeClub();
+    }
 }
 
 void MainWindow::loadScoreFile(QString &fileName, QList<Score *> &list)
@@ -423,7 +696,7 @@ void MainWindow::loadScoreFile(QString &fileName, QList<Score *> &list)
   ScoreXmlHandler handler(list);
 
   if (handler.parse(fileName))
-    qDebug() << "File loaded: " << fileName << " entries: " << list.size();
+    qDebug() << "File loaded:" << fileName << " entries:" << list.size();
 }
 
 void MainWindow::saveScoreFile(QString &fileName, QList<Score *> &list)
@@ -432,17 +705,17 @@ void MainWindow::saveScoreFile(QString &fileName, QList<Score *> &list)
 
   if (handler.save(fileName))
     // TODO: banner
-    qDebug() << "File saved: " << fileName << " entries: " << list.size();
+    qDebug() << "File saved:" << fileName << " entries:" << list.size();
   else
-    qDebug() << "Unable to save: " << fileName;
+    qWarning() << "Unable to save:" << fileName;
 }
 
-void MainWindow::loadClubFile(QString &fileName, QList<Club *> &list)
+void MainWindow::loadClubFile(QString &fileName, QList<Club *> &list, bool readOnly)
 {
-  ClubXmlHandler handler(list);
+    ClubXmlHandler handler(list);
 
-  if (handler.parse(fileName))
-    qDebug() << "File loaded: " << fileName << " entries: " << list.size();
+    if (handler.parse(fileName, readOnly))
+        qDebug() << "File loaded:" << fileName << " entries:" << list.size();
 }
 
 void MainWindow::saveClubFile(QString &fileName, QList<Club *> &list)
@@ -451,8 +724,8 @@ void MainWindow::saveClubFile(QString &fileName, QList<Club *> &list)
 
   if (handler.save(fileName))
     // TODO: banner
-    qDebug() << "File saved: " << fileName << " entries: " << list.size();
+    qDebug() << "File saved:" << fileName << " entries:" << list.size();
   else
-    qDebug() << "Unable to save: " << fileName;
+    qWarning() << "Unable to save:" << fileName;
 
 }