Added debian packaging
[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 topDir("/opt/scorecard");
15 QString mmcDir("/media/mmc1/scorecard");
16 QString dataDirName("/data/");
17 QString dataDir;
18 QString imgDir(topDir + "/pixmaps");
19 QString scoreFileName("score.xml");
20 QString scoreFile;
21 QString clubFileName("club.xml");
22 QString clubFile;
23 QString logFile("/tmp/scorecard.log");
24
25 MainWindow::MainWindow(QMainWindow *parent) : QMainWindow(parent)
26 {
27   resize(800, 480);
28
29   loadSettings();
30
31   QWidget *centralWidget = new QWidget(this);
32
33   // TODO: move to proper function
34   tableViewFront = new QTableView(centralWidget);
35   tableViewBack = new QTableView(centralWidget);
36
37   setCentralWidget(centralWidget);
38
39   loadScoreFile(scoreFile, scoreList);
40   loadClubFile(clubFile, clubList);
41
42 #ifdef TEST
43   saveScoreFile(scoreFileWr, scoreList);
44   saveClubFile(clubFileWr, clubList);
45 #endif
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(tableViewFront);
99   tableLayout->addWidget(tableViewBack);
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   nextButton = new QPushButton(tr(">"));
111   prevButton = new QPushButton(tr("<"));
112   firstButton = new QPushButton(tr("<<"));
113   lastButton = new QPushButton(tr(">>"));
114
115   connect(nextButton, SIGNAL(clicked()), this, SLOT(nextButtonClicked()));
116   connect(prevButton, SIGNAL(clicked()), this, SLOT(prevButtonClicked()));
117   connect(firstButton, SIGNAL(clicked()), this, SLOT(firstButtonClicked()));
118   connect(lastButton, SIGNAL(clicked()), this, SLOT(lastButtonClicked()));
119
120   scoreTableModel = new ScoreTableModel();
121   scoreTableModel->setScore(scoreList);
122   scoreTableModel->setClub(clubList);
123
124   tableViewFront->showGrid();
125   tableViewBack->showGrid();
126
127   tableViewFront->setModel(scoreTableModel);
128   tableViewBack->setModel(scoreTableModel);
129
130   // Flag model items which one belongs to front and back nines
131   tableViewFront->setRootIndex(scoreTableModel->index(0, 0));
132   tableViewBack->setRootIndex(scoreTableModel->index(0, 1));
133
134   // Fill out all the space with the tables
135   tableViewFront->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
136   tableViewFront->verticalHeader()->setResizeMode(QHeaderView::Stretch);
137   tableViewBack->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
138   tableViewBack->verticalHeader()->setResizeMode(QHeaderView::Stretch);
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   updateStatusBar();
183 }
184
185 void MainWindow::createActions()
186 {
187   newScoreAct = new QAction(tr("&New Score"), this);
188   connect(newScoreAct, SIGNAL(triggered()), this, SLOT(newScore()));
189
190   newCourseAct = new QAction(tr("&New Course"), this);
191   connect(newCourseAct, SIGNAL(triggered()), this, SLOT(newCourse()));
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 }
216
217 void MainWindow::updateStatusBar()
218 {
219   setWindowTitle(scoreTableModel->getInfoText());
220 }
221
222 void MainWindow::firstButtonClicked()
223 {
224   scoreTableModel->first();
225   updateStatusBar();
226 }
227
228 void MainWindow::lastButtonClicked()
229 {
230   scoreTableModel->last();
231   updateStatusBar();
232 }
233
234 void MainWindow::nextButtonClicked()
235 {
236   scoreTableModel->next();
237   updateStatusBar();
238 }
239
240 void MainWindow::prevButtonClicked()
241 {
242   scoreTableModel->prev();
243   updateStatusBar();
244 }
245
246 // FIXME: dup code from table-model.cpp
247 Club *MainWindow::findClub(QString &name)
248 {
249   QListIterator<Club *> i(clubList);
250   Club *c;
251
252   while (i.hasNext()) {
253     c = i.next();
254     if (c->getName() == name)
255       return c;
256   }
257   return 0;
258 }
259
260 void MainWindow::newCourse()
261 {
262   CourseSelectDialog *selectDialog = new CourseSelectDialog(this);
263
264   int result = selectDialog->exec();
265   if (result) {
266     QString clubName;
267     QString courseName;
268     QString date;
269
270     selectDialog->results(clubName, courseName);
271
272     CourseDialog *courseDialog = new CourseDialog(this);
273
274     QString title = "New Course : " + clubName + "," + courseName;
275     courseDialog->setWindowTitle(title);
276
277     int result = courseDialog->exec();
278     if (result) {
279       QVector<QString> par(18);
280       QVector<QString> hcp(18);
281       QVector<QString> len(18);
282
283       courseDialog->results(par, hcp, len);
284
285       Course *course = 0;
286       Club *club = findClub(clubName);
287       if (club) {
288         course = club->getCourse(courseName);
289         if (course) {
290           qDebug() << "Error: club/course already in the database";
291           return;
292         }
293         else {
294           course = new Course(courseName, par, hcp);
295           club->addCourse(course);
296         }
297       }
298       else {
299         club = new Club(clubName);
300         course = new Course(courseName, par, hcp);
301         club->addCourse(course);
302         clubList << club;
303       }
304       saveClubFile(clubFile, clubList);
305
306       // TODO: does this really work? No mem leaks?
307       scoreTableModel->setClub(clubList);
308
309     }
310   }
311 }
312
313 void MainWindow::newScore()
314 {
315   SelectDialog *selectDialog = new SelectDialog(this);
316
317   selectDialog->init(clubList);
318
319   int result = selectDialog->exec();
320   if (result) {
321     QString clubName;
322     QString courseName;
323     QString date;
324
325     selectDialog->results(clubName, courseName, date);
326
327     ScoreDialog *scoreDialog = new ScoreDialog(this);
328     QString title = "New Score : " + courseName + ", " + date;
329     scoreDialog->setWindowTitle(title);
330
331     Club *club = findClub(clubName);
332     if (!club) {
333       qDebug() << "Error: no such club: " << clubName;
334       return;
335     }
336     Course *course = club->getCourse(courseName);
337     if (!course) {
338       qDebug() << "Error: no such course: " << courseName;
339       return;
340     }
341
342     scoreDialog->init(course);
343
344     result = scoreDialog->exec();
345
346     if (result) {
347       QVector<QString> scores(18);
348
349       scoreDialog->results(scores);
350       Score *score = new Score(scores, clubName, courseName, date);
351       scoreList << score;
352
353       saveScoreFile(scoreFile, scoreList);
354
355       // TODO: does this really work? No mem leaks?
356       scoreTableModel->setScore(scoreList);
357       lastButtonClicked();
358     }
359   }
360 }
361
362 void MainWindow::loadScoreFile(QString &fileName, QList<Score *> &list)
363 {
364   ScoreXmlHandler handler(list);
365
366   if (handler.parse(fileName))
367     qDebug() << "File loaded: " + fileName +" entries : " + list.size();
368 }
369
370 void MainWindow::saveScoreFile(QString &fileName, QList<Score *> &list)
371 {
372   ScoreXmlHandler handler(list);
373
374   if (handler.save(fileName))
375     // TODO: banner
376     qDebug() << "File saved : " << fileName << " entries : " << list.size();
377   else
378     qDebug() << "Unable to save : " << fileName;
379 }
380
381 void MainWindow::loadClubFile(QString &fileName, QList<Club *> &list)
382 {
383   ClubXmlHandler handler(list);
384
385   if (handler.parse(fileName))
386     qDebug() << "File loaded: " + fileName +" entries : " + list.size();
387 }
388
389 void MainWindow::saveClubFile(QString &fileName, QList<Club *> &list)
390 {
391   ClubXmlHandler handler(list);
392
393   if (handler.save(fileName))
394     // TODO: banner
395     qDebug() << "File saved : " << fileName << " entries : " << list.size();
396   else
397     qDebug() << "Unable to save : " << fileName;
398
399 }