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 "settings-dialog.h"
19 #include "stat-model.h"
20 #include "xml-dom-parser.h"
22 QString appName("scorecard");
23 QString topDir("/opt");
24 QString mmcDir("/media/mmc1");
25 QString dataDirName("data");
27 QString imgDir(topDir + "/pixmaps");
28 QString scoreFileName("score.xml");
30 QString clubFileName("club.xml");
32 QString masterFileName("club-master.xml");
34 QString logFile("/tmp/scorecard.log");
35 QString titleScores("ScoreCard - Scores");
36 QString titleCourses("ScoreCard - Courses");
38 bool dateLessThan(const Score *s1, const Score *s2)
43 bool dateMoreThan(const Score *s1, const Score *s2)
47 // Find score based on club and course name
48 Score *MainWindow::findScore(QString & clubName, QString & courseName)
50 QListIterator<Score *> i(scoreList);
55 if ((s->getClubName() == clubName) &&
56 (s->getCourseName() == courseName))
62 // Find club based on name
63 Club *MainWindow::findClub(QString &name)
65 QListIterator<Club *> i(clubList);
70 if (c->getName() == name)
76 // Find course based on club & course name
77 Course *MainWindow::findCourse(const QString &clubName,
78 const QString &courseName)
80 QListIterator<Club *> i(clubList);
85 if (c->getName() == clubName) {
86 return c->getCourse(courseName);
92 // Find course based on current selection on the list
93 // TODO: make sure this is only called when course list is the model...
94 Course *MainWindow::findCourse()
96 QModelIndex index = selectionModel->currentIndex();
97 const QAbstractItemModel *model = selectionModel->model();
98 QString str = model->data(index, Qt::DisplayRole).toString();
100 QStringList strList = str.split(",");
101 if (strList.count() != 2) {
102 showNote(tr("Invalid course selection"));
105 return findCourse(strList[0], strList[1]);
108 MainWindow::MainWindow(QMainWindow *parent): QMainWindow(parent)
113 setAttribute(Qt::WA_Maemo5StackedWindow);
118 centralWidget = new QWidget(this);
120 setCentralWidget(centralWidget);
122 loadScoreFile(scoreFile, scoreList);
123 loadClubFile(masterFile, clubList, true);
124 loadClubFile(clubFile, clubList);
126 // Sort the scores based on dates
127 qSort(scoreList.begin(), scoreList.end(), dateMoreThan);
131 createListView(scoreList, clubList);
133 createLayoutList(centralWidget);
136 void MainWindow::loadSettings(void)
138 bool external = false;
144 // TODO: make via user option, automatic will never work
148 dataDir = "./" + dataDirName;
151 dataDir = mmcDir + "/" + appName + "/" + dataDirName;
154 dataDir = topDir + "/" + appName + "/" + dataDirName;
157 scoreFile = dataDir + "/" + scoreFileName;
158 clubFile = dataDir + "/" + clubFileName;
159 masterFile = dataDir + "/" + masterFileName;
163 if (!dir.mkpath(dataDir)) {
164 qWarning() << "Unable to create: " + dataDir;
167 qDebug() << "Data is at:" + dataDir;
169 settings.beginGroup("Settings");
170 conf.hcp = settings.value("hcp");
171 conf.homeClub = settings.value("home-club");
172 conf.defaultCourses = settings.value("default-courses");
174 qDebug() << "Settings: " << conf.hcp << conf.homeClub << conf.defaultCourses;
177 void MainWindow::saveSettings(void)
179 settings.beginGroup("Settings");
180 if (conf.hcp.isValid())
181 settings.setValue("hcp", conf.hcp);
182 if (conf.homeClub.isValid())
183 settings.setValue("home-club", conf.homeClub);
184 if (conf.defaultCourses.isValid())
185 settings.setValue("default-courses", conf.defaultCourses);
190 void MainWindow::createLayoutList(QWidget *parent)
192 QVBoxLayout * tableLayout = new QVBoxLayout;
193 tableLayout->addWidget(list);
195 QHBoxLayout *mainLayout = new QHBoxLayout(parent);
196 mainLayout->addLayout(tableLayout);
197 parent->setLayout(mainLayout);
200 void MainWindow::createListView(QList<Score *> &scoreList,
201 QList <Club *> &clubList)
203 list = new QListView(this);
205 scoreListModel = new ScoreListModel(scoreList, clubList);
206 courseListModel = new CourseListModel(clubList);
208 list->setStyleSheet(ScoreStyle::style());
210 list->setSelectionMode(QAbstractItemView::SingleSelection);
211 list->setProperty("FingerScrolling", true);
216 connect(list, SIGNAL(clicked(QModelIndex)),
217 this, SLOT(clickedList(QModelIndex)));
220 void MainWindow::listScores()
222 list->setModel(scoreListModel);
223 selectionModel = list->selectionModel();
224 updateTitleBar(titleScores);
227 void MainWindow::listCourses()
229 list->setModel(courseListModel);
230 selectionModel = list->selectionModel();
231 updateTitleBar(titleCourses);
234 void MainWindow::createActions()
236 newScoreAction = new QAction(tr("New Score"), this);
237 connect(newScoreAction, SIGNAL(triggered()), this, SLOT(newScore()));
239 newCourseAction = new QAction(tr("New Course"), this);
240 connect(newCourseAction, SIGNAL(triggered()), this, SLOT(newCourse()));
242 statAction = new QAction(tr("Statistics"), this);
243 connect(statAction, SIGNAL(triggered()), this, SLOT(viewStatistics()));
245 settingsAction = new QAction(tr("Settings"), this);
246 connect(settingsAction, SIGNAL(triggered()), this, SLOT(viewSettings()));
248 // Maemo5 style menu filters
249 filterGroup = new QActionGroup(this);
250 filterGroup->setExclusive(true);
252 listScoreAction = new QAction(tr("Scores"), filterGroup);
253 listScoreAction->setCheckable(true);
254 listScoreAction->setChecked(true);
255 connect(listScoreAction, SIGNAL(triggered()), this, SLOT(listScores()));
257 listCourseAction = new QAction(tr("Courses"), filterGroup);
258 listCourseAction->setCheckable(true);
259 connect(listCourseAction, SIGNAL(triggered()), this, SLOT(listCourses()));
262 void MainWindow::createMenus()
265 menu = menuBar()->addMenu("");
267 menu = menuBar()->addMenu("Menu");
270 menu->addAction(newScoreAction);
271 menu->addAction(newCourseAction);
272 menu->addAction(statAction);
273 menu->addAction(settingsAction);
274 menu->addActions(filterGroup->actions());
277 void MainWindow::updateTitleBar(QString & msg)
282 void MainWindow::showNote(QString msg)
285 QMaemo5InformationBox::information(this,
287 QMaemo5InformationBox::DefaultTimeout);
291 void MainWindow::clickedList(const QModelIndex &index)
293 int row = index.row();
295 const QAbstractItemModel *m = index.model();
296 if (m == scoreListModel) {
297 if (row < scoreList.count()) {
298 Score * score = scoreList.at(row);
299 Course * course = findCourse(score->getClubName(), score->getCourseName());
300 viewScore(score, course);
303 else if (m == courseListModel) {
304 QString str = courseListModel->data(index, Qt::DisplayRole).toString();
305 QStringList strList = str.split(",");
307 if (strList.count() != 2) {
308 showNote(QString("Invalid course selection"));
311 Course * course = findCourse(strList.at(0), strList.at(1));
317 void MainWindow::newCourse()
319 CourseSelectDialog *selectDialog = new CourseSelectDialog(this);
321 int result = selectDialog->exec();
327 selectDialog->results(clubName, courseName);
329 CourseDialog *courseDialog = new CourseDialog(this);
330 courseDialog->init();
331 QString title = "New Course: " + clubName + "," + courseName;
332 courseDialog->setWindowTitle(title);
334 int result = courseDialog->exec();
336 QVector<QString> par(18);
337 QVector<QString> hcp(18);
338 QVector<QString> len(18);
340 courseDialog->results(par, hcp, len);
343 Club *club = findClub(clubName);
345 course = club->getCourse(courseName);
347 qDebug() << "Error: club/course already in the database";
351 course = new Course(courseName, par, hcp);
352 club->addCourse(course);
356 // New club and course
357 club = new Club(clubName);
358 course = new Course(courseName, par, hcp);
359 club->addCourse(course);
363 saveClubFile(clubFile, clubList);
364 courseListModel->update(clubList);
370 void MainWindow::deleteCourse()
372 Course * course = findCourse();
373 Club * club = course->parent();
375 // Can not delete course if it has scores -- check
376 if (findScore(club->getName(), course->getName()) != 0) {
377 showNote(tr("Can not delete course, delete scores on the course first"));
384 club->delCourse(course);
386 if (club->isEmpty()) {
387 int index = clubList.indexOf(club);
389 clubList.removeAt(index);
393 saveClubFile(clubFile, clubList);
394 courseListModel->update(clubList);
398 void MainWindow::editCourse()
400 Course *course = findCourse();
403 showNote(tr("No course on edit"));
407 CourseDialog *courseDialog = new CourseDialog(this);
408 courseDialog->init(course);
410 QString title = "Edit Course: " + course->getName();
411 courseDialog->setWindowTitle(title);
413 int result = courseDialog->exec();
415 QVector<QString> par(18);
416 QVector<QString> hcp(18);
417 QVector<QString> len(18);
419 courseDialog->results(par, hcp, len);
421 course->update(par, hcp, len);
422 saveClubFile(clubFile, clubList);
426 void MainWindow::newScore()
428 SelectDialog *selectDialog = new SelectDialog(this);
430 selectDialog->init(clubList);
432 int result = selectDialog->exec();
438 selectDialog->results(clubName, courseName, date);
440 ScoreDialog *scoreDialog = new ScoreDialog(this);
441 QString title = "New Score: " + courseName + ", " + date;
442 scoreDialog->setWindowTitle(title);
444 Club *club = findClub(clubName);
446 showNote(tr("Error: no such club"));
449 Course *course = club->getCourse(courseName);
451 showNote(tr("Error: no such course:"));
454 scoreDialog->init(course);
455 result = scoreDialog->exec();
457 QVector<QString> scores(18);
459 scoreDialog->results(scores);
460 Score *score = new Score(scores, clubName, courseName, date);
463 // Sort the scores based on dates
464 qSort(scoreList.begin(), scoreList.end(), dateMoreThan);
466 saveScoreFile(scoreFile, scoreList);
467 scoreListModel->update(scoreList);
473 void MainWindow::deleteScore()
478 QModelIndex index = selectionModel->currentIndex();
479 scoreList.removeAt(index.row());
481 saveScoreFile(scoreFile, scoreList);
482 scoreListModel->update(scoreList);
486 void MainWindow::editScore()
488 QModelIndex index = selectionModel->currentIndex();
489 Score * score = scoreList.at(index.row());
492 course = findCourse(score->getClubName(), score->getCourseName());
494 if (!course || !score) {
495 qDebug() << "No score/course to edit";
499 QString date = score->getDate();
501 ScoreDialog *scoreDialog = new ScoreDialog;
503 QString title = "Edit Score: " + course->getName() + ", " + date;
504 scoreDialog->setWindowTitle(title);
506 scoreDialog->init(course, score);
508 int result = scoreDialog->exec();
511 QVector<QString> scores(18);
513 scoreDialog->results(scores);
515 score->update(scores);
517 // Sort the scores based on dates
518 qSort(scoreList.begin(), scoreList.end(), dateMoreThan);
520 saveScoreFile(scoreFile, scoreList);
522 scoreListModel->update(scoreList);
526 void MainWindow::viewScore(Score * score, Course * course)
528 scoreWin = new QMainWindow(this);
529 QString title = QString("Score: %1, %2 - %3").arg(score->getClubName()).arg(score->getCourseName()).arg(score->getDate());
530 scoreWin->setWindowTitle(title);
532 scoreWin->setAttribute(Qt::WA_Maemo5StackedWindow);
535 QAction *editAction = new QAction(tr("Edit"), scoreWin);
536 connect(editAction, SIGNAL(triggered()), this, SLOT(editScore()));
537 scoreWin->menuBar()->addAction(editAction);
539 QAction *delAction = new QAction(tr("Delete"), scoreWin);
540 connect(delAction, SIGNAL(triggered()), this, SLOT(deleteScore()));
541 scoreWin->menuBar()->addAction(delAction);
543 ScoreTableModel *model = new ScoreTableModel(score, course);
545 QTableView * table = new QTableView;
547 table->setSelectionMode(QAbstractItemView::NoSelection);
548 table->setStyleSheet(ScoreStyle::style());
549 table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
550 table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
551 table->horizontalHeader()->hide();
552 table->setModel(model);
554 QWidget *central = new QWidget(scoreWin);
555 scoreWin->setCentralWidget(central);
557 QVBoxLayout *layout = new QVBoxLayout;
558 layout->addWidget(table);
560 central->setLayout(layout);
564 void MainWindow::viewCourse(Course * course)
566 courseWin = new QMainWindow(this);
567 QString title = QString("Course: %1, Par - %2").arg(course->getName()).arg(course->getTotal(Total));
568 courseWin->setWindowTitle(title);
570 courseWin->setAttribute(Qt::WA_Maemo5StackedWindow);
573 QAction *editAction = new QAction(tr("Edit"), courseWin);
574 connect(editAction, SIGNAL(triggered()), this, SLOT(editCourse()));
575 courseWin->menuBar()->addAction(editAction);
577 QAction *delAction = new QAction(tr("Delete"), courseWin);
578 connect(delAction, SIGNAL(triggered()), this, SLOT(deleteCourse()));
579 courseWin->menuBar()->addAction(delAction);
581 CourseTableModel *model = new CourseTableModel(course);
583 QTableView * table = new QTableView;
585 table->setSelectionMode(QAbstractItemView::NoSelection);
586 //table->setStyleSheet(ScoreStyle::headerView());
587 table->setStyleSheet(ScoreStyle::style());
588 table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
589 table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
590 table->horizontalHeader()->hide();
591 table->setModel(model);
593 QWidget *central = new QWidget(courseWin);
594 courseWin->setCentralWidget(central);
596 QVBoxLayout *layout = new QVBoxLayout;
597 layout->addWidget(table);
599 central->setLayout(layout);
603 void MainWindow::viewStatistics()
605 QMainWindow *win = new QMainWindow(this);
606 QString title = "Statistics";
607 win->setWindowTitle(title);
609 win->setAttribute(Qt::WA_Maemo5StackedWindow);
612 StatModel *model = new StatModel(clubList, scoreList);
614 QTableView *table = new QTableView;
616 table->setSelectionMode(QAbstractItemView::NoSelection);
617 table->setStyleSheet(ScoreStyle::style());
618 table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
619 table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
620 table->verticalHeader()->setAutoFillBackground(true);
621 table->setModel(model);
623 QWidget *central = new QWidget(win);
624 win->setCentralWidget(central);
626 QTextEdit *textEdit = new QTextEdit;
628 textEdit->setReadOnly(true);
630 QVBoxLayout *infoLayout = new QVBoxLayout;
631 infoLayout->addWidget(table);
633 QHBoxLayout *mainLayout = new QHBoxLayout(central);
634 mainLayout->addLayout(infoLayout);
635 central->setLayout(mainLayout);
640 void MainWindow::viewSettings()
642 SettingsDialog *dlg = new SettingsDialog(this);
644 dlg->init(conf, clubList);
646 int result = dlg->exec();
651 //qDebug() << << b << c;
656 void MainWindow::loadScoreFile(QString &fileName, QList<Score *> &list)
658 ScoreXmlHandler handler(list);
660 if (handler.parse(fileName))
661 qDebug() << "File loaded:" << fileName << " entries:" << list.size();
664 void MainWindow::saveScoreFile(QString &fileName, QList<Score *> &list)
666 ScoreXmlHandler handler(list);
668 if (handler.save(fileName))
670 qDebug() << "File saved:" << fileName << " entries:" << list.size();
672 qWarning() << "Unable to save:" << fileName;
675 void MainWindow::loadClubFile(QString &fileName, QList<Club *> &list, bool readOnly)
677 ClubXmlHandler handler(list);
679 if (handler.parse(fileName, readOnly))
680 qDebug() << "File loaded:" << fileName << " entries:" << list.size();
683 void MainWindow::saveClubFile(QString &fileName, QList<Club *> &list)
685 ClubXmlHandler handler(list);
687 if (handler.save(fileName))
689 qDebug() << "File saved:" << fileName << " entries:" << list.size();
691 qWarning() << "Unable to save:" << fileName;