2 * Copyright (C) 2009 Sakari Poussa
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 2.
11 #include <QMaemo5InformationBox>
14 #include "score-common.h"
15 #include "main-window.h"
16 #include "score-dialog.h"
17 #include "course-dialog.h"
18 #include "stat-model.h"
19 #include "xml-dom-parser.h"
21 QString appName("scorecard");
22 QString topDir("/opt");
23 QString mmcDir("/media/mmc1");
24 QString dataDirName("data");
26 QString imgDir(topDir + "/pixmaps");
27 QString scoreFileName("score.xml");
29 QString clubFileName("club.xml");
31 QString logFile("/tmp/scorecard.log");
33 bool dateLessThan(const Score *s1, const Score *s2)
38 bool dateMoreThan(const Score *s1, const Score *s2)
42 // Find score based on club and course name
43 Score *MainWindow::findScore(QString & clubName, QString & courseName)
45 QListIterator<Score *> i(scoreList);
50 if ((s->getClubName() == clubName) &&
51 (s->getCourseName() == courseName))
57 // Find club based on name
58 Club *MainWindow::findClub(QString &name)
60 QListIterator<Club *> i(clubList);
65 if (c->getName() == name)
71 // Find course based on club & course name
72 Course *MainWindow::findCourse(const QString &clubName,
73 const QString &courseName)
75 QListIterator<Club *> i(clubList);
80 if (c->getName() == clubName) {
81 return c->getCourse(courseName);
87 // Find course based on current selection on the list
88 Course *MainWindow::findCourse()
90 QModelIndex index = selectionModel->currentIndex();
91 const QAbstractItemModel *model = selectionModel->model();
92 QString str = model->data(index, Qt::DisplayRole).toString();
94 QStringList strList = str.split(",");
95 if (strList.count() != 2) {
96 showNote(tr("Invalid course selection"));
99 return findCourse(strList[0], strList[1]);
102 MainWindow::MainWindow(QMainWindow *parent): QMainWindow(parent)
107 setAttribute(Qt::WA_Maemo5StackedWindow);
112 centralWidget = new QWidget(this);
114 setCentralWidget(centralWidget);
116 loadScoreFile(scoreFile, scoreList);
117 loadClubFile(clubFile, clubList);
119 // Sort the scores based on dates
120 qSort(scoreList.begin(), scoreList.end(), dateMoreThan);
124 createListView(scoreList, clubList);
127 createLayoutList(centralWidget);
130 void MainWindow::loadSettings(void)
132 bool external = false;
138 // TODO: make via user option, automatic will never work
142 dataDir = "./" + dataDirName;
145 dataDir = mmcDir + "/" + appName + "/" + dataDirName;
148 dataDir = topDir + "/" + appName + "/" + dataDirName;
151 scoreFile = dataDir + "/" + scoreFileName;
152 clubFile = dataDir + "/" + clubFileName;
156 if (!dir.mkpath(dataDir)) {
157 qWarning() << "Unable to create: " + dataDir;
160 qDebug() << "Data is at:" + dataDir;
163 void MainWindow::createLayoutList(QWidget *parent)
165 QVBoxLayout * tableLayout = new QVBoxLayout;
166 tableLayout->addWidget(list);
168 QHBoxLayout *mainLayout = new QHBoxLayout(parent);
169 mainLayout->addLayout(tableLayout);
170 parent->setLayout(mainLayout);
173 void MainWindow::createListView(QList<Score *> &scoreList,
174 QList <Club *> &clubList)
176 list = new QListView;
178 scoreListModel = new ScoreListModel(scoreList, clubList);
179 courseListModel = new CourseListModel(clubList);
181 list->setStyleSheet(ScoreStyle::style());
183 list->setSelectionMode(QAbstractItemView::SingleSelection);
189 void MainWindow::listScores()
191 list->setModel(scoreListModel);
192 selectionModel = list->selectionModel();
193 connect(selectionModel, SIGNAL(selectionChanged (const QItemSelection &, const QItemSelection &)),
194 this, SLOT(scoreSelectionChanged(const QItemSelection &, const QItemSelection &)));
197 void MainWindow::listCourses()
199 list->setModel(courseListModel);
200 selectionModel = list->selectionModel();
201 connect(selectionModel, SIGNAL(selectionChanged (const QItemSelection &, const QItemSelection &)),
202 this, SLOT(courseSelectionChanged(const QItemSelection &, const QItemSelection &)));
205 void MainWindow::createActions()
207 newScoreAction = new QAction(tr("New Score"), this);
208 connect(newScoreAction, SIGNAL(triggered()), this, SLOT(newScore()));
210 newCourseAction = new QAction(tr("New Course"), this);
211 connect(newCourseAction, SIGNAL(triggered()), this, SLOT(newCourse()));
213 statAction = new QAction(tr("Statistics"), this);
214 connect(statAction, SIGNAL(triggered()), this, SLOT(viewStatistics()));
216 // Maemo5 style menu filters
217 filterGroup = new QActionGroup(this);
218 filterGroup->setExclusive(true);
220 listScoreAction = new QAction(tr("Scores"), filterGroup);
221 listScoreAction->setCheckable(true);
222 listScoreAction->setChecked(true);
223 connect(listScoreAction, SIGNAL(triggered()), this, SLOT(listScores()));
225 listCourseAction = new QAction(tr("Courses"), filterGroup);
226 listCourseAction->setCheckable(true);
227 connect(listCourseAction, SIGNAL(triggered()), this, SLOT(listCourses()));
230 void MainWindow::createMenus()
233 menu = menuBar()->addMenu("");
235 menu = menuBar()->addMenu("Menu");
238 menu->addAction(newScoreAction);
239 menu->addAction(newCourseAction);
240 menu->addAction(statAction);
241 menu->addActions(filterGroup->actions());
244 void MainWindow::updateTitleBar()
246 QString title("ScoreCard");
247 setWindowTitle(title);
250 void MainWindow::showNote(QString msg)
253 QMaemo5InformationBox::information(this,
255 QMaemo5InformationBox::DefaultTimeout);
259 void MainWindow::scoreSelectionChanged(const QItemSelection &selected,
260 const QItemSelection &deselected)
262 QModelIndexList list = selected.indexes();
264 int row = list.at(0).row();
266 Score * score = scoreList.at(row);
267 Course * course = findCourse(score->getClubName(), score->getCourseName());
268 viewScore(score, course);
271 void MainWindow::courseSelectionChanged(const QItemSelection &selected,
272 const QItemSelection &deselected)
274 QModelIndexList indexes = selected.indexes();
276 int row = indexes.at(0).row();
278 QString str = courseListModel->data(indexes.at(0), Qt::DisplayRole).toString();
280 QStringList strList = str.split(",");
282 if (strList.count() != 2) {
283 showNote(QString("Invalid course selection"));
286 Course * course = findCourse(strList.at(0), strList.at(1));
290 void MainWindow::changeCurrent(const QModelIndex ¤t,
291 const QModelIndex &previous)
293 qDebug() << "Current: " << current;
296 void MainWindow::newCourse()
298 CourseSelectDialog *selectDialog = new CourseSelectDialog(this);
300 int result = selectDialog->exec();
306 selectDialog->results(clubName, courseName);
308 CourseDialog *courseDialog = new CourseDialog(this);
309 courseDialog->init();
310 QString title = "New Course: " + clubName + "," + courseName;
311 courseDialog->setWindowTitle(title);
313 int result = courseDialog->exec();
315 QVector<QString> par(18);
316 QVector<QString> hcp(18);
317 QVector<QString> len(18);
319 courseDialog->results(par, hcp, len);
322 Club *club = findClub(clubName);
324 course = club->getCourse(courseName);
326 qDebug() << "Error: club/course already in the database";
330 course = new Course(courseName, par, hcp);
331 club->addCourse(course);
335 // New club and course
336 club = new Club(clubName);
337 course = new Course(courseName, par, hcp);
338 club->addCourse(course);
342 saveClubFile(clubFile, clubList);
343 // TODO: update on live
344 //courseListModel->update(courseList);
350 void MainWindow::deleteCourse()
352 Course * course = findCourse();
353 Club * club = course->parent();
355 // Can not delete course if it has scores -- check
356 if (findScore(club->getName(), course->getName()) != 0) {
357 showNote(tr("Can not delete course, delete scores on the course first"));
364 club->delCourse(course);
366 if (club->isEmpty()) {
367 int index = clubList.indexOf(club);
369 clubList.removeAt(index);
373 saveClubFile(clubFile, clubList);
374 courseListModel->update(clubList);
378 void MainWindow::editCourse()
380 Course *course = findCourse();
383 showNote(tr("No course on edit"));
387 CourseDialog *courseDialog = new CourseDialog(this);
388 courseDialog->init(course);
390 QString title = "Edit Course: " + course->getName();
391 courseDialog->setWindowTitle(title);
393 int result = courseDialog->exec();
395 QVector<QString> par(18);
396 QVector<QString> hcp(18);
397 QVector<QString> len(18);
399 courseDialog->results(par, hcp, len);
401 course->update(par, hcp, len);
402 saveClubFile(clubFile, clubList);
406 void MainWindow::newScore()
408 SelectDialog *selectDialog = new SelectDialog(this);
410 selectDialog->init(clubList);
412 int result = selectDialog->exec();
418 selectDialog->results(clubName, courseName, date);
420 ScoreDialog *scoreDialog = new ScoreDialog(this);
421 QString title = "New Score: " + courseName + ", " + date;
422 scoreDialog->setWindowTitle(title);
424 Club *club = findClub(clubName);
426 showNote(tr("Error: no such club"));
429 Course *course = club->getCourse(courseName);
431 showNote(tr("Error: no such course:"));
434 scoreDialog->init(course);
435 result = scoreDialog->exec();
437 QVector<QString> scores(18);
439 scoreDialog->results(scores);
440 Score *score = new Score(scores, clubName, courseName, date);
443 // Sort the scores based on dates
444 qSort(scoreList.begin(), scoreList.end(), dateMoreThan);
446 saveScoreFile(scoreFile, scoreList);
447 scoreListModel->update(scoreList);
453 void MainWindow::deleteScore()
458 QModelIndex index = selectionModel->currentIndex();
459 scoreList.removeAt(index.row());
461 saveScoreFile(scoreFile, scoreList);
462 scoreListModel->update(scoreList);
466 void MainWindow::editScore()
468 QModelIndex index = selectionModel->currentIndex();
469 Score * score = scoreList.at(index.row());
472 course = findCourse(score->getClubName(), score->getCourseName());
474 if (!course || !score) {
475 qDebug() << "No score/course to edit";
479 QString date = score->getDate();
481 ScoreDialog *scoreDialog = new ScoreDialog;
483 QString title = "Edit Score: " + course->getName() + ", " + date;
484 scoreDialog->setWindowTitle(title);
486 scoreDialog->init(course, score);
488 int result = scoreDialog->exec();
491 QVector<QString> scores(18);
493 scoreDialog->results(scores);
495 score->update(scores);
497 // Sort the scores based on dates
498 qSort(scoreList.begin(), scoreList.end(), dateMoreThan);
500 saveScoreFile(scoreFile, scoreList);
502 scoreListModel->update(scoreList);
506 void MainWindow::viewScore(Score * score,
509 scoreWin = new QMainWindow(this);
510 QString title = QString("Score: %1, %2 - %3").arg(score->getClubName()).arg(score->getCourseName()).arg(score->getDate());
511 scoreWin->setWindowTitle(title);
513 scoreWin->setAttribute(Qt::WA_Maemo5StackedWindow);
516 QAction *editAction = new QAction(tr("Edit"), scoreWin);
517 connect(editAction, SIGNAL(triggered()), this, SLOT(editScore()));
518 scoreWin->menuBar()->addAction(editAction);
520 QAction *delAction = new QAction(tr("Delete"), scoreWin);
521 connect(delAction, SIGNAL(triggered()), this, SLOT(deleteScore()));
522 scoreWin->menuBar()->addAction(delAction);
524 ScoreTableModel *model = new ScoreTableModel(score, course);
526 QTableView * table = new QTableView;
528 table->setSelectionMode(QAbstractItemView::NoSelection);
529 //table->setStyleSheet(ScoreStyle::headerView());
530 table->setStyleSheet(ScoreStyle::style());
531 table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
532 table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
533 table->horizontalHeader()->hide();
534 table->setModel(model);
536 QWidget *central = new QWidget(scoreWin);
537 scoreWin->setCentralWidget(central);
539 QVBoxLayout *layout = new QVBoxLayout;
540 layout->addWidget(table);
542 central->setLayout(layout);
546 void MainWindow::viewCourse(Course * course)
548 courseWin = new QMainWindow(this);
549 QString title = QString("Course: %1, Par - %2").arg(course->getName()).arg(course->getTotal(Total));
550 courseWin->setWindowTitle(title);
552 courseWin->setAttribute(Qt::WA_Maemo5StackedWindow);
555 QAction *editAction = new QAction(tr("Edit"), courseWin);
556 connect(editAction, SIGNAL(triggered()), this, SLOT(editCourse()));
557 courseWin->menuBar()->addAction(editAction);
559 QAction *delAction = new QAction(tr("Delete"), courseWin);
560 connect(delAction, SIGNAL(triggered()), this, SLOT(deleteCourse()));
561 courseWin->menuBar()->addAction(delAction);
563 CourseTableModel *model = new CourseTableModel(course);
565 QTableView * table = new QTableView;
567 table->setSelectionMode(QAbstractItemView::NoSelection);
568 //table->setStyleSheet(ScoreStyle::headerView());
569 table->setStyleSheet(ScoreStyle::style());
570 table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
571 table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
572 table->horizontalHeader()->hide();
573 table->setModel(model);
575 QWidget *central = new QWidget(courseWin);
576 courseWin->setCentralWidget(central);
578 QVBoxLayout *layout = new QVBoxLayout;
579 layout->addWidget(table);
581 central->setLayout(layout);
585 void MainWindow::viewStatistics()
587 QMainWindow *win = new QMainWindow(this);
588 QString title = "Statistics";
589 win->setWindowTitle(title);
591 win->setAttribute(Qt::WA_Maemo5StackedWindow);
594 StatModel *model = new StatModel(clubList, scoreList);
596 QTableView *table = new QTableView;
598 table->setSelectionMode(QAbstractItemView::NoSelection);
599 table->setStyleSheet(ScoreStyle::headerView());
600 table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
601 table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
602 table->verticalHeader()->setAutoFillBackground(true);
603 table->setModel(model);
605 QWidget *central = new QWidget(win);
606 win->setCentralWidget(central);
608 QTextEdit *textEdit = new QTextEdit;
610 textEdit->setReadOnly(true);
612 QVBoxLayout *infoLayout = new QVBoxLayout;
613 infoLayout->addWidget(table);
615 QHBoxLayout *mainLayout = new QHBoxLayout(central);
616 mainLayout->addLayout(infoLayout);
617 central->setLayout(mainLayout);
622 void MainWindow::loadScoreFile(QString &fileName, QList<Score *> &list)
624 ScoreXmlHandler handler(list);
626 if (handler.parse(fileName))
627 qDebug() << "File loaded:" << fileName << " entries:" << list.size();
630 void MainWindow::saveScoreFile(QString &fileName, QList<Score *> &list)
632 ScoreXmlHandler handler(list);
634 if (handler.save(fileName))
636 qDebug() << "File saved:" << fileName << " entries:" << list.size();
638 qWarning() << "Unable to save:" << fileName;
641 void MainWindow::loadClubFile(QString &fileName, QList<Club *> &list)
643 ClubXmlHandler handler(list);
645 if (handler.parse(fileName))
646 qDebug() << "File loaded:" << fileName << " entries:" << list.size();
649 void MainWindow::saveClubFile(QString &fileName, QList<Club *> &list)
651 ClubXmlHandler handler(list);
653 if (handler.save(fileName))
655 qDebug() << "File saved:" << fileName << " entries:" << list.size();
657 qWarning() << "Unable to save:" << fileName;