Behave correctly if score contains unknown course
[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 #include "score-common.h"
14
15 QString empty("");
16
17 ScoreTableModel::ScoreTableModel(QObject *parent) 
18     : QAbstractTableModel(parent)
19 {
20     score = 0;
21     course = 0;
22     handicap = -1;
23 }
24
25 void ScoreTableModel::set(Score * s, Course * c, int h)
26 {
27     score = s;
28     course = c;
29     handicap = h;
30 }
31
32 int ScoreTableModel::rowCount(const QModelIndex &) const
33 {
34     return ROWS;
35 }
36  
37 int ScoreTableModel::columnCount(const QModelIndex &) const
38 {
39     return COLS + 2; // 2 for in/out and tot columns
40 }
41
42 QVariant ScoreTableModel::data(const QModelIndex &index, int role) const
43 {
44     if (!index.isValid())
45         return QVariant();
46
47     int row = index.row();
48     int col = index.column();
49
50     //
51     // ALIGNMENT
52     //
53     if (role == Qt::TextAlignmentRole ) {
54         return Qt::AlignCenter;
55     }
56
57     if (index.column() > 10)
58         return QVariant();
59
60     //
61     // COLORS
62     //
63     if (role == Qt::ForegroundRole) {
64         // Hole numbers 1-18. All hole nums, in, out and tot cell but not
65         // the empty cell.
66         if ((row == ROW_HOLE && col != 10) || row == ROW_HOLE_2) {
67             QBrush brush(ScoreColor::holeBg());
68             return brush;
69         }
70         if (score && course && (row == ROW_SCORE || row == ROW_SCORE_2)) {
71             int par;
72             int shots;
73             if (row == ROW_SCORE) {
74                 par = course->getPar(col).toInt();
75                 shots = score->getScore(col).toInt();
76             }
77             else {
78                 par = course->getPar(col + 9).toInt();
79                 shots = score->getScore(col + 9).toInt();
80             }
81
82             if (col == (COLS+1) && row == ROW_SCORE_2) {
83                 // Total score
84                 QBrush brush(ScoreColor::total());
85                 return brush;
86             }
87             if (col == COLS) {
88                 // In and Out scores
89                 QBrush brush(ScoreColor::subTotal());
90                 return brush;
91             }
92             if (col < COLS) {
93                 if (shots == par) {
94                     // Par
95                     QBrush brush(ScoreColor::par());
96                     return brush;
97                 }
98                 if (shots == (par-1)) {
99                     // Birdie
100                     QBrush brush(ScoreColor::birdie());
101                     return brush;
102                 }
103                 if (shots == (par+1)) {
104                     // Bogey
105                     QBrush brush(ScoreColor::bogey());
106                     return brush;
107                 }
108                 if (shots == (par+2)) {
109                     // Double Bogey
110                     QBrush brush(ScoreColor::doubleBogey());
111                     return brush;
112                 }
113                 if (shots > (par+2)) {
114                     // Very bad
115                     QBrush brush(ScoreColor::bad());
116                     return brush;
117                 }
118             }
119         }
120         return QVariant();
121     }
122     //
123     // FONT
124     //
125     if (role == Qt::FontRole) {
126         QFont font;
127         if (col == (COLS+1) && row == ROW_SCORE_2) {
128             font.setBold(true);
129             font.setPointSize(fontSize+4);
130         }
131         else 
132             font.setPointSize(fontSize);
133         if (row == ROW_HOLE || row == ROW_HOLE_2) {
134             font.setBold(true);
135         }
136         return font;
137     }
138
139     //
140     // NUMBERS
141     //
142     if (role == Qt::DisplayRole) {
143
144         if (col == COLS) {
145             // In/out label
146             if (row == ROW_HOLE)
147                 return QString("Out");
148             if (row == ROW_HOLE_2)
149                 return QString("In");
150
151             // In/Out for par
152             if (score && course && row == ROW_PAR)
153                 return course->getTotal(TotalOut);
154             if (score && course && row == ROW_PAR_2)
155                 return course->getTotal(TotalIn);
156
157             // In/Out for score
158             if (score && row == ROW_SCORE)
159                 return score->getTotal(TotalOut);
160             if (score && row == ROW_SCORE_2)
161                 return score->getTotal(TotalIn);
162       
163         }
164         else if (col == (COLS+1)) {
165             // Total label
166             if (row == ROW_HOLE_2)
167                 return QString("Tot");
168             // Total score
169             if (score && course && row == ROW_PAR_2)
170                 return course->getTotal(Total);
171             if (score && row == ROW_SCORE_2)
172                 return score->getTotal(Total);
173             // calculate net score
174             if (score && course && row == ROW_HCP_2) {
175                 int scoreTotal = score->getTotal(Total).toInt();
176                 int courseTotal = course->getTotal(Total).toInt();
177                 int n = scoreTotal - courseTotal;
178                 return QString("+%1").arg(n);
179             }
180         }
181         else {
182             // data cells
183             switch(row) {
184             case ROW_HOLE:
185                 return col + 1;
186
187             case ROW_HOLE_2:
188                 return col + 10;
189
190             case ROW_PAR:
191                 if (course)
192                     return course->getPar(col);
193                 else
194                     return QString("");
195
196             case ROW_PAR_2:
197                 if (course)
198                     return course->getPar(col + 9);
199                 else
200                     return QString("");
201
202             case ROW_HCP: 
203                 if (course)
204                     return course->getHcp(col); 
205                 else
206                     return QString("");
207
208             case ROW_HCP_2:
209                 if (course)
210                     return course->getHcp(col + 9);
211                 else
212                     return QString("");
213
214             case ROW_SCORE:
215                 if (score)
216                     return score->getScore(col);
217                 else
218                     return QString("");
219               
220             case ROW_SCORE_2: 
221                 if (score)
222                     return score->getScore(col + 9);
223                 else
224                     return QString("");
225             }
226         }
227     }
228     return QVariant();
229 }
230
231 QVariant ScoreTableModel::headerData(int section, Qt::Orientation orientation, int role) const
232 {
233     // Only vertical header -- horizontal is hidden
234     if (orientation == Qt::Horizontal)
235         return QVariant();
236
237     if (role == Qt::FontRole) {
238         QFont font;
239         font.setPointSize(fontSize);
240         return font;
241     }
242     if (role == Qt::DisplayRole) {
243         switch(section) {
244         case ROW_HOLE: 
245         case ROW_HOLE_2: 
246             return QString("Hole");
247         case ROW_PAR: 
248         case ROW_PAR_2: 
249             return QString("Par");
250         case ROW_HCP: 
251         case ROW_HCP_2: 
252             return QString("HCP");
253         case ROW_SCORE: 
254         case ROW_SCORE_2: 
255             return QString("Score");
256         }
257         return QVariant();
258     }
259
260     return QVariant();
261 }
262
263 //
264 // CourseTableModel
265 //
266 CourseTableModel::CourseTableModel(QObject *parent) 
267     : QAbstractTableModel(parent)
268 {
269     course = 0;
270 }
271
272 void CourseTableModel::set(Course *c)
273 {
274     course = c;
275 }
276
277 int CourseTableModel::rowCount(const QModelIndex &) const
278 {
279     return ROWS;
280 }
281  
282 int CourseTableModel::columnCount(const QModelIndex &) const
283 {
284     return COLS + 2;
285 }
286
287 QVariant CourseTableModel::data(const QModelIndex &index, int role) const
288 {
289     if (!index.isValid())
290         return QVariant();
291
292     int row = index.row();
293     int col = index.column();
294
295     //
296     // ALIGNMENT
297     //
298     if (role == Qt::TextAlignmentRole ) {
299         return Qt::AlignCenter;
300     }
301
302     //
303     // FONT
304     //
305     if (role == Qt::FontRole) {
306         QFont font;
307         font.setPointSize(fontSize);
308         if (row == ROW_HOLE || row == ROW_HOLE_2) {
309             font.setBold(true);
310         }
311         return font;
312     }
313     //
314     // COLORS
315     //
316     if (role == Qt::ForegroundRole) {
317         // Hole numbers 1-18. All hole nums, in, out and tot cell but not
318         // the empty cell.
319         if ((row == ROW_HOLE && col != 10) || row == ROW_HOLE_2) {
320             QBrush brush(ScoreColor::holeBg());
321             return brush;
322         }
323         return QVariant();
324     }
325     //
326     // NUMBERS
327     //
328     if (role == Qt::DisplayRole) {
329
330         if (col == COLS) {
331             // In/out label
332             if (row == ROW_HOLE)
333                 return QString("Out");
334             if (row == ROW_HOLE_2)
335                 return QString("In");
336
337             // In/Out for par
338             if (course && row == ROW_PAR)
339                 return course->getTotal(TotalOut);
340             if (course && row == ROW_PAR_2)
341                 return course->getTotal(TotalIn);
342         }
343         else if (col == (COLS+1)) {
344             // Total label
345             if (row == ROW_HOLE_2)
346                 return QString("Tot");
347             // Total score
348             if (course && row == ROW_PAR_2)
349                 return course->getTotal(Total);
350         }
351         else {
352             // data cells
353             switch(row) {
354             case ROW_HOLE:
355                 return col + 1;
356             case ROW_HOLE_2:
357                 return col + 10;
358             case ROW_PAR:
359                 if (course)
360                     return course->getPar(col); 
361             case ROW_PAR_2:
362                 if (course)
363                     return course->getPar(col + 9); 
364             case ROW_HCP: 
365                 if (course)
366                     return course->getHcp(col); 
367             case ROW_HCP_2:
368                 if (course)
369                     return course->getHcp(col + 9);
370             }
371         }
372     }
373     return QVariant();
374 }
375
376 QVariant CourseTableModel::headerData(int section, Qt::Orientation orientation, int role) const
377 {
378     // Only vertical header -- horizontal is hidden
379     if (orientation == Qt::Horizontal)
380         return QVariant();
381
382     if (role == Qt::FontRole) {
383         QFont font;
384         font.setPointSize(fontSize);
385         return font;
386     }
387     if (role == Qt::DisplayRole) {
388         switch(section) {
389         case ROW_HOLE: 
390         case ROW_HOLE_2: 
391             return QString("Hole");
392         case ROW_PAR: 
393         case ROW_PAR_2: 
394             return QString("Par");
395         case ROW_HCP: 
396         case ROW_HCP_2: 
397             return QString("HCP");
398         case ROW_LEN: 
399         case ROW_LEN_2: 
400             return QString("Len");
401         }
402         return QVariant();
403     }
404
405     return QVariant();
406 }