Merge two table views into one in main window
[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   // TODO: move to proper function
40   table = new QTableView(centralWidget);
41
42   setCentralWidget(centralWidget);
43
44   loadScoreFile(scoreFile, scoreList);
45   loadClubFile(clubFile, clubList);
46
47   // Sort the scores based on dates
48   qSort(scoreList.begin(), scoreList.end(), dateLessThan); 
49
50   createTableView(scoreList, clubList);
51   //createTreeView(scoreList, parent);
52   createStatusBar();
53
54   createLayout(centralWidget);
55
56   createActions();
57   createMenus();
58 }
59
60 void MainWindow::loadSettings(void)
61 {
62   bool external = false;
63
64 #ifndef Q_WS_HILDON
65   topDir = ".";
66 #endif
67
68   QDir mmc(mmcDir);
69   if (mmc.exists())
70     external = true;
71
72   if (external) {
73     dataDir = mmcDir + dataDirName;
74   }
75   else {
76     dataDir = topDir + dataDirName;
77   }
78   scoreFile = dataDir + scoreFileName;
79   clubFile = dataDir + clubFileName;
80
81   QDir dir(dataDir);
82   if (!dir.exists())
83     if (!dir.mkdir(dataDir)) {
84       // TODO: mkdir does not work...
85       qDebug() << "Unable to create: " + dataDir;
86       return;
87     }
88   qDebug() << "Data is at: " + dataDir;
89 }
90
91 void MainWindow::createLayout(QWidget *parent)
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   setLayout(mainLayout);
107 }
108
109 // Setup 'score' tab view
110 void MainWindow::createTableView(QList<Score *> &scoreList, QList <Club *> &clubList)
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   // Flag model items which one belongs to front and back nines
131   table->setRootIndex(scoreTableModel->index(0, 1));
132
133   // Fill out all the space with the tables
134   table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
135   table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
136   table->horizontalHeader()->hide();
137 }
138
139 // When selection down in 'stat' view, this is called.
140 void MainWindow::updateTreeView(const QModelIndex & index)
141 {
142   QString scope("Scope");
143   QString count("Rounds");
144   QString scoreAvg("Score (avg.)");
145   QString scoreBest("Score (best)");
146   QString score("Total");
147   QString scoreIn("Total in");
148   QString scoreOut("Total out");
149
150   QVariant str = scoreTreeModel->data(index, Qt::DisplayRole);
151   QVariant type = scoreTreeModel->data(index, ScoreTreeModel::Type);
152
153   qDebug() << "update(" << index.row() << "/" << index.column() << "):" << str << type;
154
155   tableModel->setData(tableModel->index(0, 0, QModelIndex()), scope);
156   tableModel->setData(tableModel->index(0, 1, QModelIndex()), str);
157
158   if (type == TreeItem::TypeDate) {
159     tableModel->setData(tableModel->index(1, 0, QModelIndex()), count);
160     tableModel->setData(tableModel->index(2, 0, QModelIndex()), scoreAvg);
161     tableModel->setData(tableModel->index(3, 0, QModelIndex()), scoreBest);
162   }    
163   else if (type == TreeItem::TypeScore) {
164     QVariant value = scoreTreeModel->data(index, ScoreTreeModel::Total);
165     tableModel->setData(tableModel->index(1, 0, QModelIndex()), score);
166     tableModel->setData(tableModel->index(1, 1, QModelIndex()), value);
167
168     value = scoreTreeModel->data(index, ScoreTreeModel::TotalOut);
169     tableModel->setData(tableModel->index(2, 0, QModelIndex()), scoreOut);
170     tableModel->setData(tableModel->index(2, 1, QModelIndex()), value);
171
172     value = scoreTreeModel->data(index, ScoreTreeModel::TotalIn);
173     tableModel->setData(tableModel->index(3, 0, QModelIndex()), scoreIn);
174     tableModel->setData(tableModel->index(3, 1, QModelIndex()), value);
175   }
176 }
177
178 void MainWindow::createStatusBar()
179 {
180   updateStatusBar();
181 }
182
183 void MainWindow::createActions()
184 {
185   newScoreAct = new QAction(tr("&New Score"), this);
186   connect(newScoreAct, SIGNAL(triggered()), this, SLOT(newScore()));
187
188   newCourseAct = new QAction(tr("&New Course"), this);
189   connect(newCourseAct, SIGNAL(triggered()), this, SLOT(newCourse()));
190
191 #if 0
192   viewScoreAct = new QAction(tr("&View Scores"), this);
193   connect(viewScoreAct, SIGNAL(triggered()), this, SLOT(viewScore()));
194
195   viewCourseAct = new QAction(tr("&View Courses"), this);
196   connect(viewCourseAct, SIGNAL(triggered()), this, SLOT(viewCourse()));
197
198   viewStatisticAct = new QAction(tr("&View Statistics"), this);
199   connect(viewStatisticAct, SIGNAL(triggered()), this, SLOT(viewStatistic()));
200 #endif
201 }
202
203 void MainWindow::createMenus()
204 {
205   menu = menuBar()->addMenu(tr("fremantle"));
206 #if 0
207   menu->addAction(viewScoreAct);
208   menu->addAction(viewCourseAct);
209   menu->addAction(viewStatisticAct);
210 #endif
211   menu->addAction(newScoreAct);
212   menu->addAction(newCourseAct);
213 }
214
215 void MainWindow::updateStatusBar()
216 {
217   setWindowTitle(scoreTableModel->getInfoText());
218 }
219
220 void MainWindow::firstButtonClicked()
221 {
222   scoreTableModel->first();
223   updateStatusBar();
224 }
225
226 void MainWindow::lastButtonClicked()
227 {
228   scoreTableModel->last();
229   updateStatusBar();
230 }
231
232 void MainWindow::nextButtonClicked()
233 {
234   scoreTableModel->next();
235   updateStatusBar();
236 }
237
238 void MainWindow::prevButtonClicked()
239 {
240   scoreTableModel->prev();
241   updateStatusBar();
242 }
243
244 // FIXME: dup code from table-model.cpp
245 Club *MainWindow::findClub(QString &name)
246 {
247   QListIterator<Club *> i(clubList);
248   Club *c;
249
250   while (i.hasNext()) {
251     c = i.next();
252     if (c->getName() == name)
253       return c;
254   }
255   return 0;
256 }
257
258 void MainWindow::newCourse()
259 {
260   CourseSelectDialog *selectDialog = new CourseSelectDialog(this);
261
262   int result = selectDialog->exec();
263   if (result) {
264     QString clubName;
265     QString courseName;
266     QString date;
267
268     selectDialog->results(clubName, courseName);
269
270     CourseDialog *courseDialog = new CourseDialog(this);
271
272     QString title = "New Course : " + clubName + "," + courseName;
273     courseDialog->setWindowTitle(title);
274
275     int result = courseDialog->exec();
276     if (result) {
277       QVector<QString> par(18);
278       QVector<QString> hcp(18);
279       QVector<QString> len(18);
280
281       courseDialog->results(par, hcp, len);
282
283       Course *course = 0;
284       Club *club = findClub(clubName);
285       if (club) {
286         course = club->getCourse(courseName);
287         if (course) {
288           qDebug() << "Error: club/course already in the database";
289           return;
290         }
291         else {
292           course = new Course(courseName, par, hcp);
293           club->addCourse(course);
294         }
295       }
296       else {
297         club = new Club(clubName);
298         course = new Course(courseName, par, hcp);
299         club->addCourse(course);
300         clubList << club;
301       }
302       saveClubFile(clubFile, clubList);
303
304       // TODO: does this really work? No mem leaks?
305       scoreTableModel->setClub(clubList);
306
307     }
308   }
309 }
310
311 void MainWindow::newScore()
312 {
313   SelectDialog *selectDialog = new SelectDialog(this);
314
315   selectDialog->init(clubList);
316
317   int result = selectDialog->exec();
318   if (result) {
319     QString clubName;
320     QString courseName;
321     QString date;
322
323     selectDialog->results(clubName, courseName, date);
324
325     ScoreDialog *scoreDialog = new ScoreDialog(this);
326     QString title = "New Score : " + courseName + ", " + date;
327     scoreDialog->setWindowTitle(title);
328
329     Club *club = findClub(clubName);
330     if (!club) {
331       qDebug() << "Error: no such club: " << clubName;
332       return;
333     }
334     Course *course = club->getCourse(courseName);
335     if (!course) {
336       qDebug() << "Error: no such course: " << courseName;
337       return;
338     }
339
340     scoreDialog->init(course);
341
342     result = scoreDialog->exec();
343
344     if (result) {
345       QVector<QString> scores(18);
346
347       scoreDialog->results(scores);
348       Score *score = new Score(scores, clubName, courseName, date);
349       scoreList << score;
350
351       // Sort the scores based on dates
352       qSort(scoreList.begin(), scoreList.end(), dateLessThan); 
353       // Save it
354       saveScoreFile(scoreFile, scoreList);
355
356       // TODO: does this really work? No mem leaks?
357       scoreTableModel->setScore(scoreList, score);
358       updateStatusBar();
359     }
360   }
361 }
362
363 void MainWindow::loadScoreFile(QString &fileName, QList<Score *> &list)
364 {
365   ScoreXmlHandler handler(list);
366
367   if (handler.parse(fileName))
368     qDebug() << "File loaded: " << fileName << " entries : " << list.size();
369 }
370
371 void MainWindow::saveScoreFile(QString &fileName, QList<Score *> &list)
372 {
373   ScoreXmlHandler handler(list);
374
375   if (handler.save(fileName))
376     // TODO: banner
377     qDebug() << "File saved : " << fileName << " entries : " << list.size();
378   else
379     qDebug() << "Unable to save : " << fileName;
380 }
381
382 void MainWindow::loadClubFile(QString &fileName, QList<Club *> &list)
383 {
384   ClubXmlHandler handler(list);
385
386   if (handler.parse(fileName))
387     qDebug() << "File loaded: " << fileName << " entries : " << list.size();
388 }
389
390 void MainWindow::saveClubFile(QString &fileName, QList<Club *> &list)
391 {
392   ClubXmlHandler handler(list);
393
394   if (handler.save(fileName))
395     // TODO: banner
396     qDebug() << "File saved : " << fileName << " entries : " << list.size();
397   else
398     qDebug() << "Unable to save : " << fileName;
399
400 }