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