29b018ce23e9e7ad53b0261e02ecaaf5ef6e52c8
[scorecard] / src / score-dialog.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 <QtGui>
10 #include <QInputContext>
11 #ifdef Q_WS_MAEMO_5
12 #include <QMaemo5InformationBox>
13 #endif
14
15 #include "score-dialog.h"
16 #include "score-common.h"
17 #include "table-model.h"
18
19 ////////////////////////////////////////////////////////////////////////////////
20 // ScoreWindow based on QMainWindow
21 ////////////////////////////////////////////////////////////////////////////////
22 ScoreWindow::ScoreWindow(QWidget *parent) : QMainWindow(parent)
23 {
24 #ifdef Q_WS_MAEMO_5
25     setAttribute(Qt::WA_Maemo5StackedWindow);
26 #endif
27
28     QAction *editAction = new QAction(tr("Edit"), this);
29     connect(editAction, SIGNAL(triggered()), parent, SLOT(editScore()));
30     menuBar()->addAction(editAction);
31
32     QAction *delAction = new QAction(tr("Delete"), this);
33     connect(delAction, SIGNAL(triggered()), parent, SLOT(deleteScore()));
34     menuBar()->addAction(delAction);
35
36     model = new ScoreTableModel;
37     
38     QTableView * table = new QTableView;
39     table->showGrid();
40     table->setSelectionMode(QAbstractItemView::NoSelection);
41     table->setStyleSheet(defaultStyleSheet);
42     table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
43     table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
44     table->horizontalHeader()->hide();
45     table->setModel(model);
46     
47     QWidget *central = new QWidget(this);
48     setCentralWidget(central);
49     
50     QVBoxLayout *layout = new QVBoxLayout;
51     layout->addWidget(table);
52     
53     central->setLayout(layout);
54 }
55
56 ScoreWindow::~ScoreWindow()
57 {
58     TRACE;
59 }
60
61 void ScoreWindow::setup(Score *score, Course *course)
62 {
63     TRACE;
64     QString title = QString("Score: %1, %2 - %3").arg(score->getClubName()).arg(score->getCourseName()).arg(score->getDate());
65     setWindowTitle(title);
66     model->set(score, course);
67 }
68
69
70 ////////////////////////////////////////////////////////////////////////////////
71 // SelectDialog based on QDialog
72 ////////////////////////////////////////////////////////////////////////////////
73 SelectDialog::SelectDialog(QWidget *parent) : QDialog(parent)
74 {
75     resize(800, 350);
76
77     QWidget *centralWidget = new QWidget(this);
78     createLayout(centralWidget);
79
80     setWindowTitle(tr("ScoreCard: Select Course and Date"));
81 }
82
83 void SelectDialog::createLayout(QWidget *parent)
84 {
85     listWidgetClub = new QListWidget(parent);
86     pushButtonNext = new QPushButton(tr("Next"));
87
88     connect(pushButtonNext, SIGNAL(clicked()), this, SLOT(next()));
89
90     QDialogButtonBox * buttonBox = new QDialogButtonBox(Qt::Vertical);
91     buttonBox->addButton(pushButtonNext, QDialogButtonBox::ActionRole);
92
93     leftLayout = new QVBoxLayout;
94     leftLayout->addWidget(listWidgetClub);
95
96 #ifdef Q_WS_MAEMO_5
97     dateButton = new QMaemo5ValueButton();
98     dateButton->setValueLayout(QMaemo5ValueButton::ValueUnderText);
99     dateButton->setPickSelector(new QMaemo5DatePickSelector());
100     dateButton->setText(QString::fromUtf8("Date"));
101     leftLayout->addWidget(dateButton);
102 #else
103     QDate today(QDate::currentDate());
104     lineEditDate = new QLineEdit;
105     lineEditDate->setText(today.toString("yyyy-MM-dd"));
106     date = new QDateEdit;
107     leftLayout->addWidget(date);
108     leftLayout->addWidget(lineEditDate);
109 #endif
110
111     rightLayout = new QVBoxLayout;
112     rightLayout->addStretch();
113     rightLayout->addWidget(buttonBox);
114
115     QHBoxLayout *mainLayout = new QHBoxLayout(parent);
116     mainLayout->addLayout(leftLayout);
117     mainLayout->addLayout(rightLayout);
118
119     setLayout(mainLayout);
120 }
121
122 void SelectDialog::init(QList<Club *> &list)
123 {
124     TRACE;
125     clubList = list;
126
127     QListIterator<Club *> i(clubList);
128     int index = 0;
129     bool markedFlag = false;
130
131     while (i.hasNext()) {
132         Club *club = i.next();
133
134         QList<Course *> courseList = club->getCourseList();
135
136         QListIterator<Course *> j(courseList);
137         while (j.hasNext()) {
138             Course *course = j.next();
139
140             QListWidgetItem *newItem = new QListWidgetItem;
141             
142             QString entry = club->getName() + ", " + course->getName();
143
144             newItem->setText(entry);
145             listWidgetClub->insertItem(index, newItem);
146
147             if (!markedFlag & club->isHomeClub()) {
148                 listWidgetClub->setCurrentRow(index);
149                 // Mark the 1st course of the home club the selection
150                 markedFlag = true;
151             }
152             index++;
153         }
154     }
155 }
156
157 void SelectDialog::results(QString &club, 
158                            QString &course, 
159                            QString &date)
160 {  
161     QListWidgetItem *current = listWidgetClub->currentItem();
162
163     if (current) {
164         QString tmp = current->text();
165
166         QStringList stringList = tmp.split(", ");
167         club = stringList[0];
168         course = stringList[1];
169 #ifdef Q_WS_MAEMO_5
170         QMaemo5DatePickSelector *sel = (QMaemo5DatePickSelector *)dateButton->pickSelector();
171         QDate d = sel->currentDate();
172         // TODO: change to QDate
173         date = d.toString(Qt::ISODate);
174 #else
175         date = lineEditDate->text();
176 #endif
177     }
178 }
179
180 bool SelectDialog::validate(void)
181 {
182     return true;
183 }
184
185 void SelectDialog::next(void)
186 {
187     if (validate())
188         done(1);
189     else {
190         qDebug() << "SelectDialog: invalid data, cancel or correct";
191     }
192 }
193
194 void SelectDialog::reject(void)
195 {
196     done(0);
197 }
198
199 ////////////////////////////////////////////////////////////////////////////////
200 // ScoreDialog based on QDialog
201 ////////////////////////////////////////////////////////////////////////////////
202 ScoreDialog::ScoreDialog(QWidget *parent) : QDialog(parent)
203 {
204     TRACE;
205     resize(800, 400);
206     QFont font;
207     font.setPointSize(fontSize);
208     setFont(font);
209
210     QWidget *centralWidget = new QWidget(this);
211
212     createTable();
213     createButton();
214     
215     createLayout(centralWidget);
216 }
217
218 ScoreDialog::~ScoreDialog()
219 {
220     //if (centralWidget)
221     //  delete centralWidget;
222     if (leftLayout)
223         delete leftLayout;
224     if (rightLayout)
225         delete rightLayout;
226     //if (mainLayout)
227     //  delete mainLayout;
228     if (table)
229         delete table;
230 }
231
232 void ScoreDialog::createLayout(QWidget *parent)
233 {
234     TRACE;
235     leftLayout = new QVBoxLayout;
236     leftLayout->addWidget(table);
237
238     QDialogButtonBox * buttonBoxUp = new QDialogButtonBox(Qt::Vertical);
239     buttonBoxUp->addButton(pushButtonUp, QDialogButtonBox::ActionRole);
240     buttonBoxUp->addButton(pushButtonDown, QDialogButtonBox::ActionRole);
241     buttonBoxUp->addButton(pushButtonNext, QDialogButtonBox::ActionRole);
242
243     QDialogButtonBox * buttonBoxDown = new QDialogButtonBox(Qt::Vertical);
244     buttonBoxDown->addButton(pushButtonFinish, QDialogButtonBox::ActionRole);
245
246     rightLayout = new QVBoxLayout;
247     rightLayout->addWidget(buttonBoxUp);
248     rightLayout->addStretch();
249     rightLayout->addWidget(buttonBoxDown);
250
251     QHBoxLayout *mainLayout = new QHBoxLayout(parent);
252     mainLayout->addLayout(leftLayout);
253     mainLayout->addLayout(rightLayout);
254     setLayout(mainLayout);
255 }
256
257 void ScoreDialog::createTable(QWidget *parent)
258 {
259     TRACE;
260     table = new QTableWidget(ROWS, COLS, parent);
261
262     table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
263     table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
264     table->horizontalHeader()->hide();
265
266     table->setStyleSheet(defaultStyleSheet);
267
268     QStringList headers;
269     headers << "" << "Par" << "HCP" << "Score" << "" << "Par" << "HCP" << "Score";
270     table->setVerticalHeaderLabels(headers);
271 }
272
273 void ScoreDialog::createButton(QWidget *parent)
274 {
275     TRACE;
276     Q_UNUSED(parent);
277     pushButtonUp = new QPushButton(tr("+"));
278     connect(pushButtonUp, SIGNAL(clicked()), this, SLOT(up()));
279     
280     pushButtonDown = new QPushButton(tr("-"));
281     connect(pushButtonDown, SIGNAL(clicked()), this, SLOT(down()));
282   
283     pushButtonNext = new QPushButton(tr("Next"));
284     connect(pushButtonNext, SIGNAL(clicked()), this, SLOT(next()));
285
286     pushButtonFinish = new QPushButton(tr("Finish"));
287     connect(pushButtonFinish, SIGNAL(clicked()), this, SLOT(finish()));
288 }
289
290 void ScoreDialog::init(Course *course, Score *score)
291 {
292     TRACE;
293     QTableWidgetItem *par, *hcp, *scoreItem, *holeNum;
294
295     for (int i = 0; i < 18; i++) {
296         par = new QTableWidgetItem(course->getPar(i));
297         hcp = new QTableWidgetItem(course->getHcp(i));
298         if (score)
299             scoreItem = new QTableWidgetItem(score->getScore(i));
300         else
301             scoreItem = new QTableWidgetItem("");
302         holeNum = new QTableWidgetItem(QString::number(i+1));
303
304         holeNum->setTextAlignment(Qt::AlignCenter);
305         holeNum->setFlags(Qt::NoItemFlags);
306         holeNum->setForeground(ScoreColor::holeBg());
307         
308         par->setTextAlignment(Qt::AlignCenter);
309         par->setFlags(Qt::NoItemFlags);
310
311         hcp->setTextAlignment(Qt::AlignCenter);
312         hcp->setFlags(Qt::NoItemFlags);
313         
314         scoreItem->setTextAlignment(Qt::AlignCenter);
315
316         if (i < 9) {
317             table->setItem(ROW_HOLE, i, holeNum);
318             table->setItem(ROW_PAR, i, par);
319             table->setItem(ROW_HCP, i, hcp);
320             table->setItem(ROW_SCORE, i, scoreItem);
321         }
322         else {
323             table->setItem(ROW_HOLE_2, i-9, holeNum);
324             table->setItem(ROW_PAR_2, i-9, par);
325             table->setItem(ROW_HCP_2, i-9, hcp);
326             table->setItem(ROW_SCORE_2, i-9, scoreItem);
327         }
328     }
329
330     // Set focus to 1st cell
331     table->setCurrentCell(ROW_SCORE, 0);
332     if (!score)
333         setDefaultScore(table);
334 }
335
336 // Set default score to par if not set
337 void ScoreDialog::setDefaultScore(QTableWidget *table)
338 {
339     int row = table->currentRow();
340     int col = table->currentColumn();
341   
342     if (row == ROW_SCORE)
343         row = ROW_PAR;
344     else if (row == ROW_SCORE_2)
345         row = ROW_PAR_2;
346     else {
347         qDebug() << "ERROR: unknown row in default score";
348         return;
349     }
350     QTableWidgetItem *par = table->item(row, col);
351     QTableWidgetItem *score = table->item(row + 2, col);
352
353     if (par && score && score->text() == "") {
354         QVariant value(par->text());
355         score->setData(Qt::DisplayRole, value);
356     }
357 }
358
359 void ScoreDialog::up(void)
360 {
361     QTableWidgetItem *item = table->currentItem();
362
363     if (!item) {
364         qWarning() << "ERROR: no current item";
365         return;
366     }
367
368     int i = (item->text()).toInt();
369     QVariant value(i+1);
370     item->setData(Qt::DisplayRole, value);
371 }
372
373 void ScoreDialog::down(void)
374 {
375     QTableWidgetItem *item = table->currentItem();
376
377     if (!item)
378         return;
379
380     int i = (item->text()).toInt();
381     QVariant value(i-1);
382     item->setData(Qt::DisplayRole, value);
383 }
384
385 void ScoreDialog::next(void)
386 {
387     if (table) {
388         QTableWidgetItem *item = table->currentItem();
389         moveToNextCell(item);
390         setDefaultScore(table);
391     }
392 }
393
394 void ScoreDialog::moveToNextCell(QTableWidgetItem *item)
395 {
396     if (!item)
397         return;
398
399     QTableWidget *table = item->tableWidget();
400
401     if (!table)
402         return;
403
404     int row = table->currentRow();
405     int col = table->currentColumn();
406
407     if (col < (COLS-1)) {
408         col++;
409     }
410     else if (col == (COLS-1)) {
411         col = 0;
412         row = (row == ROW_SCORE_2) ? ROW_SCORE : ROW_SCORE_2;
413     }
414     table->setCurrentCell(row, col);
415 }
416
417 void ScoreDialog::results(QVector<QString> &scores)
418 {
419     TRACE;
420     for (int i = 0; i < 9; i++) {
421         QTableWidgetItem *frontItem = table->item(ROW_SCORE, i);
422         QTableWidgetItem *backItem = table->item(ROW_SCORE_2, i);
423
424         if (frontItem)
425             scores[i] = frontItem->text();
426
427         if (backItem)
428             scores[i+9] = backItem->text();
429     }
430 }
431
432 bool ScoreDialog::validate(void)
433 {
434     for (int i=0; i<9; i++) {
435         QTableWidgetItem *frontItem = table->item(ROW_SCORE, i);
436         QTableWidgetItem *backItem = table->item(ROW_SCORE_2, i);
437     
438         if (!frontItem || !backItem)
439             return false;
440     
441         QString str1 = frontItem->text();
442         QString str2 = backItem->text();
443     
444         if (str1.isEmpty() || str2.isEmpty())
445             return false;
446     }
447     return true;
448 }
449
450 void ScoreDialog::finish(void)
451 {
452     if (validate())
453         done(1);
454     else {
455         showNote("Invalid data - cancel or correct");
456     }
457 }
458
459 void ScoreDialog::reject(void)
460 {
461     done(0);
462 }
463
464 void ScoreDialog::showNote(QString msg)
465 {
466 #ifdef Q_WS_MAEMO_5
467     QMaemo5InformationBox::information(this, 
468                                        msg,
469                                        QMaemo5InformationBox::DefaultTimeout);
470 #endif
471 }