d622f56ddde79b683c3a629671f22a5b3f8ad023
[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 #ifndef Q_WS_HILDON
62   topDir = ".";
63 #endif
64
65   QDir mmc(mmcDir);
66   if (mmc.exists())
67     external = true;
68
69   // TODO: make via user option, automatic will never work
70   external = false;
71
72   if (external) {
73     dataDir = mmcDir + "/" + appName + "/" + dataDirName;
74   }
75   else {
76     dataDir = topDir + "/" + appName + "/" + dataDirName;
77   }
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   CourseDialog *courseDialog = new CourseDialog(this);
349   courseDialog->init(course);
350
351   QString title = "Edit Course: " + course->getName();
352   courseDialog->setWindowTitle(title);
353   
354   int result = courseDialog->exec();
355   if (result) {
356     QVector<QString> par(18);
357     QVector<QString> hcp(18);
358     QVector<QString> len(18);
359     
360     courseDialog->results(par, hcp, len);
361     
362     course->update(par, hcp, len);
363     saveClubFile(clubFile, clubList);
364   }
365 }
366
367 void MainWindow::newScore()
368 {
369   SelectDialog *selectDialog = new SelectDialog(this);
370
371   selectDialog->init(clubList);
372
373   int result = selectDialog->exec();
374   if (result) {
375     QString clubName;
376     QString courseName;
377     QString date;
378
379     selectDialog->results(clubName, courseName, date);
380
381     ScoreDialog *scoreDialog = new ScoreDialog(this);
382     QString title = "New Score: " + courseName + ", " + date;
383     scoreDialog->setWindowTitle(title);
384
385     Club *club = findClub(clubName);
386     if (!club) {
387       qWarning() << "Error: no such club:" << clubName;
388       return;
389     }
390     Course *course = club->getCourse(courseName);
391     if (!course) {
392       qWarning() << "Error: no such course:" << courseName;
393       return;
394     }
395     scoreDialog->init(course);
396     result = scoreDialog->exec();
397     if (result) {
398       QVector<QString> scores(18);
399
400       scoreDialog->results(scores);
401       Score *score = new Score(scores, clubName, courseName, date);
402       scoreList << score;
403
404       // Sort the scores based on dates
405       qSort(scoreList.begin(), scoreList.end(), dateLessThan); 
406       // Save it
407       saveScoreFile(scoreFile, scoreList);
408
409       // TODO: does this really work? No mem leaks?
410       scoreTableModel->setScore(scoreList, score);
411       updateStatusBar();
412     }
413   }
414 }
415
416 void MainWindow::editScore()
417 {
418   Course *course = scoreTableModel->getCourse();
419   Score *score = scoreTableModel->getScore();
420   QString date = score->getDate();
421
422   ScoreDialog *scoreDialog = new ScoreDialog(this);
423   
424   QString title = "Edit Score: " + course->getName() + ", " + date;
425   scoreDialog->setWindowTitle(title);
426
427   scoreDialog->init(course, score);
428
429   int result = scoreDialog->exec();
430
431   if (result) {
432     QVector<QString> scores(18);
433
434     scoreDialog->results(scores);
435     
436     score->update(scores);
437
438     // Sort the scores based on dates
439     qSort(scoreList.begin(), scoreList.end(), dateLessThan); 
440     // Save it
441     saveScoreFile(scoreFile, scoreList);
442
443     // TODO: does this really work? No mem leaks?
444     scoreTableModel->setScore(scoreList, score);
445     updateStatusBar();
446   }
447 }
448
449 void MainWindow::loadScoreFile(QString &fileName, QList<Score *> &list)
450 {
451   ScoreXmlHandler handler(list);
452
453   if (handler.parse(fileName))
454     qDebug() << "File loaded:" << fileName << " entries:" << list.size();
455 }
456
457 void MainWindow::saveScoreFile(QString &fileName, QList<Score *> &list)
458 {
459   ScoreXmlHandler handler(list);
460
461   if (handler.save(fileName))
462     // TODO: banner
463     qDebug() << "File saved:" << fileName << " entries:" << list.size();
464   else
465     qWarning() << "Unable to save:" << fileName;
466 }
467
468 void MainWindow::loadClubFile(QString &fileName, QList<Club *> &list)
469 {
470   ClubXmlHandler handler(list);
471
472   if (handler.parse(fileName))
473     qDebug() << "File loaded:" << fileName << " entries:" << list.size();
474 }
475
476 void MainWindow::saveClubFile(QString &fileName, QList<Club *> &list)
477 {
478   ClubXmlHandler handler(list);
479
480   if (handler.save(fileName))
481     // TODO: banner
482     qDebug() << "File saved:" << fileName << " entries:" << list.size();
483   else
484     qWarning() << "Unable to save:" << fileName;
485
486 }