98351e23fc5302fa03e59aa9d8daa2678380dea9
[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");
16 QString mmcDir("/media/mmc1");
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   setCentralWidget(centralWidget);
40
41   loadScoreFile(scoreFile, scoreList);
42   loadClubFile(clubFile, clubList);
43
44   // Sort the scores based on dates
45   qSort(scoreList.begin(), scoreList.end(), dateLessThan); 
46
47   createActions();
48   createMenus();
49
50   createTableView(scoreList, clubList);
51   //createTreeView(scoreList, parent);
52   createStatusBar();
53
54   createLayout(centralWidget);
55 }
56
57 void MainWindow::loadSettings(void)
58 {
59   bool external = false;
60
61   QDir mmc(mmcDir);
62   if (mmc.exists())
63     external = true;
64
65   // TODO: make via user option, automatic will never work
66   external = false;
67
68 #ifndef Q_WS_HILDON
69   dataDir = "./" + dataDirName;
70 #else
71   if (external) {
72     dataDir = mmcDir + "/" + appName + "/" + dataDirName;
73   }
74   else {
75     dataDir = topDir + "/" + appName + "/" + dataDirName;
76   }
77 #endif
78   scoreFile = dataDir + "/" + scoreFileName;
79   clubFile = dataDir + "/" + clubFileName;
80
81   QDir dir(dataDir);
82   if (!dir.exists())
83     if (!dir.mkpath(dataDir)) {
84       qWarning() << "Unable to create: " + dataDir;
85       return;
86     }
87   qDebug() << "Data is at:" + dataDir;
88 }
89
90 void MainWindow::createLayout(QWidget *parent)
91 {
92
93   buttonLayout = new QVBoxLayout;
94   //labelLayout->addStretch();
95   buttonLayout->addWidget(nextButton);
96   buttonLayout->addWidget(prevButton);
97   buttonLayout->addWidget(lastButton);
98   buttonLayout->addWidget(firstButton);
99
100   tableLayout = new QVBoxLayout;
101   tableLayout->addWidget(table);
102
103   QHBoxLayout *mainLayout = new QHBoxLayout(parent);
104   mainLayout->addLayout(tableLayout);
105   mainLayout->addLayout(buttonLayout);
106   parent->setLayout(mainLayout);
107 }
108
109 // Setup 'score' tab view
110 void MainWindow::createTableView(QList<Score *> &scoreList, QList <Club *> &clubList)
111 {
112   table = new QTableView;
113
114   nextButton = new QPushButton(tr("Next"));
115   prevButton = new QPushButton(tr("Prev"));
116   firstButton = new QPushButton(tr("First"));
117   lastButton = new QPushButton(tr("Last"));
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
126   table->showGrid();
127
128   table->setModel(scoreTableModel);
129   QItemSelectionModel selectionModel();
130   table->setSelectionMode(QAbstractItemView::NoSelection);
131
132   scoreTableModel->setScore(scoreList);
133   scoreTableModel->setClub(clubList);
134
135   // Fill out all the space with the tables
136   table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
137   table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
138   table->verticalHeader()->setAutoFillBackground(true);
139   table->horizontalHeader()->hide();
140 }
141
142 // When selection down in 'stat' view, this is called.
143 void MainWindow::updateTreeView(const QModelIndex & index)
144 {
145   QString scope("Scope");
146   QString count("Rounds");
147   QString scoreAvg("Score (avg.)");
148   QString scoreBest("Score (best)");
149   QString score("Total");
150   QString scoreIn("Total in");
151   QString scoreOut("Total out");
152
153   QVariant str = scoreTreeModel->data(index, Qt::DisplayRole);
154   QVariant type = scoreTreeModel->data(index, ScoreTreeModel::Type);
155
156   qDebug() << "update(" << index.row() << "/" << index.column() << "):" << str << type;
157
158   tableModel->setData(tableModel->index(0, 0, QModelIndex()), scope);
159   tableModel->setData(tableModel->index(0, 1, QModelIndex()), str);
160
161   if (type == TreeItem::TypeDate) {
162     tableModel->setData(tableModel->index(1, 0, QModelIndex()), count);
163     tableModel->setData(tableModel->index(2, 0, QModelIndex()), scoreAvg);
164     tableModel->setData(tableModel->index(3, 0, QModelIndex()), scoreBest);
165   }    
166   else if (type == TreeItem::TypeScore) {
167     QVariant value = scoreTreeModel->data(index, ScoreTreeModel::Total);
168     tableModel->setData(tableModel->index(1, 0, QModelIndex()), score);
169     tableModel->setData(tableModel->index(1, 1, QModelIndex()), value);
170
171     value = scoreTreeModel->data(index, ScoreTreeModel::TotalOut);
172     tableModel->setData(tableModel->index(2, 0, QModelIndex()), scoreOut);
173     tableModel->setData(tableModel->index(2, 1, QModelIndex()), value);
174
175     value = scoreTreeModel->data(index, ScoreTreeModel::TotalIn);
176     tableModel->setData(tableModel->index(3, 0, QModelIndex()), scoreIn);
177     tableModel->setData(tableModel->index(3, 1, QModelIndex()), value);
178   }
179 }
180
181 void MainWindow::createStatusBar()
182 {
183 #if 0
184   // TODO: use toolbar or buttons. Toolbar seems not to be ready and
185   // requires more work.
186   toolbar = addToolBar(tr("foo"));
187   toolbar->addAction(firstAct);
188   toolbar->addAction(lastAct);
189   toolbar->addAction(prevAct);
190   toolbar->addAction(nextAct);
191 #endif
192   updateStatusBar();
193 }
194
195 void MainWindow::createActions()
196 {
197   newScoreAct = new QAction(tr("New Score"), this);
198   connect(newScoreAct, SIGNAL(triggered()), this, SLOT(newScore()));
199
200   newCourseAct = new QAction(tr("New Course"), this);
201   connect(newCourseAct, SIGNAL(triggered()), this, SLOT(newCourse()));
202
203   editScoreAct = new QAction(tr("Edit Score"), this);
204   connect(editScoreAct, SIGNAL(triggered()), this, SLOT(editScore()));
205
206   editCourseAct = new QAction(tr("Edit Course"), this);
207   connect(editCourseAct, SIGNAL(triggered()), this, SLOT(editCourse()));
208
209 #if 0
210   viewScoreAct = new QAction(tr("&View Scores"), this);
211   connect(viewScoreAct, SIGNAL(triggered()), this, SLOT(viewScore()));
212
213   viewCourseAct = new QAction(tr("&View Courses"), this);
214   connect(viewCourseAct, SIGNAL(triggered()), this, SLOT(viewCourse()));
215
216   viewStatisticAct = new QAction(tr("&View Statistics"), this);
217   connect(viewStatisticAct, SIGNAL(triggered()), this, SLOT(viewStatistic()));
218 #endif
219
220   nextAct = new QAction(tr( "   Next   "), this);
221   connect(nextAct, SIGNAL(triggered()), this, SLOT(nextButtonClicked()));
222
223   prevAct = new QAction("   Prev   ", this);
224   connect(prevAct, SIGNAL(triggered()), this, SLOT(prevButtonClicked()));
225
226   firstAct = new QAction(tr("   First  "), this);
227   connect(firstAct, SIGNAL(triggered()), this, SLOT(firstButtonClicked()));
228
229   lastAct = new QAction(tr( "   Last   "), this);
230   connect(lastAct, SIGNAL(triggered()), this, SLOT(lastButtonClicked()));
231 }
232
233 void MainWindow::createMenus()
234 {
235   menu = menuBar()->addMenu("");
236 #if 0
237   menu->addAction(viewScoreAct);
238   menu->addAction(viewCourseAct);
239   menu->addAction(viewStatisticAct);
240 #endif
241   menu->addAction(newScoreAct);
242   menu->addAction(newCourseAct);
243   menu->addAction(editScoreAct);
244   menu->addAction(editCourseAct);
245 }
246
247 void MainWindow::updateStatusBar()
248 {
249   setWindowTitle(scoreTableModel->getInfoText());
250 }
251
252 void MainWindow::firstButtonClicked()
253 {
254   scoreTableModel->first();
255   updateStatusBar();
256 }
257
258 void MainWindow::lastButtonClicked()
259 {
260   scoreTableModel->last();
261   updateStatusBar();
262 }
263
264 void MainWindow::nextButtonClicked()
265 {
266   scoreTableModel->next();
267   updateStatusBar();
268 }
269
270 void MainWindow::prevButtonClicked()
271 {
272   scoreTableModel->prev();
273   updateStatusBar();
274 }
275
276 // FIXME: dup code from table-model.cpp
277 Club *MainWindow::findClub(QString &name)
278 {
279   QListIterator<Club *> i(clubList);
280   Club *c;
281
282   while (i.hasNext()) {
283     c = i.next();
284     if (c->getName() == name)
285       return c;
286   }
287   return 0;
288 }
289
290 void MainWindow::newCourse()
291 {
292   CourseSelectDialog *selectDialog = new CourseSelectDialog(this);
293
294   int result = selectDialog->exec();
295   if (result) {
296     QString clubName;
297     QString courseName;
298     QString date;
299
300     selectDialog->results(clubName, courseName);
301
302     CourseDialog *courseDialog = new CourseDialog(this);
303     courseDialog->init();
304
305     QString title = "New Course: " + clubName + "," + courseName;
306     courseDialog->setWindowTitle(title);
307
308     int result = courseDialog->exec();
309     if (result) {
310       QVector<QString> par(18);
311       QVector<QString> hcp(18);
312       QVector<QString> len(18);
313
314       courseDialog->results(par, hcp, len);
315
316       Course *course = 0;
317       Club *club = findClub(clubName);
318       if (club) {
319         course = club->getCourse(courseName);
320         if (course) {
321           qDebug() << "Error: club/course already in the database";
322           return;
323         }
324         else {
325           course = new Course(courseName, par, hcp);
326           club->addCourse(course);
327         }
328       }
329       else {
330         // New club and course
331         club = new Club(clubName);
332         course = new Course(courseName, par, hcp);
333         club->addCourse(course);
334         clubList << club;
335       }
336       saveClubFile(clubFile, clubList);
337
338       // TODO: does this really work? No mem leaks?
339       scoreTableModel->setClub(clubList);
340     }
341   }
342 }
343
344 void MainWindow::editCourse()
345 {
346   Course *course = scoreTableModel->getCourse();
347
348   if (!course) {
349     qWarning() << "No course on edit";
350     return;
351   }
352
353   CourseDialog *courseDialog = new CourseDialog(this);
354   courseDialog->init(course);
355
356   QString title = "Edit Course: " + course->getName();
357   courseDialog->setWindowTitle(title);
358   
359   int result = courseDialog->exec();
360   if (result) {
361     QVector<QString> par(18);
362     QVector<QString> hcp(18);
363     QVector<QString> len(18);
364     
365     courseDialog->results(par, hcp, len);
366     
367     course->update(par, hcp, len);
368     saveClubFile(clubFile, clubList);
369   }
370 }
371
372 void MainWindow::newScore()
373 {
374   SelectDialog *selectDialog = new SelectDialog(this);
375
376   selectDialog->init(clubList);
377
378   int result = selectDialog->exec();
379   if (result) {
380     QString clubName;
381     QString courseName;
382     QString date;
383
384     selectDialog->results(clubName, courseName, date);
385
386     ScoreDialog *scoreDialog = new ScoreDialog(this);
387     QString title = "New Score: " + courseName + ", " + date;
388     scoreDialog->setWindowTitle(title);
389
390     Club *club = findClub(clubName);
391     if (!club) {
392       qWarning() << "Error: no such club:" << clubName;
393       return;
394     }
395     Course *course = club->getCourse(courseName);
396     if (!course) {
397       qWarning() << "Error: no such course:" << courseName;
398       return;
399     }
400     scoreDialog->init(course);
401     result = scoreDialog->exec();
402     if (result) {
403       QVector<QString> scores(18);
404
405       scoreDialog->results(scores);
406       Score *score = new Score(scores, clubName, courseName, date);
407       scoreList << score;
408
409       // Sort the scores based on dates
410       qSort(scoreList.begin(), scoreList.end(), dateLessThan); 
411       // Save it
412       saveScoreFile(scoreFile, scoreList);
413
414       // TODO: does this really work? No mem leaks?
415       scoreTableModel->setScore(scoreList, score);
416       updateStatusBar();
417     }
418   }
419 }
420
421 void MainWindow::editScore()
422 {
423   Course *course = scoreTableModel->getCourse();
424   Score *score = scoreTableModel->getScore();
425   QString date = score->getDate();
426
427   ScoreDialog *scoreDialog = new ScoreDialog(this);
428   
429   QString title = "Edit Score: " + course->getName() + ", " + date;
430   scoreDialog->setWindowTitle(title);
431
432   scoreDialog->init(course, score);
433
434   int result = scoreDialog->exec();
435
436   if (result) {
437     QVector<QString> scores(18);
438
439     scoreDialog->results(scores);
440     
441     score->update(scores);
442
443     // Sort the scores based on dates
444     qSort(scoreList.begin(), scoreList.end(), dateLessThan); 
445     // Save it
446     saveScoreFile(scoreFile, scoreList);
447
448     // TODO: does this really work? No mem leaks?
449     scoreTableModel->setScore(scoreList, score);
450     updateStatusBar();
451   }
452 }
453
454 void MainWindow::loadScoreFile(QString &fileName, QList<Score *> &list)
455 {
456   ScoreXmlHandler handler(list);
457
458   if (handler.parse(fileName))
459     qDebug() << "File loaded:" << fileName << " entries:" << list.size();
460 }
461
462 void MainWindow::saveScoreFile(QString &fileName, QList<Score *> &list)
463 {
464   ScoreXmlHandler handler(list);
465
466   if (handler.save(fileName))
467     // TODO: banner
468     qDebug() << "File saved:" << fileName << " entries:" << list.size();
469   else
470     qWarning() << "Unable to save:" << fileName;
471 }
472
473 void MainWindow::loadClubFile(QString &fileName, QList<Club *> &list)
474 {
475   ClubXmlHandler handler(list);
476
477   if (handler.parse(fileName))
478     qDebug() << "File loaded:" << fileName << " entries:" << list.size();
479 }
480
481 void MainWindow::saveClubFile(QString &fileName, QList<Club *> &list)
482 {
483   ClubXmlHandler handler(list);
484
485   if (handler.save(fileName))
486     // TODO: banner
487     qDebug() << "File saved:" << fileName << " entries:" << list.size();
488   else
489     qWarning() << "Unable to save:" << fileName;
490
491 }