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