More robust handling of cases where no data files
[scorecard] / src / main-window.cpp
1 #include <QtGui>
2 #include <QDirModel>
3 #include <QTreeView>
4 #include <QListView>
5 #include <QStandardItemModel>
6
7 #include "main-window.h"
8 #include "score-dialog.h"
9 #include "course-dialog.h"
10 #include "tree-widget.h"
11 #include "xml-parser.h"
12 #include "xml-dom-parser.h"
13
14 QString scoreFile("data/score.xml");
15 QString scoreFileWr("data/score-save.xml");
16 QString clubFile("data/club.xml");
17 QString clubFileWr("data/club-save.xml");
18
19 MainWindow::MainWindow(QMainWindow *parent) : QMainWindow(parent)
20 {
21   resize(800, 480);
22
23   QWidget *centralWidget = new QWidget(this);
24
25   // TODO: move to proper function
26   tableViewFront = new QTableView(centralWidget);
27   tableViewBack = new QTableView(centralWidget);
28
29   setCentralWidget(centralWidget);
30
31   loadScoreFile(scoreFile, scoreList);
32   loadClubFile(clubFile, clubList);
33
34 #ifdef TEST
35   saveScoreFile(scoreFileWr, scoreList);
36   saveClubFile(clubFileWr, clubList);
37 #endif
38
39   createTableView(scoreList, clubList);
40   //createTreeView(scoreList, parent);
41   createStatusBar();
42
43   createLayout(centralWidget);
44
45   createActions();
46   createMenus();
47 }
48
49 void MainWindow::createLayout(QWidget *parent)
50 {
51   buttonLayout = new QVBoxLayout;
52   //labelLayout->addStretch();
53   buttonLayout->addWidget(nextButton);
54   buttonLayout->addWidget(prevButton);
55   buttonLayout->addWidget(lastButton);
56   buttonLayout->addWidget(firstButton);
57
58   tableLayout = new QVBoxLayout;
59   tableLayout->addWidget(tableViewFront);
60   tableLayout->addWidget(tableViewBack);
61
62   QHBoxLayout *mainLayout = new QHBoxLayout(parent);
63   mainLayout->addLayout(tableLayout);
64   mainLayout->addLayout(buttonLayout);
65   setLayout(mainLayout);
66 }
67
68 // Setup 'score' tab view
69 void MainWindow::createTableView(QList<Score *> &scoreList, QList <Club *> &clubList)
70 {
71   nextButton = new QPushButton(tr(">"));
72   prevButton = new QPushButton(tr("<"));
73   firstButton = new QPushButton(tr("<<"));
74   lastButton = new QPushButton(tr(">>"));
75
76   connect(nextButton, SIGNAL(clicked()), this, SLOT(nextButtonClicked()));
77   connect(prevButton, SIGNAL(clicked()), this, SLOT(prevButtonClicked()));
78   connect(firstButton, SIGNAL(clicked()), this, SLOT(firstButtonClicked()));
79   connect(lastButton, SIGNAL(clicked()), this, SLOT(lastButtonClicked()));
80
81   scoreTableModel = new ScoreTableModel();
82   scoreTableModel->setScore(scoreList);
83   scoreTableModel->setClub(clubList);
84
85   tableViewFront->showGrid();
86   tableViewBack->showGrid();
87
88   tableViewFront->setModel(scoreTableModel);
89   tableViewBack->setModel(scoreTableModel);
90
91   // Flag model items which one belongs to front and back nines
92   tableViewFront->setRootIndex(scoreTableModel->index(0, 0));
93   tableViewBack->setRootIndex(scoreTableModel->index(0, 1));
94
95   // Fill out all the space with the tables
96   tableViewFront->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
97   tableViewFront->verticalHeader()->setResizeMode(QHeaderView::Stretch);
98   tableViewBack->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
99   tableViewBack->verticalHeader()->setResizeMode(QHeaderView::Stretch);
100 }
101
102 // When selection down in 'stat' view, this is called.
103 void MainWindow::updateTreeView(const QModelIndex & index)
104 {
105   QString scope("Scope");
106   QString count("Rounds");
107   QString scoreAvg("Score (avg.)");
108   QString scoreBest("Score (best)");
109   QString score("Total");
110   QString scoreIn("Total in");
111   QString scoreOut("Total out");
112
113   QVariant str = scoreTreeModel->data(index, Qt::DisplayRole);
114   QVariant type = scoreTreeModel->data(index, ScoreTreeModel::Type);
115
116   qDebug() << "update(" << index.row() << "/" << index.column() << "):" << str << type;
117
118   tableModel->setData(tableModel->index(0, 0, QModelIndex()), scope);
119   tableModel->setData(tableModel->index(0, 1, QModelIndex()), str);
120
121   if (type == TreeItem::TypeDate) {
122     tableModel->setData(tableModel->index(1, 0, QModelIndex()), count);
123     tableModel->setData(tableModel->index(2, 0, QModelIndex()), scoreAvg);
124     tableModel->setData(tableModel->index(3, 0, QModelIndex()), scoreBest);
125   }    
126   else if (type == TreeItem::TypeScore) {
127     QVariant value = scoreTreeModel->data(index, ScoreTreeModel::Total);
128     tableModel->setData(tableModel->index(1, 0, QModelIndex()), score);
129     tableModel->setData(tableModel->index(1, 1, QModelIndex()), value);
130
131     value = scoreTreeModel->data(index, ScoreTreeModel::TotalOut);
132     tableModel->setData(tableModel->index(2, 0, QModelIndex()), scoreOut);
133     tableModel->setData(tableModel->index(2, 1, QModelIndex()), value);
134
135     value = scoreTreeModel->data(index, ScoreTreeModel::TotalIn);
136     tableModel->setData(tableModel->index(3, 0, QModelIndex()), scoreIn);
137     tableModel->setData(tableModel->index(3, 1, QModelIndex()), value);
138   }
139 }
140
141 void MainWindow::createStatusBar()
142 {
143   updateStatusBar();
144 }
145
146 void MainWindow::createActions()
147 {
148   newScoreAct = new QAction(tr("&New Score"), this);
149   connect(newScoreAct, SIGNAL(triggered()), this, SLOT(newScore()));
150
151   newCourseAct = new QAction(tr("&New Course"), this);
152   connect(newCourseAct, SIGNAL(triggered()), this, SLOT(newCourse()));
153
154 #if 0
155   viewScoreAct = new QAction(tr("&View Scores"), this);
156   connect(viewScoreAct, SIGNAL(triggered()), this, SLOT(viewScore()));
157
158   viewCourseAct = new QAction(tr("&View Courses"), this);
159   connect(viewCourseAct, SIGNAL(triggered()), this, SLOT(viewCourse()));
160
161   viewStatisticAct = new QAction(tr("&View Statistics"), this);
162   connect(viewStatisticAct, SIGNAL(triggered()), this, SLOT(viewStatistic()));
163 #endif
164 }
165
166 void MainWindow::createMenus()
167 {
168   menu = menuBar()->addMenu(tr("fremantle"));
169 #if 0
170   menu->addAction(viewScoreAct);
171   menu->addAction(viewCourseAct);
172   menu->addAction(viewStatisticAct);
173 #endif
174   menu->addAction(newScoreAct);
175   menu->addAction(newCourseAct);
176 }
177
178 void MainWindow::updateStatusBar()
179 {
180   setWindowTitle(scoreTableModel->getInfoText());
181 }
182
183 void MainWindow::firstButtonClicked()
184 {
185   scoreTableModel->first();
186   updateStatusBar();
187 }
188
189 void MainWindow::lastButtonClicked()
190 {
191   scoreTableModel->last();
192   updateStatusBar();
193 }
194
195 void MainWindow::nextButtonClicked()
196 {
197   scoreTableModel->next();
198   updateStatusBar();
199 }
200
201 void MainWindow::prevButtonClicked()
202 {
203   scoreTableModel->prev();
204   updateStatusBar();
205 }
206
207 // FIXME: dup code from table-model.cpp
208 Club *MainWindow::findClub(QString &name)
209 {
210   QListIterator<Club *> i(clubList);
211   Club *c;
212
213   while (i.hasNext()) {
214     c = i.next();
215     if (c->getName() == name)
216       return c;
217   }
218   return 0;
219 }
220
221 void MainWindow::newCourse()
222 {
223   CourseSelectDialog *selectDialog = new CourseSelectDialog(this);
224
225   int result = selectDialog->exec();
226   if (result) {
227     QString clubName;
228     QString courseName;
229     QString date;
230
231     selectDialog->results(clubName, courseName);
232
233     CourseDialog *courseDialog = new CourseDialog(this);
234
235     QString title = "New Course : " + clubName + "," + courseName;
236     courseDialog->setWindowTitle(title);
237
238     int result = courseDialog->exec();
239     if (result) {
240       QVector<QString> par(18);
241       QVector<QString> hcp(18);
242       QVector<QString> len(18);
243
244       courseDialog->results(par, hcp, len);
245
246       Course *course = 0;
247       Club *club = findClub(clubName);
248       if (club) {
249         course = club->getCourse(courseName);
250         if (course) {
251           qDebug() << "Error: club/course already in the database";
252           return;
253         }
254         else {
255           course = new Course(courseName, par, hcp);
256           club->addCourse(course);
257         }
258       }
259       else {
260         club = new Club(clubName);
261         course = new Course(courseName, par, hcp);
262         club->addCourse(course);
263         clubList << club;
264       }
265       saveClubFile(clubFile, clubList);
266
267       // TODO: does this really work? No mem leaks?
268       scoreTableModel->setClub(clubList);
269
270     }
271   }
272 }
273
274 void MainWindow::newScore()
275 {
276   SelectDialog *selectDialog = new SelectDialog(this);
277
278   selectDialog->init(clubList);
279
280   int result = selectDialog->exec();
281   if (result) {
282     QString clubName;
283     QString courseName;
284     QString date;
285
286     selectDialog->results(clubName, courseName, date);
287
288     ScoreDialog *scoreDialog = new ScoreDialog(this);
289     QString title = "New Score : " + courseName + ", " + date;
290     scoreDialog->setWindowTitle(title);
291
292     Club *club = findClub(clubName);
293     if (!club) {
294       qDebug() << "Error: no such club: " << clubName;
295       return;
296     }
297     Course *course = club->getCourse(courseName);
298     if (!course) {
299       qDebug() << "Error: no such course: " << courseName;
300       return;
301     }
302
303     scoreDialog->init(course);
304
305     result = scoreDialog->exec();
306
307     if (result) {
308       QVector<QString> scores(18);
309
310       scoreDialog->results(scores);
311       Score *score = new Score(scores, clubName, courseName, date);
312       scoreList << score;
313
314       saveScoreFile(scoreFile, scoreList);
315
316       // TODO: does this really work? No mem leaks?
317       scoreTableModel->setScore(scoreList);
318       lastButtonClicked();
319     }
320   }
321 }
322
323 void MainWindow::loadScoreFile(QString &fileName, QList<Score *> &list)
324 {
325   ScoreXmlHandler handler(list);
326
327   if (handler.parse(fileName))
328     qDebug() << "Score loaded : " << fileName;
329   qDebug() << "Score entries : " << list.size();
330 }
331
332 void MainWindow::saveScoreFile(QString &fileName, QList<Score *> &list)
333 {
334   ScoreXmlHandler handler(list);
335
336   if (handler.save(fileName))
337     qDebug() << "Score saved : " << fileName << 
338       " entries : " << list.size();
339 }
340
341 void MainWindow::loadClubFile(QString &fileName, QList<Club *> &list)
342 {
343   ClubXmlHandler handler(list);
344
345   if (handler.parse(fileName))
346     qDebug() << "Club loaded: " << fileName;
347   qDebug() << "Club entries : " << list.size();
348 }
349
350 void MainWindow::saveClubFile(QString &fileName, QList<Club *> &list)
351 {
352   ClubXmlHandler handler(list);
353
354   if (handler.save(fileName))
355     qDebug() << "Club saved : " << fileName << 
356       " entries : " << list.size();
357 }