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 masterFileName("club-master.xml");
33 QString logFile("/tmp/scorecard.log");
34 QString titleScores("ScoreCard - Scores");
35 QString titleCourses("ScoreCard - Courses");
37 bool dateLessThan(const Score *s1, const Score *s2)
42 bool dateMoreThan(const Score *s1, const Score *s2)
46 // Find score based on club and course name
47 Score *MainWindow::findScore(QString & clubName, QString & courseName)
49 QListIterator<Score *> i(scoreList);
54 if ((s->getClubName() == clubName) &&
55 (s->getCourseName() == courseName))
61 // Find club based on name
62 Club *MainWindow::findClub(QString &name)
64 QListIterator<Club *> i(clubList);
69 if (c->getName() == name)
75 // Find course based on club & course name
76 Course *MainWindow::findCourse(const QString &clubName,
77 const QString &courseName)
79 QListIterator<Club *> i(clubList);
84 if (c->getName() == clubName) {
85 return c->getCourse(courseName);
91 // Find course based on current selection on the list
92 // TODO: make sure this is only called when course list is the model...
93 Course *MainWindow::findCourse()
95 QModelIndex index = selectionModel->currentIndex();
96 const QAbstractItemModel *model = selectionModel->model();
97 QString str = model->data(index, Qt::DisplayRole).toString();
99 QStringList strList = str.split(",");
100 if (strList.count() != 2) {
101 showNote(tr("Invalid course selection"));
104 return findCourse(strList[0], strList[1]);
107 MainWindow::MainWindow(QMainWindow *parent): QMainWindow(parent)
112 setAttribute(Qt::WA_Maemo5StackedWindow);
117 centralWidget = new QWidget(this);
119 setCentralWidget(centralWidget);
121 loadScoreFile(scoreFile, scoreList);
122 loadClubFile(masterFile, clubList, true);
123 loadClubFile(clubFile, clubList);
125 // Sort the scores based on dates
126 qSort(scoreList.begin(), scoreList.end(), dateMoreThan);
130 createListView(scoreList, clubList);
132 createLayoutList(centralWidget);
135 void MainWindow::loadSettings(void)
137 bool external = false;
143 // TODO: make via user option, automatic will never work
147 dataDir = "./" + dataDirName;
150 dataDir = mmcDir + "/" + appName + "/" + dataDirName;
153 dataDir = topDir + "/" + appName + "/" + dataDirName;
156 scoreFile = dataDir + "/" + scoreFileName;
157 clubFile = dataDir + "/" + clubFileName;
158 masterFile = dataDir + "/" + masterFileName;
162 if (!dir.mkpath(dataDir)) {
163 qWarning() << "Unable to create: " + dataDir;
166 qDebug() << "Data is at:" + dataDir;
169 void MainWindow::createLayoutList(QWidget *parent)
171 QVBoxLayout * tableLayout = new QVBoxLayout;
172 tableLayout->addWidget(list);
174 QHBoxLayout *mainLayout = new QHBoxLayout(parent);
175 mainLayout->addLayout(tableLayout);
176 parent->setLayout(mainLayout);
179 void MainWindow::createListView(QList<Score *> &scoreList,
180 QList <Club *> &clubList)
182 list = new QListView(this);
184 scoreListModel = new ScoreListModel(scoreList, clubList);
185 courseListModel = new CourseListModel(clubList);
187 list->setStyleSheet(ScoreStyle::style());
189 list->setSelectionMode(QAbstractItemView::SingleSelection);
190 list->setProperty("FingerScrolling", true);
195 connect(list, SIGNAL(clicked(QModelIndex)),
196 this, SLOT(clickedList(QModelIndex)));
199 void MainWindow::listScores()
201 list->setModel(scoreListModel);
202 selectionModel = list->selectionModel();
203 updateTitleBar(titleScores);
206 void MainWindow::listCourses()
208 list->setModel(courseListModel);
209 selectionModel = list->selectionModel();
210 updateTitleBar(titleCourses);
213 void MainWindow::createActions()
215 newScoreAction = new QAction(tr("New Score"), this);
216 connect(newScoreAction, SIGNAL(triggered()), this, SLOT(newScore()));
218 newCourseAction = new QAction(tr("New Course"), this);
219 connect(newCourseAction, SIGNAL(triggered()), this, SLOT(newCourse()));
221 statAction = new QAction(tr("Statistics"), this);
222 connect(statAction, SIGNAL(triggered()), this, SLOT(viewStatistics()));
224 // Maemo5 style menu filters
225 filterGroup = new QActionGroup(this);
226 filterGroup->setExclusive(true);
228 listScoreAction = new QAction(tr("Scores"), filterGroup);
229 listScoreAction->setCheckable(true);
230 listScoreAction->setChecked(true);
231 connect(listScoreAction, SIGNAL(triggered()), this, SLOT(listScores()));
233 listCourseAction = new QAction(tr("Courses"), filterGroup);
234 listCourseAction->setCheckable(true);
235 connect(listCourseAction, SIGNAL(triggered()), this, SLOT(listCourses()));
238 void MainWindow::createMenus()
241 menu = menuBar()->addMenu("");
243 menu = menuBar()->addMenu("Menu");
246 menu->addAction(newScoreAction);
247 menu->addAction(newCourseAction);
248 menu->addAction(statAction);
249 menu->addActions(filterGroup->actions());
252 void MainWindow::updateTitleBar(QString & msg)
257 void MainWindow::showNote(QString msg)
260 QMaemo5InformationBox::information(this,
262 QMaemo5InformationBox::DefaultTimeout);
266 void MainWindow::clickedList(const QModelIndex &index)
268 int row = index.row();
270 const QAbstractItemModel *m = index.model();
271 if (m == scoreListModel) {
272 if (row < scoreList.count()) {
273 Score * score = scoreList.at(row);
274 Course * course = findCourse(score->getClubName(), score->getCourseName());
275 viewScore(score, course);
278 else if (m == courseListModel) {
279 QString str = courseListModel->data(index, 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));
292 void MainWindow::newCourse()
294 CourseSelectDialog *selectDialog = new CourseSelectDialog(this);
296 int result = selectDialog->exec();
302 selectDialog->results(clubName, courseName);
304 CourseDialog *courseDialog = new CourseDialog(this);
305 courseDialog->init();
306 QString title = "New Course: " + clubName + "," + courseName;
307 courseDialog->setWindowTitle(title);
309 int result = courseDialog->exec();
311 QVector<QString> par(18);
312 QVector<QString> hcp(18);
313 QVector<QString> len(18);
315 courseDialog->results(par, hcp, len);
318 Club *club = findClub(clubName);
320 course = club->getCourse(courseName);
322 qDebug() << "Error: club/course already in the database";
326 course = new Course(courseName, par, hcp);
327 club->addCourse(course);
331 // New club and course
332 club = new Club(clubName);
333 course = new Course(courseName, par, hcp);
334 club->addCourse(course);
338 saveClubFile(clubFile, clubList);
339 courseListModel->update(clubList);
345 void MainWindow::deleteCourse()
347 Course * course = findCourse();
348 Club * club = course->parent();
350 // Can not delete course if it has scores -- check
351 if (findScore(club->getName(), course->getName()) != 0) {
352 showNote(tr("Can not delete course, delete scores on the course first"));
359 club->delCourse(course);
361 if (club->isEmpty()) {
362 int index = clubList.indexOf(club);
364 clubList.removeAt(index);
368 saveClubFile(clubFile, clubList);
369 courseListModel->update(clubList);
373 void MainWindow::editCourse()
375 Course *course = findCourse();
378 showNote(tr("No course on edit"));
382 CourseDialog *courseDialog = new CourseDialog(this);
383 courseDialog->init(course);
385 QString title = "Edit Course: " + course->getName();
386 courseDialog->setWindowTitle(title);
388 int result = courseDialog->exec();
390 QVector<QString> par(18);
391 QVector<QString> hcp(18);
392 QVector<QString> len(18);
394 courseDialog->results(par, hcp, len);
396 course->update(par, hcp, len);
397 saveClubFile(clubFile, clubList);
401 void MainWindow::newScore()
403 SelectDialog *selectDialog = new SelectDialog(this);
405 selectDialog->init(clubList);
407 int result = selectDialog->exec();
413 selectDialog->results(clubName, courseName, date);
415 ScoreDialog *scoreDialog = new ScoreDialog(this);
416 QString title = "New Score: " + courseName + ", " + date;
417 scoreDialog->setWindowTitle(title);
419 Club *club = findClub(clubName);
421 showNote(tr("Error: no such club"));
424 Course *course = club->getCourse(courseName);
426 showNote(tr("Error: no such course:"));
429 scoreDialog->init(course);
430 result = scoreDialog->exec();
432 QVector<QString> scores(18);
434 scoreDialog->results(scores);
435 Score *score = new Score(scores, clubName, courseName, date);
438 // Sort the scores based on dates
439 qSort(scoreList.begin(), scoreList.end(), dateMoreThan);
441 saveScoreFile(scoreFile, scoreList);
442 scoreListModel->update(scoreList);
448 void MainWindow::deleteScore()
453 QModelIndex index = selectionModel->currentIndex();
454 scoreList.removeAt(index.row());
456 saveScoreFile(scoreFile, scoreList);
457 scoreListModel->update(scoreList);
461 void MainWindow::editScore()
463 QModelIndex index = selectionModel->currentIndex();
464 Score * score = scoreList.at(index.row());
467 course = findCourse(score->getClubName(), score->getCourseName());
469 if (!course || !score) {
470 qDebug() << "No score/course to edit";
474 QString date = score->getDate();
476 ScoreDialog *scoreDialog = new ScoreDialog;
478 QString title = "Edit Score: " + course->getName() + ", " + date;
479 scoreDialog->setWindowTitle(title);
481 scoreDialog->init(course, score);
483 int result = scoreDialog->exec();
486 QVector<QString> scores(18);
488 scoreDialog->results(scores);
490 score->update(scores);
492 // Sort the scores based on dates
493 qSort(scoreList.begin(), scoreList.end(), dateMoreThan);
495 saveScoreFile(scoreFile, scoreList);
497 scoreListModel->update(scoreList);
501 void MainWindow::viewScore(Score * score, Course * course)
503 scoreWin = new QMainWindow(this);
504 QString title = QString("Score: %1, %2 - %3").arg(score->getClubName()).arg(score->getCourseName()).arg(score->getDate());
505 scoreWin->setWindowTitle(title);
507 scoreWin->setAttribute(Qt::WA_Maemo5StackedWindow);
510 QAction *editAction = new QAction(tr("Edit"), scoreWin);
511 connect(editAction, SIGNAL(triggered()), this, SLOT(editScore()));
512 scoreWin->menuBar()->addAction(editAction);
514 QAction *delAction = new QAction(tr("Delete"), scoreWin);
515 connect(delAction, SIGNAL(triggered()), this, SLOT(deleteScore()));
516 scoreWin->menuBar()->addAction(delAction);
518 ScoreTableModel *model = new ScoreTableModel(score, course);
520 QTableView * table = new QTableView;
522 table->setSelectionMode(QAbstractItemView::NoSelection);
523 //table->setStyleSheet(ScoreStyle::headerView());
524 table->setStyleSheet(ScoreStyle::style());
525 table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
526 table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
527 table->horizontalHeader()->hide();
528 table->setModel(model);
530 QWidget *central = new QWidget(scoreWin);
531 scoreWin->setCentralWidget(central);
533 QVBoxLayout *layout = new QVBoxLayout;
534 layout->addWidget(table);
536 central->setLayout(layout);
540 void MainWindow::viewCourse(Course * course)
542 courseWin = new QMainWindow(this);
543 QString title = QString("Course: %1, Par - %2").arg(course->getName()).arg(course->getTotal(Total));
544 courseWin->setWindowTitle(title);
546 courseWin->setAttribute(Qt::WA_Maemo5StackedWindow);
549 QAction *editAction = new QAction(tr("Edit"), courseWin);
550 connect(editAction, SIGNAL(triggered()), this, SLOT(editCourse()));
551 courseWin->menuBar()->addAction(editAction);
553 QAction *delAction = new QAction(tr("Delete"), courseWin);
554 connect(delAction, SIGNAL(triggered()), this, SLOT(deleteCourse()));
555 courseWin->menuBar()->addAction(delAction);
557 CourseTableModel *model = new CourseTableModel(course);
559 QTableView * table = new QTableView;
561 table->setSelectionMode(QAbstractItemView::NoSelection);
562 //table->setStyleSheet(ScoreStyle::headerView());
563 table->setStyleSheet(ScoreStyle::style());
564 table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
565 table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
566 table->horizontalHeader()->hide();
567 table->setModel(model);
569 QWidget *central = new QWidget(courseWin);
570 courseWin->setCentralWidget(central);
572 QVBoxLayout *layout = new QVBoxLayout;
573 layout->addWidget(table);
575 central->setLayout(layout);
579 void MainWindow::viewStatistics()
581 QMainWindow *win = new QMainWindow(this);
582 QString title = "Statistics";
583 win->setWindowTitle(title);
585 win->setAttribute(Qt::WA_Maemo5StackedWindow);
588 StatModel *model = new StatModel(clubList, scoreList);
590 QTableView *table = new QTableView;
592 table->setSelectionMode(QAbstractItemView::NoSelection);
593 table->setStyleSheet(ScoreStyle::headerView());
594 table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
595 table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
596 table->verticalHeader()->setAutoFillBackground(true);
597 table->setModel(model);
599 QWidget *central = new QWidget(win);
600 win->setCentralWidget(central);
602 QTextEdit *textEdit = new QTextEdit;
604 textEdit->setReadOnly(true);
606 QVBoxLayout *infoLayout = new QVBoxLayout;
607 infoLayout->addWidget(table);
609 QHBoxLayout *mainLayout = new QHBoxLayout(central);
610 mainLayout->addLayout(infoLayout);
611 central->setLayout(mainLayout);
616 void MainWindow::loadScoreFile(QString &fileName, QList<Score *> &list)
618 ScoreXmlHandler handler(list);
620 if (handler.parse(fileName))
621 qDebug() << "File loaded:" << fileName << " entries:" << list.size();
624 void MainWindow::saveScoreFile(QString &fileName, QList<Score *> &list)
626 ScoreXmlHandler handler(list);
628 if (handler.save(fileName))
630 qDebug() << "File saved:" << fileName << " entries:" << list.size();
632 qWarning() << "Unable to save:" << fileName;
635 void MainWindow::loadClubFile(QString &fileName, QList<Club *> &list, bool readOnly)
637 ClubXmlHandler handler(list);
639 if (handler.parse(fileName, readOnly))
640 qDebug() << "File loaded:" << fileName << " entries:" << list.size();
643 void MainWindow::saveClubFile(QString &fileName, QList<Club *> &list)
645 ClubXmlHandler handler(list);
647 if (handler.save(fileName))
649 qDebug() << "File saved:" << fileName << " entries:" << list.size();
651 qWarning() << "Unable to save:" << fileName;