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