GPLv2 license
[scorecard] / src / table-model.cpp
1 /*
2  * Copyright (C) 2009 Sakari Poussa
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, version 2.
7  */
8
9 #include <QColor>
10 #include <QBrush>
11 #include <QFont>
12 #include "table-model.h"
13
14 QString empty("");
15
16 QColor colorHoleBg(Qt::darkGray);
17 QColor colorHoleFg(Qt::yellow);
18 QColor colorBirdie(102, 102, 255);
19 QColor colorPar(Qt::green);
20 QColor colorBogey(Qt::darkGreen);
21 QColor colorDoubleBogey(Qt::red);
22 QColor colorBad(Qt::red);
23 QColor colorSubTotal(Qt::black);
24 QColor colorTotal(Qt::black);
25
26 Qt::ItemFlags ScoreTableModel::flags (const QModelIndex & index)
27 {
28   return 0;
29 }
30
31 void ScoreTableModel::setMode(int m)
32 {
33   currentMode = m;
34 }
35
36 int ScoreTableModel::mode(void)
37 {
38   return currentMode;
39 }
40
41 // Assign the 'sList' to internal 'scoreList'. Set the current score
42 // to 'currentScore', or to 's'.
43 void ScoreTableModel::setScore(QList<Score *> &sList, Score *s)
44 {
45   scoreList = sList;
46   if (scoreList.size() > 0) {
47     if (s) {
48       currentScore = scoreList.indexOf(s);
49       if (currentScore == -1)
50         currentScore = 0;
51     }
52     score = scoreList.at(currentScore); // NOTE: assumes non-empty list
53   }
54 }
55
56 void ScoreTableModel::setClub(QList<Club *> &cList)
57 {
58   clubList = cList;
59
60   if (clubList.size() > 0)
61     club = clubList.at(0);
62
63   if (club)
64     course = club->getCourse(0);
65 }
66
67 QString ScoreTableModel::getInfoText()
68 {
69   QString str("");
70
71   if (score)
72     str = QString("%1, %2 / [%3/%4]").arg(score->getCourseName()).arg(score->getDate()).arg(currentScore+1).arg(scoreList.count());
73
74   return str;
75 }
76
77 QString ScoreTableModel::getCountText()
78 {
79   QString str = QString("%1/%2").arg(currentScore+1, 2).arg(scoreList.count(), 2);
80   return str;
81 }
82
83 QString& ScoreTableModel::clubName(void)
84 {
85   if (club)
86     return club->getName();
87
88   return empty;
89 }
90
91 QString& ScoreTableModel::courseName(void)
92 {
93   if (course)
94     return course->getName();
95
96   return empty;
97 }
98
99 Course *ScoreTableModel::findCourse(const QString &clubName, 
100                                     const QString &courseName)
101 {
102   QListIterator<Club *> i(clubList);
103   Club *c;
104
105   while (i.hasNext()) {
106     c = i.next();
107     if (c->getName() == clubName) {
108       return c->getCourse(courseName);
109     }
110   }
111   return 0;
112 }
113
114 Club *ScoreTableModel::getClub(void)
115 {
116   return club;
117 }
118
119 Course *ScoreTableModel::getCourse(void)
120 {
121   return course;
122 }
123
124 Score *ScoreTableModel::getScore(void)
125 {
126   return score;
127 }
128
129 void ScoreTableModel::first()
130 {
131   if (score && course) {
132     currentScore = 0;
133     score = scoreList.at(currentScore);
134     course = findCourse(score->getClubName(), score->getCourseName());
135     emit dataChanged(createIndex(0, 0), createIndex(ROW_COUNT-1, COL_COUNT-1));
136   }
137 }
138
139 void ScoreTableModel::last()
140 {
141   if (score && course) {
142     currentScore = scoreList.size() - 1;
143     score = scoreList.at(currentScore);
144     course = findCourse(score->getClubName(), score->getCourseName());
145     emit dataChanged(createIndex(0, 0), createIndex(ROW_COUNT-1, COL_COUNT-1));
146   }
147 }
148
149 void ScoreTableModel::next()
150 {
151   if (score && course) {
152     if (currentScore < (scoreList.size() - 1)) {
153       currentScore++;
154       score = scoreList.at(currentScore);
155       course = findCourse(score->getClubName(), score->getCourseName());
156       emit dataChanged(createIndex(0, 0), createIndex(ROW_COUNT-1, COL_COUNT-1));
157     }
158   }
159 }
160
161 void ScoreTableModel::prev()
162 {
163   if (score && course) {
164     if (currentScore > 0) {
165       currentScore--;
166       score = scoreList.at(currentScore);
167       course = findCourse(score->getClubName(), score->getCourseName());
168       emit dataChanged(createIndex(0, 0), createIndex(ROW_COUNT-1, COL_COUNT-1));
169     }
170   }
171 }
172
173 int ScoreTableModel::rowCount(const QModelIndex & parent) const
174 {
175   return 8;
176 }
177  
178 int ScoreTableModel::columnCount(const QModelIndex & parent) const
179 {
180   return 9 + 2; // 2 for in/out and tot columns
181 }
182
183 QModelIndex ScoreTableModel::index(int row, int column, const QModelIndex &parent) const
184 {
185   if (hasIndex(row, column, parent)) {
186     int flag = (parent.column() > 0) ? parent.column() : 0;
187     return createIndex(row, column, flag);
188   }
189   else {
190     return QModelIndex();
191   }
192 }
193
194 QVariant ScoreTableModel::data(const QModelIndex &index, int role) const
195 {
196   // TODO: move away from the stack
197
198   if (!index.isValid())
199     return QVariant();
200
201   int row = index.row();
202   int col = index.column();
203
204   //
205   // ALIGNMENT
206   //
207   if (role == Qt::TextAlignmentRole ) {
208     return Qt::AlignCenter;
209   }
210
211   if (index.column() > 10)
212     return QVariant();
213
214   //
215   // COLORS
216   //
217   if (role == Qt::BackgroundRole) {
218     // Hole numbers 1-18. All hole nums, in, out and tot cell but not
219     // the empty cell.
220     if ((row == ROW_HOLE && col != 10) || row == ROW_HOLE_2) {
221         QBrush brush(colorHoleBg);
222         return brush;
223     }
224     if (score && course && (row == ROW_SCORE || row == ROW_SCORE_2)) {
225       int par;
226       int shots;
227       if (row == ROW_SCORE) {
228         par = course->getPar(col).toInt();
229         shots = score->getScore(col).toInt();
230       }
231       else {
232         par = course->getPar(col + 9).toInt();
233         shots = score->getScore(col + 9).toInt();
234       }
235
236       if (col == 10 && row == ROW_SCORE_2) {
237         // Total score
238         QBrush brush(colorTotal);
239         return brush;
240       }
241       if (col == 9) {
242         // In and Out scores
243         QBrush brush(colorSubTotal);
244         return brush;
245       }
246       if (col < 9) {
247         if (shots == par) {
248           // Par
249           QBrush brush(colorPar);
250           return brush;
251         }
252         if (shots == (par-1)) {
253           // Birdie
254           QBrush brush(colorBirdie);
255           return brush;
256         }
257         if (shots == (par+1)) {
258           // Bogey
259           QBrush brush(colorBogey);
260           return brush;
261         }
262         if (shots == (par+2)) {
263           // Double Bogey
264           QBrush brush(colorDoubleBogey);
265           return brush;
266         }
267         if (shots > (par+2)) {
268           // Very bad
269           QBrush brush(colorBad);
270           return brush;
271         }
272       }
273     }
274     return QVariant();
275   }
276   //
277   // FONT
278   //
279   if (role == Qt::FontRole) {
280     if (row == ROW_SCORE_2 && col == 10) {
281         QFont font;
282         font.setBold(true);
283         return font;
284     }
285   }
286   //
287   // NUMBERS
288   //
289   if (role == Qt::DisplayRole) {
290
291     if (col == 9) {
292       // In/out label
293       if (row == ROW_HOLE)
294         return QString("Out");
295       if (row == ROW_HOLE_2)
296         return QString("In");
297
298       // In/Out for par
299       if (score && course && row == ROW_PAR)
300         return course->getTotal(TotalOut);
301       if (score && course && row == ROW_PAR_2)
302         return course->getTotal(TotalIn);
303
304       // In/Out for score
305       if (score && row == ROW_SCORE)
306         return score->getTotal(TotalOut);
307       if (score && row == ROW_SCORE_2)
308         return score->getTotal(TotalIn);
309       
310     }
311     else if (col == 10) {
312       // Total label
313       if (row == ROW_HOLE_2)
314         return QString("Tot");
315       // Total score
316       if (score && course && row == ROW_PAR_2)
317         return course->getTotal(Total);
318       if (score && row == ROW_SCORE_2)
319         return score->getTotal(Total);
320     }
321     else {
322       // data cells
323       switch(row) {
324       case ROW_HOLE:
325         return col + 1;
326       case ROW_HOLE_2:
327         return col + 10;
328       case ROW_PAR:
329         if (score && course)
330           return course->getPar(col); 
331       case ROW_PAR_2:
332         if (score && course)
333           return course->getPar(col + 9); 
334       case ROW_HCP: 
335         if (score && course)
336           return course->getHcp(col); 
337       case ROW_HCP_2:
338         if (score && course)
339           return course->getHcp(col + 9);
340       case ROW_SCORE:
341         if (score)
342           return score->getScore(col);
343       case ROW_SCORE_2: 
344         if (score)
345           return score->getScore(col + 9);
346       }
347     }
348   }
349   return QVariant();
350 }
351
352 int ScoreTableModel::setItem(int row, int col, int data)
353 {
354   emit dataChanged(createIndex(row, col), createIndex(row, col));
355   return 1;
356 }
357
358 QVariant ScoreTableModel::headerData(int section, Qt::Orientation orientation, int role) const
359 {
360   // Only vertical header -- horizontal is hidden
361   if (orientation == Qt::Horizontal)
362     return QVariant();
363
364 #if 1
365   if (role == Qt::BackgroundRole) {
366     QColor colorHoleBg(Qt::darkGray);
367     QBrush brush(colorHoleBg);
368     return brush;
369   }
370 #endif
371   if (role == Qt::DisplayRole) {
372     switch(section) {
373     case ROW_PAR: 
374     case ROW_PAR_2: 
375       return QString("Par");
376     case ROW_HCP: 
377     case ROW_HCP_2: 
378       return QString("HCP");
379     case ROW_SCORE: 
380     case ROW_SCORE_2: 
381       return QString("Score");
382     }
383     return QVariant();
384   }
385
386   return QVariant();
387 }
388