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