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