From 97db841c6d9a01ee4fa51ccd0723d5b1a71e90bd Mon Sep 17 00:00:00 2001 From: Sakari Poussa Date: Sun, 25 Apr 2010 18:24:35 +0300 Subject: [PATCH] Big refactoring: new UI logic, Qt 4.6 support, more Maemo5 features --- data/score.xml | 460 ++++++++++++++++++++++++++++++++-- scorecard.pro | 2 + src/cell-delegate.h | 14 ++ src/course-dialog.cpp | 2 +- src/data.cpp | 26 +- src/data.h | 13 +- src/main-window.cpp | 646 ++++++++++++++++++++++++++++++------------------ src/main-window.h | 71 +++--- src/score-dialog.cpp | 2 +- src/table-model.cpp | 323 ++++++++++++------------ src/table-model.h | 113 ++++----- src/xml-dom-parser.cpp | 18 +- 12 files changed, 1156 insertions(+), 534 deletions(-) diff --git a/data/score.xml b/data/score.xml index c7f64df..644d8ad 100644 --- a/data/score.xml +++ b/data/score.xml @@ -1,24 +1,4 @@ - - - - - - - - - - - - - - - - - - - - @@ -679,4 +659,444 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scorecard.pro b/scorecard.pro index 01ec878..2fd2cd9 100644 --- a/scorecard.pro +++ b/scorecard.pro @@ -18,6 +18,7 @@ src/main-window.h \ src/score-dialog.h \ src/course-dialog.h \ src/table-model.h \ +src/list-model.h \ src/stat-model.h \ src/xml-dom-parser.h \ src/data.h @@ -28,6 +29,7 @@ src/main-window.cpp \ src/score-dialog.cpp \ src/course-dialog.cpp \ src/table-model.cpp \ +src/list-model.cpp \ src/stat-model.cpp \ src/xml-dom-parser.cpp \ src/data.cpp diff --git a/src/cell-delegate.h b/src/cell-delegate.h index 38df746..aba54a9 100644 --- a/src/cell-delegate.h +++ b/src/cell-delegate.h @@ -52,6 +52,20 @@ protected: QObject *m_parent; }; +class RowDelegate : public QItemDelegate +{ + Q_OBJECT + +public: + RowDelegate(QObject *parent = 0); + +private slots: + void commitAndCloseEditor(); + + private: + QObject *m_parent; +}; + class CellDelegate : public QItemDelegate { Q_OBJECT diff --git a/src/course-dialog.cpp b/src/course-dialog.cpp index 9f2f3f7..a4ebc57 100644 --- a/src/course-dialog.cpp +++ b/src/course-dialog.cpp @@ -135,7 +135,7 @@ void CourseDialog::createTable(QWidget *parent) table->horizontalHeader()->hide(); table->horizontalHeader()->setResizeMode(QHeaderView::Stretch); table->verticalHeader()->setResizeMode(QHeaderView::Stretch); - table->setStyleSheet(ScoreColor::styleSheet()); + //table->setStyleSheet(ScoreColor::styleSheet()); } void CourseDialog::init(Course *course) diff --git a/src/data.cpp b/src/data.cpp index 19be40a..6ff2d98 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -219,8 +219,10 @@ Course::Course(const QXmlAttributes &attrs) { name = attrs.value("name"); } -Course::Course(const QDomElement node) { - name = node.attribute("name", ""); +Course::Course(const QDomElement node, Club * parent) + : club(parent) +{ + name = node.attribute("name", ""); } Course::Course(QString &name, @@ -235,6 +237,11 @@ Course::Course(QString &name, } } +Club * Course::parent() +{ + return club; +} + QDomElement Course::toElement(QDomDocument doc) { QDomElement node = doc.createElement("course"); @@ -332,6 +339,21 @@ void Club::addCourse(Course *iCourse) { courseList << iCourse; } +void Club::delCourse(Course * course) { + int index = courseList.indexOf(course); + + if (index != -1) + courseList.removeAt(index); +} + +bool Club::isEmpty() +{ + bool rc = false; + if (courseList.count() == 0) + rc = true; + return rc; +} + QDomElement Club::toElement(QDomDocument doc) { QDomElement node = doc.createElement("club"); diff --git a/src/data.h b/src/data.h index 580581b..5709416 100644 --- a/src/data.h +++ b/src/data.h @@ -50,6 +50,11 @@ class Score { return date < val.getDate(); } + bool operator> (const Score& val) const + { + return date > val.getDate(); + } + QDomElement toElement(QDomDocument doc); int update(QVector &scores); void addHole(Hole *iHole); @@ -65,10 +70,12 @@ class Score { QString club, course, date; }; +class Club; + class Course { public: Course(const QXmlAttributes &attrs); - Course(const QDomElement node); + Course(const QDomElement node, Club * parent = 0); Course(QString &name, QVector &, QVector &); QDomElement toElement(QDomDocument doc); int update(QVector &, QVector &, QVector &); @@ -78,10 +85,12 @@ class Course { QString& getName(); QString getTotal(int what); void dump(); + Club * parent(); private: QList holeList; QString name; + Club *club; }; class Club { @@ -93,10 +102,12 @@ class Club { QDomElement toElement(QDomDocument doc); void addCourse(Course *iCourse); + void delCourse(Course *iCourse); void dump(); QString& getName(); Course *getCourse(int pos); Course *getCourse(const QString &courseName); + bool isEmpty(); QList getCourseList() { return courseList; } // HACK: fixme diff --git a/src/main-window.cpp b/src/main-window.cpp index 49d973a..42c6b44 100644 --- a/src/main-window.cpp +++ b/src/main-window.cpp @@ -7,6 +7,9 @@ */ #include +#ifdef Q_WS_MAEMO_5 +#include +#endif #include "score-common.h" #include "main-window.h" @@ -32,10 +35,78 @@ 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) +{ + QListIterator 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) +{ + QListIterator 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) +{ + QListIterator 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 +Course *MainWindow::findCourse() +{ + QModelIndex index = selectionModel->currentIndex(); + 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]); +} + MainWindow::MainWindow(QMainWindow *parent): QMainWindow(parent) { resize(800, 480); +#ifdef Q_WS_MAEMO_5 + setAttribute(Qt::WA_Maemo5StackedWindow); +#endif + loadSettings(); centralWidget = new QWidget(this); @@ -46,14 +117,14 @@ MainWindow::MainWindow(QMainWindow *parent): QMainWindow(parent) loadClubFile(clubFile, clubList); // Sort the scores based on dates - qSort(scoreList.begin(), scoreList.end(), dateLessThan); + qSort(scoreList.begin(), scoreList.end(), dateMoreThan); createActions(); createMenus(); - createTableView(scoreList, clubList); + createListView(scoreList, clubList); updateTitleBar(); - createLayout(centralWidget); + createLayoutList(centralWidget); } void MainWindow::loadSettings(void) @@ -89,319 +160,426 @@ void MainWindow::loadSettings(void) qDebug() << "Data is at:" + dataDir; } -void MainWindow::createLayout(QWidget *parent) +void MainWindow::createLayoutList(QWidget *parent) { + QVBoxLayout * tableLayout = new QVBoxLayout; + tableLayout->addWidget(list); - buttonLayout = new QVBoxLayout; - //labelLayout->addStretch(); - buttonLayout->addWidget(nextButton); - buttonLayout->addWidget(prevButton); - buttonLayout->addWidget(lastButton); - buttonLayout->addWidget(firstButton); - - tableLayout = new QVBoxLayout; - tableLayout->addWidget(table); - - QHBoxLayout *mainLayout = new QHBoxLayout(parent); - mainLayout->addLayout(tableLayout); - mainLayout->addLayout(buttonLayout); - parent->setLayout(mainLayout); + QHBoxLayout *mainLayout = new QHBoxLayout(parent); + mainLayout->addLayout(tableLayout); + parent->setLayout(mainLayout); } -// Setup 'score' tab view -void MainWindow::createTableView(QList &scoreList, QList &clubList) +void MainWindow::createListView(QList &scoreList, + QList &clubList) { - table = new QTableView; - - nextButton = new QPushButton(tr("Next")); - prevButton = new QPushButton(tr("Prev")); - firstButton = new QPushButton(tr("First")); - lastButton = new QPushButton(tr("Last")); - - 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())); + list = new QListView; - scoreTableModel = new ScoreTableModel(); + scoreListModel = new ScoreListModel(scoreList, clubList); + courseListModel = new CourseListModel(clubList); - table->showGrid(); + list->setStyleSheet(ScoreStyle::style()); - table->setStyleSheet(ScoreColor::styleSheet()); + list->setSelectionMode(QAbstractItemView::SingleSelection); - table->setModel(scoreTableModel); - table->setSelectionMode(QAbstractItemView::NoSelection); + // Initial view + listScores(); +} - scoreTableModel->setScore(scoreList); - scoreTableModel->setClub(clubList); +void MainWindow::listScores() +{ + list->setModel(scoreListModel); + selectionModel = list->selectionModel(); + connect(selectionModel, SIGNAL(selectionChanged (const QItemSelection &, const QItemSelection &)), + this, SLOT(scoreSelectionChanged(const QItemSelection &, const QItemSelection &))); +} - // Fill out all the space with the tables - table->horizontalHeader()->setResizeMode(QHeaderView::Stretch); - table->verticalHeader()->setResizeMode(QHeaderView::Stretch); - table->horizontalHeader()->hide(); - //table->verticalHeader()->setStyleSheet("color : gray }"); +void MainWindow::listCourses() +{ + list->setModel(courseListModel); + selectionModel = list->selectionModel(); + connect(selectionModel, SIGNAL(selectionChanged (const QItemSelection &, const QItemSelection &)), + this, SLOT(courseSelectionChanged(const QItemSelection &, const QItemSelection &))); } void MainWindow::createActions() { - newScoreAct = new QAction(tr("New Score"), this); - connect(newScoreAct, SIGNAL(triggered()), this, SLOT(newScore())); + 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())); + // Maemo5 style menu filters + filterGroup = new QActionGroup(this); + filterGroup->setExclusive(true); - statAct = new QAction(tr("Statistics"), this); - connect(statAct, SIGNAL(triggered()), this, SLOT(viewStatistics())); + listScoreAction = new QAction(tr("Scores"), filterGroup); + listScoreAction->setCheckable(true); + listScoreAction->setChecked(true); + connect(listScoreAction, SIGNAL(triggered()), this, SLOT(listScores())); - nextAct = new QAction(tr( " Next "), this); - connect(nextAct, SIGNAL(triggered()), this, SLOT(nextButtonClicked())); - - prevAct = new QAction(" Prev ", this); - connect(prevAct, SIGNAL(triggered()), this, SLOT(prevButtonClicked())); - - firstAct = new QAction(tr(" First "), this); - connect(firstAct, SIGNAL(triggered()), this, SLOT(firstButtonClicked())); - - lastAct = new QAction(tr( " Last "), this); - connect(lastAct, SIGNAL(triggered()), this, SLOT(lastButtonClicked())); + listCourseAction = new QAction(tr("Courses"), filterGroup); + listCourseAction->setCheckable(true); + connect(listCourseAction, SIGNAL(triggered()), this, SLOT(listCourses())); } void MainWindow::createMenus() { #ifdef Q_WS_MAEMO_5 - menu = menuBar()->addMenu(""); + menu = menuBar()->addMenu(""); #else - menu = menuBar()->addMenu("Menu"); + menu = menuBar()->addMenu("Menu"); #endif - menu->addAction(newScoreAct); - menu->addAction(newCourseAct); - menu->addAction(editScoreAct); - menu->addAction(editCourseAct); - menu->addAction(statAct); + menu->addAction(newScoreAction); + menu->addAction(newCourseAction); + menu->addAction(statAction); + menu->addActions(filterGroup->actions()); } void MainWindow::updateTitleBar() { - QString title = scoreTableModel->getInfoText(); - if (title.isEmpty()) - title = "ScoreCard - No Scores"; - - setWindowTitle(title); + QString title("ScoreCard"); + setWindowTitle(title); } -void MainWindow::firstButtonClicked() +void MainWindow::showNote(QString msg) { - scoreTableModel->first(); - updateTitleBar(); +#ifdef Q_WS_MAEMO_5 + QMaemo5InformationBox::information(this, + msg, + QMaemo5InformationBox::DefaultTimeout); +#endif } -void MainWindow::lastButtonClicked() +void MainWindow::scoreSelectionChanged(const QItemSelection &selected, + const QItemSelection &deselected) { - scoreTableModel->last(); - updateTitleBar(); -} + QModelIndexList list = selected.indexes(); -void MainWindow::nextButtonClicked() -{ - scoreTableModel->next(); - updateTitleBar(); + int row = list.at(0).row(); + + Score * score = scoreList.at(row); + Course * course = findCourse(score->getClubName(), score->getCourseName()); + viewScore(score, course); } -void MainWindow::prevButtonClicked() +void MainWindow::courseSelectionChanged(const QItemSelection &selected, + const QItemSelection &deselected) { - scoreTableModel->prev(); - updateTitleBar(); + QModelIndexList indexes = selected.indexes(); + + int row = indexes.at(0).row(); + + QString str = courseListModel->data(indexes.at(0), 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); } -// FIXME: dup code from table-model.cpp -Club *MainWindow::findClub(QString &name) +void MainWindow::changeCurrent(const QModelIndex ¤t, + const QModelIndex &previous) { - QListIterator i(clubList); - Club *c; - - while (i.hasNext()) { - c = i.next(); - if (c->getName() == name) - return c; - } - return 0; + qDebug() << "Current: " << current; } void MainWindow::newCourse() { - CourseSelectDialog *selectDialog = new CourseSelectDialog(this); + 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 par(18); + QVector hcp(18); + QVector 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 { + // New club and course + club = new Club(clubName); + course = new Course(courseName, par, hcp); + club->addCourse(course); + clubList << club; + } + // Save it + saveClubFile(clubFile, clubList); + // TODO: update on live + //courseListModel->update(courseList); + list->update(); + } + } +} - selectDialog->results(clubName, courseName); +void MainWindow::deleteCourse() +{ + Course * course = findCourse(); + Club * club = course->parent(); - CourseDialog *courseDialog = new CourseDialog(this); - courseDialog->init(); + // 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 (courseWin) + courseWin->close(); - QString title = "New Course: " + clubName + "," + courseName; - courseDialog->setWindowTitle(title); + club->delCourse(course); - int result = courseDialog->exec(); - if (result) { - QVector par(18); - QVector hcp(18); - QVector 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 { - // New club and course - 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); + 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::editCourse() { - Course *course = scoreTableModel->getCourse(); + Course *course = findCourse(); - if (!course) { - qWarning() << "No course on edit"; - return; - } + if (!course) { + showNote(tr("No course on edit")); + return; + } - CourseDialog *courseDialog = new CourseDialog(this); - courseDialog->init(course); + CourseDialog *courseDialog = new CourseDialog(this); + courseDialog->init(course); - QString title = "Edit Course: " + course->getName(); - courseDialog->setWindowTitle(title); + QString title = "Edit Course: " + course->getName(); + courseDialog->setWindowTitle(title); - int result = courseDialog->exec(); - if (result) { - QVector par(18); - QVector hcp(18); - QVector len(18); + int result = courseDialog->exec(); + if (result) { + QVector par(18); + QVector hcp(18); + QVector len(18); - courseDialog->results(par, hcp, len); + courseDialog->results(par, hcp, len); - course->update(par, hcp, len); - saveClubFile(clubFile, clubList); - } + course->update(par, hcp, len); + saveClubFile(clubFile, clubList); + } } void MainWindow::newScore() { - SelectDialog *selectDialog = new SelectDialog(this); + SelectDialog *selectDialog = new SelectDialog(this); - selectDialog->init(clubList); + selectDialog->init(clubList); - 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, 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 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(); + } + } +} - selectDialog->results(clubName, courseName, date); +void MainWindow::deleteScore() +{ + if (scoreWin) + scoreWin->close(); - ScoreDialog *scoreDialog = new ScoreDialog(this); - QString title = "New Score: " + courseName + ", " + date; - scoreDialog->setWindowTitle(title); + QModelIndex index = selectionModel->currentIndex(); + scoreList.removeAt(index.row()); + // Save it + saveScoreFile(scoreFile, scoreList); + scoreListModel->update(scoreList); + list->update(); +} - Club *club = findClub(clubName); - if (!club) { - qWarning() << "Error: no such club:" << clubName; - return; - } - Course *course = club->getCourse(courseName); - if (!course) { - qWarning() << "Error: no such course:" << courseName; - return; +void MainWindow::editScore() +{ + QModelIndex index = selectionModel->currentIndex(); + Score * score = scoreList.at(index.row()); + Course * course = 0; + if (score) + course = findCourse(score->getClubName(), score->getCourseName()); + + if (!course || !score) { + qDebug() << "No score/course to edit"; + return; } - scoreDialog->init(course); - result = scoreDialog->exec(); - if (result) { - QVector scores(18); - scoreDialog->results(scores); - Score *score = new Score(scores, clubName, courseName, date); - scoreList << score; + QString date = score->getDate(); - // Sort the scores based on dates - qSort(scoreList.begin(), scoreList.end(), dateLessThan); - // Save it - saveScoreFile(scoreFile, scoreList); + ScoreDialog *scoreDialog = new ScoreDialog; + + QString title = "Edit Score: " + course->getName() + ", " + date; + scoreDialog->setWindowTitle(title); - // TODO: does this really work? No mem leaks? - scoreTableModel->setScore(scoreList, score); - updateTitleBar(); + scoreDialog->init(course, score); + + int result = scoreDialog->exec(); + + if (result) { + QVector 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); + // Update the model + scoreListModel->update(scoreList); } - } } -void MainWindow::editScore() +void MainWindow::viewScore(Score * score, + Course * course) { - Course *course = scoreTableModel->getCourse(); - Score *score = scoreTableModel->getScore(); + scoreWin = new QMainWindow(this); + QString title = QString("Score: %1, %2 - %3").arg(score->getClubName()).arg(score->getCourseName()).arg(score->getDate()); + scoreWin->setWindowTitle(title); +#ifdef Q_WS_MAEMO_5 + scoreWin->setAttribute(Qt::WA_Maemo5StackedWindow); +#endif - if (!course || !score) { - qDebug() << "No score/course to edit"; - return; - } + QAction *editAction = new QAction(tr("Edit"), scoreWin); + connect(editAction, SIGNAL(triggered()), this, SLOT(editScore())); + scoreWin->menuBar()->addAction(editAction); - QString date = score->getDate(); + QAction *delAction = new QAction(tr("Delete"), scoreWin); + connect(delAction, SIGNAL(triggered()), this, SLOT(deleteScore())); + scoreWin->menuBar()->addAction(delAction); - ScoreDialog *scoreDialog = new ScoreDialog(this); - - QString title = "Edit Score: " + course->getName() + ", " + date; - scoreDialog->setWindowTitle(title); + ScoreTableModel *model = new ScoreTableModel(score, course); + + QTableView * table = new QTableView; + table->showGrid(); + table->setSelectionMode(QAbstractItemView::NoSelection); + //table->setStyleSheet(ScoreStyle::headerView()); + table->setStyleSheet(ScoreStyle::style()); + table->horizontalHeader()->setResizeMode(QHeaderView::Stretch); + table->verticalHeader()->setResizeMode(QHeaderView::Stretch); + table->horizontalHeader()->hide(); + table->setModel(model); + + QWidget *central = new QWidget(scoreWin); + scoreWin->setCentralWidget(central); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(table); + + central->setLayout(layout); + scoreWin->show(); +} - scoreDialog->init(course, score); +void MainWindow::viewCourse(Course * course) +{ + courseWin = new QMainWindow(this); + QString title = QString("Course: %1, Par - %2").arg(course->getName()).arg(course->getTotal(Total)); + courseWin->setWindowTitle(title); +#ifdef Q_WS_MAEMO_5 + courseWin->setAttribute(Qt::WA_Maemo5StackedWindow); +#endif - int result = scoreDialog->exec(); + QAction *editAction = new QAction(tr("Edit"), courseWin); + connect(editAction, SIGNAL(triggered()), this, SLOT(editCourse())); + courseWin->menuBar()->addAction(editAction); - if (result) { - QVector scores(18); + QAction *delAction = new QAction(tr("Delete"), courseWin); + connect(delAction, SIGNAL(triggered()), this, SLOT(deleteCourse())); + courseWin->menuBar()->addAction(delAction); - scoreDialog->results(scores); + CourseTableModel *model = new CourseTableModel(course); - score->update(scores); - - // Sort the scores based on dates - qSort(scoreList.begin(), scoreList.end(), dateLessThan); - // Save it - saveScoreFile(scoreFile, scoreList); - - // TODO: does this really work? No mem leaks? - scoreTableModel->setScore(scoreList, score); - updateTitleBar(); - } + QTableView * table = new QTableView; + table->showGrid(); + table->setSelectionMode(QAbstractItemView::NoSelection); + //table->setStyleSheet(ScoreStyle::headerView()); + table->setStyleSheet(ScoreStyle::style()); + table->horizontalHeader()->setResizeMode(QHeaderView::Stretch); + table->verticalHeader()->setResizeMode(QHeaderView::Stretch); + table->horizontalHeader()->hide(); + table->setModel(model); + + QWidget *central = new QWidget(courseWin); + courseWin->setCentralWidget(central); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(table); + + central->setLayout(layout); + courseWin->show(); } void MainWindow::viewStatistics() @@ -409,27 +587,25 @@ void MainWindow::viewStatistics() QMainWindow *win = new QMainWindow(this); QString title = "Statistics"; win->setWindowTitle(title); +#ifdef Q_WS_MAEMO_5 + win->setAttribute(Qt::WA_Maemo5StackedWindow); +#endif - StatModel *statModel = new StatModel(clubList, scoreList); + StatModel *model = new StatModel(clubList, scoreList); QTableView *table = new QTableView; table->showGrid(); table->setSelectionMode(QAbstractItemView::NoSelection); + table->setStyleSheet(ScoreStyle::headerView()); table->horizontalHeader()->setResizeMode(QHeaderView::Stretch); table->verticalHeader()->setResizeMode(QHeaderView::Stretch); table->verticalHeader()->setAutoFillBackground(true); - table->setModel(statModel); + table->setModel(model); QWidget *central = new QWidget(win); win->setCentralWidget(central); - QPushButton *b1 = new QPushButton("Graphs"); - - QVBoxLayout *buttonLayout = new QVBoxLayout; - buttonLayout->addWidget(b1); - QTextEdit *textEdit = new QTextEdit; - //getStat(textEdit); textEdit->setReadOnly(true); @@ -438,8 +614,6 @@ void MainWindow::viewStatistics() QHBoxLayout *mainLayout = new QHBoxLayout(central); mainLayout->addLayout(infoLayout); - //mainLayout->addLayout(buttonLayout); - central->setLayout(mainLayout); win->show(); diff --git a/src/main-window.h b/src/main-window.h index b922038..94129cc 100644 --- a/src/main-window.h +++ b/src/main-window.h @@ -8,17 +8,19 @@ #include #include +#include #include -#include #include #include #include #include #include +#include #include #include "data.h" #include "table-model.h" +#include "list-model.h" class MainWindow : public QMainWindow { @@ -26,8 +28,9 @@ class MainWindow : public QMainWindow public: MainWindow(QMainWindow *parent = 0); - void createLayout(QWidget *parent = 0); - void createTableView(QList &, QList &); + void createLayoutTable(QWidget *parent = 0); + void createLayoutList(QWidget *parent = 0); + void createListView(QList &, QList &); void updateTitleBar(); void loadScoreFile(QString &fileName, QList &scoreList); void loadClubFile(QString &fileName, QList &clubList); @@ -38,66 +41,68 @@ signals: void dataChanged(); private slots: - void firstButtonClicked(); - void lastButtonClicked(); - void nextButtonClicked(); - void prevButtonClicked(); - + void scoreSelectionChanged(const QItemSelection &selected, + const QItemSelection &deselected); + void courseSelectionChanged(const QItemSelection &selected, + const QItemSelection &deselected); + void changeCurrent(const QModelIndex ¤t, + const QModelIndex &previous); void newScore(); + void deleteScore(); void editScore(); void newCourse(); + void deleteCourse(); void editCourse(); void viewStatistics(); + void listScores(); + void listCourses(); private: void loadSettings(void); - Club *findClub(QString &name); + Club * findClub(QString &name); + Course * findCourse(const QString &clubName, const QString &courseName); + Course * findCourse(); + Score * findScore(QString & clubName, QString & courseName); + + void showNote(QString msg); void getStat(QTextEdit *); + void viewScore(Score * score, Course * course); + void viewCourse(Course * course); + QList scoreList; QList clubList; ScoreTableModel *scoreTableModel; + ScoreListModel *scoreListModel; + CourseListModel *courseListModel; QAbstractItemModel *tableModel; QItemSelectionModel *selectionModel; QTableView *table; + QListView *list; // Layouts - QVBoxLayout *tableLayout; - QVBoxLayout *buttonLayout; QWidget *centralWidget; // Menus QMenu *menu; - // Buttons - QPushButton *nextButton; - QPushButton *prevButton; - QPushButton *firstButton; - QPushButton *lastButton; - - // Toolbar - QToolBar *toolbar; - // Actions - QAction *newScoreAct; - QAction *editScoreAct; - QAction *newCourseAct; - QAction *editCourseAct; - QAction *statAct; - QAction *firstAct; - QAction *lastAct; - QAction *nextAct; - QAction *prevAct; - - QAction *viewScoreAct; - QAction *viewCourseAct; + QAction *newScoreAction; + QAction *newCourseAction; + QAction *statAction; + + QActionGroup *filterGroup; + QAction *listScoreAction; + QAction *listCourseAction; void createMenus(); void createActions(); - + // Windows + QMainWindow *scoreWin; + QMainWindow *courseWin; }; diff --git a/src/score-dialog.cpp b/src/score-dialog.cpp index 958e7ce..d49884e 100644 --- a/src/score-dialog.cpp +++ b/src/score-dialog.cpp @@ -168,7 +168,7 @@ void ScoreDialog::createTable(QWidget *parent) table->verticalHeader()->setResizeMode(QHeaderView::Stretch); table->horizontalHeader()->hide(); - table->setStyleSheet(ScoreColor::styleSheet()); + //table->setStyleSheet(ScoreColor::styleSheet()); QStringList headers; headers << "" << "Par" << "HCP" << "Score" << "" << "Par" << "HCP" << "Score"; diff --git a/src/table-model.cpp b/src/table-model.cpp index a77be1f..8cadfd2 100644 --- a/src/table-model.cpp +++ b/src/table-model.cpp @@ -14,173 +14,21 @@ QString empty(""); -Qt::ItemFlags ScoreTableModel::flags (const QModelIndex &) +ScoreTableModel::ScoreTableModel(Score * s, Course * c, QObject *parent) + : QAbstractTableModel(parent) { - return 0; -} - -void ScoreTableModel::setMode(int m) -{ - currentMode = m; -} - -int ScoreTableModel::mode(void) -{ - return currentMode; -} - -// Assign the 'sList' to internal 'scoreList'. Set the current score -// to 'currentScore', or to 's'. -void ScoreTableModel::setScore(QList &sList, Score *s) -{ - scoreList = sList; - if (scoreList.size() > 0) { - if (s) { - currentScore = scoreList.indexOf(s); - if (currentScore == -1) - currentScore = 0; - } - score = scoreList.at(currentScore); // NOTE: assumes non-empty list - course = findCourse(score->getClubName(), score->getCourseName()); - } -} - -void ScoreTableModel::setClub(QList &cList) -{ - clubList = cList; - - if (clubList.size() > 0) - club = clubList.at(0); - - if (club) - course = club->getCourse(0); -} - -QString ScoreTableModel::getInfoText() -{ - QString str(""); - - if (score) - str = QString("%1, %2 / [%3/%4]").arg(score->getCourseName()).arg(score->getDate()).arg(currentScore+1).arg(scoreList.count()); - - return str; -} - -QString ScoreTableModel::getCountText() -{ - QString str = QString("%1/%2").arg(currentScore+1, 2).arg(scoreList.count(), 2); - return str; -} - -QString& ScoreTableModel::clubName(void) -{ - if (club) - return club->getName(); - - return empty; -} - -QString& ScoreTableModel::courseName(void) -{ - if (course) - return course->getName(); - - return empty; -} - -Course *ScoreTableModel::findCourse(const QString &clubName, - const QString &courseName) -{ - QListIterator i(clubList); - Club *c; - - while (i.hasNext()) { - c = i.next(); - if (c->getName() == clubName) { - return c->getCourse(courseName); - } - } - return 0; -} - -Club *ScoreTableModel::getClub(void) -{ - return club; -} - -Course *ScoreTableModel::getCourse(void) -{ - return course; -} - -Score *ScoreTableModel::getScore(void) -{ - return score; -} - -void ScoreTableModel::first() -{ - if (score && course) { - currentScore = 0; - score = scoreList.at(currentScore); - course = findCourse(score->getClubName(), score->getCourseName()); - emit dataChanged(createIndex(0, 0), createIndex(ROW_COUNT-1, COL_COUNT-1)); - } -} - -void ScoreTableModel::last() -{ - if (score && course) { - currentScore = scoreList.size() - 1; - score = scoreList.at(currentScore); - course = findCourse(score->getClubName(), score->getCourseName()); - emit dataChanged(createIndex(0, 0), createIndex(ROW_COUNT-1, COL_COUNT-1)); - } -} - -void ScoreTableModel::next() -{ - if (score && course) { - if (currentScore < (scoreList.size() - 1)) { - currentScore++; - score = scoreList.at(currentScore); - course = findCourse(score->getClubName(), score->getCourseName()); - emit dataChanged(createIndex(0, 0), createIndex(ROW_COUNT-1, COL_COUNT-1)); - } - } -} - -void ScoreTableModel::prev() -{ - if (score && course) { - if (currentScore > 0) { - currentScore--; - score = scoreList.at(currentScore); - course = findCourse(score->getClubName(), score->getCourseName()); - emit dataChanged(createIndex(0, 0), createIndex(ROW_COUNT-1, COL_COUNT-1)); - } - } + score = s; + course = c; } int ScoreTableModel::rowCount(const QModelIndex &) const { - return 8; + return ROWS; } int ScoreTableModel::columnCount(const QModelIndex &) const { - return 9 + 2; // 2 for in/out and tot columns -} - -QModelIndex ScoreTableModel::index(int row, int column, const QModelIndex &parent) const -{ - if (hasIndex(row, column, parent)) { - int flag = (parent.column() > 0) ? parent.column() : 0; - return createIndex(row, column, flag); - } - else { - return QModelIndex(); - } + return COLS + 2; // 2 for in/out and tot columns } QVariant ScoreTableModel::data(const QModelIndex &index, int role) const @@ -204,12 +52,11 @@ QVariant ScoreTableModel::data(const QModelIndex &index, int role) const // // COLORS // - if (role == Qt::BackgroundRole) { + if (role == Qt::ForegroundRole) { // Hole numbers 1-18. All hole nums, in, out and tot cell but not // the empty cell. if ((row == ROW_HOLE && col != 10) || row == ROW_HOLE_2) { QBrush brush(ScoreColor::holeBg()); - //QBrush brush(Qt::red); return brush; } if (score && course && (row == ROW_SCORE || row == ROW_SCORE_2)) { @@ -268,11 +115,16 @@ QVariant ScoreTableModel::data(const QModelIndex &index, int role) const // FONT // if (role == Qt::FontRole) { - if (row == ROW_SCORE_2 && col == (COLS+1)) { - QFont font; - font.setBold(true); - return font; - } + if (row == ROW_HOLE || row == ROW_HOLE_2) { + QFont font; + font.setBold(true); + return font; + } + if (row == ROW_SCORE || row == ROW_SCORE_2) { + QFont font; + font.setBold(true); + return font; + } } // // NUMBERS @@ -340,12 +192,6 @@ QVariant ScoreTableModel::data(const QModelIndex &index, int role) const return QVariant(); } -int ScoreTableModel::setItem(int row, int col, int) -{ - emit dataChanged(createIndex(row, col), createIndex(row, col)); - return 1; -} - QVariant ScoreTableModel::headerData(int section, Qt::Orientation orientation, int role) const { // Only vertical header -- horizontal is hidden @@ -354,6 +200,9 @@ QVariant ScoreTableModel::headerData(int section, Qt::Orientation orientation, i if (role == Qt::DisplayRole) { switch(section) { + case ROW_HOLE: + case ROW_HOLE_2: + return QString("Hole"); case ROW_PAR: case ROW_PAR_2: return QString("Par"); @@ -370,3 +219,135 @@ QVariant ScoreTableModel::headerData(int section, Qt::Orientation orientation, i return QVariant(); } +// +// CourseTableModel +// +CourseTableModel::CourseTableModel(Course * c, QObject *parent) + : QAbstractTableModel(parent), course(c) +{ +} + +int CourseTableModel::rowCount(const QModelIndex &) const +{ + return ROWS; +} + +int CourseTableModel::columnCount(const QModelIndex &) const +{ + return COLS + 2; +} + +QVariant CourseTableModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + int row = index.row(); + int col = index.column(); + + // + // ALIGNMENT + // + if (role == Qt::TextAlignmentRole ) { + return Qt::AlignCenter; + } + + // + // FONT + // + if (role == Qt::FontRole) { + if (row == ROW_HOLE || row == ROW_HOLE_2) { + QFont font; + font.setBold(true); + return font; + } + } + // + // COLORS + // + if (role == Qt::ForegroundRole) { + // Hole numbers 1-18. All hole nums, in, out and tot cell but not + // the empty cell. + if ((row == ROW_HOLE && col != 10) || row == ROW_HOLE_2) { + QBrush brush(ScoreColor::holeBg()); + return brush; + } + return QVariant(); + } + // + // NUMBERS + // + if (role == Qt::DisplayRole) { + + if (col == COLS) { + // In/out label + if (row == ROW_HOLE) + return QString("Out"); + if (row == ROW_HOLE_2) + return QString("In"); + + // In/Out for par + if (course && row == ROW_PAR) + return course->getTotal(TotalOut); + if (course && row == ROW_PAR_2) + return course->getTotal(TotalIn); + } + else if (col == (COLS+1)) { + // Total label + if (row == ROW_HOLE_2) + return QString("Tot"); + // Total score + if (course && row == ROW_PAR_2) + return course->getTotal(Total); + } + else { + // data cells + switch(row) { + case ROW_HOLE: + return col + 1; + case ROW_HOLE_2: + return col + 10; + case ROW_PAR: + if (course) + return course->getPar(col); + case ROW_PAR_2: + if (course) + return course->getPar(col + 9); + case ROW_HCP: + if (course) + return course->getHcp(col); + case ROW_HCP_2: + if (course) + return course->getHcp(col + 9); + } + } + } + return QVariant(); +} + +QVariant CourseTableModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + // Only vertical header -- horizontal is hidden + if (orientation == Qt::Horizontal) + return QVariant(); + + if (role == Qt::DisplayRole) { + switch(section) { + case ROW_HOLE: + case ROW_HOLE_2: + return QString("Hole"); + case ROW_PAR: + case ROW_PAR_2: + return QString("Par"); + case ROW_HCP: + case ROW_HCP_2: + return QString("HCP"); + case ROW_LEN: + case ROW_LEN_2: + return QString("Len"); + } + return QVariant(); + } + + return QVariant(); +} diff --git a/src/table-model.h b/src/table-model.h index 62bfdd2..c6f16c4 100644 --- a/src/table-model.h +++ b/src/table-model.h @@ -16,72 +16,65 @@ class ScoreTableModel : public QAbstractTableModel { - - Q_OBJECT + Q_OBJECT public: - enum { ViewMode = 0, EditMode = 1 }; - - ScoreTableModel(QObject *parent = 0) : QAbstractTableModel(parent) - { - currentScore = 0; - score = 0; - club = 0; - course = 0; - currentMode = ViewMode; - } - Qt::ItemFlags flags ( const QModelIndex & index ); - void setMode(int m); - int mode(void); - void setScore(QList &sList, Score *score = 0); - void setClub(QList &cList); - Score *getScore(void); - Club *getClub(void); - Course *getCourse(void); - - Course *findCourse(const QString &clubName, const QString &courseName); - QString& clubName(void); - QString& courseName(void); - int rowCount(const QModelIndex & parent) const; - int columnCount(const QModelIndex & parent) const; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; - QVariant data(const QModelIndex & index, int role) const; - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - - int setItem(int row, int col, int data); + ScoreTableModel(Score *, Course *, QObject *parent = 0); - QString getInfoText(); - QString getCountText(); + int rowCount(const QModelIndex & parent) const; + int columnCount(const QModelIndex & parent) const; + QVariant data(const QModelIndex & index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; - void next(); - void prev(); - void first(); - void last(); +private: + enum { + ROWS = 8, + COLS = 9 + }; + enum { + ROW_HOLE = 0, + ROW_PAR = 1, + ROW_HCP = 2, + ROW_SCORE = 3, + ROW_HOLE_2 = 4, + ROW_PAR_2 = 5, + ROW_HCP_2 = 6, + ROW_SCORE_2 = 7 + }; + // Current data pointers + Score *score; + Club *club; + Course *course; +}; - private: - int currentMode; - enum { - ROWS = 8, - COLS = 9 - }; - enum { - ROW_HOLE = 0, - ROW_PAR = 1, - ROW_HCP = 2, - ROW_SCORE = 3, - ROW_HOLE_2 = 4, - ROW_PAR_2 = 5, - ROW_HCP_2 = 6, - ROW_SCORE_2 = 7 - }; +class CourseTableModel : public QAbstractTableModel +{ + Q_OBJECT - QList scoreList; - QList clubList; +public: + CourseTableModel(Course *, QObject *parent = 0); - int currentScore; + int rowCount(const QModelIndex & parent) const; + int columnCount(const QModelIndex & parent) const; + QVariant data(const QModelIndex & index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; - // Current data pointers - Score *score; - Club *club; - Course *course; +private: + enum { + ROWS = 8, + COLS = 9 + }; + enum { + ROW_HOLE = 0, + ROW_PAR = 1, + ROW_HCP = 2, + ROW_LEN = 3, + ROW_HOLE_2 = 4, + ROW_PAR_2 = 5, + ROW_HCP_2 = 6, + ROW_LEN_2 = 7 + }; + // Current data pointers + Club *club; + Course *course; }; diff --git a/src/xml-dom-parser.cpp b/src/xml-dom-parser.cpp index 7964c65..bc8b7e9 100644 --- a/src/xml-dom-parser.cpp +++ b/src/xml-dom-parser.cpp @@ -107,17 +107,17 @@ int ClubXmlHandler::parse(QString &fileName) QDomElement courseElement = clubElement.firstChildElement("course"); while (!courseElement.isNull()) { - Course *course = new Course(courseElement); - club->addCourse(course); + Course *course = new Course(courseElement, club); + club->addCourse(course); - QDomElement holeElement = courseElement.firstChildElement("hole"); - while (!holeElement.isNull()) { - Hole *hole = new Hole(holeElement); - course->addHole(hole); + QDomElement holeElement = courseElement.firstChildElement("hole"); + while (!holeElement.isNull()) { + Hole *hole = new Hole(holeElement); + course->addHole(hole); - holeElement = holeElement.nextSiblingElement("hole"); - } - courseElement = courseElement.nextSiblingElement("course"); + holeElement = holeElement.nextSiblingElement("hole"); + } + courseElement = courseElement.nextSiblingElement("course"); } list << club; clubElement = clubElement.nextSiblingElement("club"); -- 1.7.9.5