- Refactor: score and course UI widget management into common files
[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(ScoreStyle::style());
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   listClub = 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(listClub);
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   clubList = list;
125
126   QListIterator<Club *> i(clubList);
127   int index = 0;
128
129   while (i.hasNext()) {
130     Club *club = i.next();
131
132     QList<Course *> courseList = club->getCourseList();
133
134     QListIterator<Course *> j(courseList);
135     while (j.hasNext()) {
136       Course *course = j.next();
137
138       QListWidgetItem *newItem = new QListWidgetItem;
139
140       QString entry = club->getName() + ", " + course->getName();
141
142       newItem->setText(entry);
143       listClub->insertItem(index, newItem);
144
145       index++;
146     }
147   }
148 }
149
150 void SelectDialog::results(QString &club, 
151                            QString &course, 
152                            QString &date)
153 {  
154   QListWidgetItem *current = listClub->currentItem();
155
156   if (current) {
157     QString tmp = current->text();
158
159     QStringList stringList = tmp.split(", ");
160     club = stringList[0];
161     course = stringList[1];
162 #ifdef Q_WS_MAEMO_5
163     QMaemo5DatePickSelector *sel = (QMaemo5DatePickSelector *)dateButton->pickSelector();
164     QDate d = sel->currentDate();
165     // TODO: change to QDate
166     date = d.toString(Qt::ISODate);
167 #else
168     date = lineEditDate->text();
169 #endif
170   }
171 }
172
173 bool SelectDialog::validate(void)
174 {
175   return true;
176 }
177
178 void SelectDialog::next(void)
179 {
180   if (validate())
181     done(1);
182   else {
183     qDebug() << "SelectDialog: invalid data, cancel or correct";
184   }
185 }
186
187 void SelectDialog::reject(void)
188 {
189   done(0);
190 }
191
192 ////////////////////////////////////////////////////////////////////////////////
193 // ScoreDialog based on QDialog
194 ////////////////////////////////////////////////////////////////////////////////
195 ScoreDialog::ScoreDialog(QWidget *parent) : QDialog(parent)
196 {
197     TRACE;
198     resize(800, 400);
199
200     QWidget *centralWidget = new QWidget(this);
201
202     createTable();
203     createButton();
204     
205     createLayout(centralWidget);
206 }
207
208 ScoreDialog::~ScoreDialog()
209 {
210     //if (centralWidget)
211     //  delete centralWidget;
212     if (leftLayout)
213         delete leftLayout;
214     if (rightLayout)
215         delete rightLayout;
216     //if (mainLayout)
217     //  delete mainLayout;
218     if (table)
219         delete table;
220 }
221
222 void ScoreDialog::createLayout(QWidget *parent)
223 {
224     TRACE;
225     leftLayout = new QVBoxLayout;
226     leftLayout->addWidget(table);
227
228     QDialogButtonBox * buttonBoxUp = new QDialogButtonBox(Qt::Vertical);
229     buttonBoxUp->addButton(pushButtonUp, QDialogButtonBox::ActionRole);
230     buttonBoxUp->addButton(pushButtonDown, QDialogButtonBox::ActionRole);
231     buttonBoxUp->addButton(pushButtonNext, QDialogButtonBox::ActionRole);
232
233     QDialogButtonBox * buttonBoxDown = new QDialogButtonBox(Qt::Vertical);
234     buttonBoxDown->addButton(pushButtonFinish, QDialogButtonBox::ActionRole);
235
236     rightLayout = new QVBoxLayout;
237     rightLayout->addWidget(buttonBoxUp);
238     rightLayout->addStretch();
239     rightLayout->addWidget(buttonBoxDown);
240
241     QHBoxLayout *mainLayout = new QHBoxLayout(parent);
242     mainLayout->addLayout(leftLayout);
243     mainLayout->addLayout(rightLayout);
244     setLayout(mainLayout);
245 }
246
247 void ScoreDialog::createTable(QWidget *parent)
248 {
249     TRACE;
250     table = new QTableWidget(ROWS, COLS, parent);
251
252     table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
253     table->verticalHeader()->setResizeMode(QHeaderView::Stretch);
254     table->horizontalHeader()->hide();
255
256     table->setStyleSheet(ScoreStyle::style());
257
258     QStringList headers;
259     headers << "" << "Par" << "HCP" << "Score" << "" << "Par" << "HCP" << "Score";
260     table->setVerticalHeaderLabels(headers);
261 }
262
263 void ScoreDialog::createButton(QWidget *parent)
264 {
265     TRACE;
266     Q_UNUSED(parent);
267     pushButtonUp = new QPushButton(tr("+"));
268     connect(pushButtonUp, SIGNAL(clicked()), this, SLOT(up()));
269     
270     pushButtonDown = new QPushButton(tr("-"));
271     connect(pushButtonDown, SIGNAL(clicked()), this, SLOT(down()));
272   
273     pushButtonNext = new QPushButton(tr("Next"));
274     connect(pushButtonNext, SIGNAL(clicked()), this, SLOT(next()));
275
276     pushButtonFinish = new QPushButton(tr("Finish"));
277     connect(pushButtonFinish, SIGNAL(clicked()), this, SLOT(finish()));
278 }
279
280 void ScoreDialog::init(Course *course, Score *score)
281 {
282     TRACE;
283     QTableWidgetItem *par, *hcp, *scoreItem, *holeNum;
284
285     for (int i = 0; i < 18; i++) {
286         par = new QTableWidgetItem(course->getPar(i));
287         hcp = new QTableWidgetItem(course->getHcp(i));
288         if (score)
289             scoreItem = new QTableWidgetItem(score->getScore(i));
290         else
291             scoreItem = new QTableWidgetItem("");
292         holeNum = new QTableWidgetItem(QString::number(i+1));
293
294         holeNum->setTextAlignment(Qt::AlignCenter);
295         holeNum->setFlags(Qt::NoItemFlags);
296         holeNum->setForeground(ScoreColor::holeBg());
297         
298         par->setTextAlignment(Qt::AlignCenter);
299         par->setFlags(Qt::NoItemFlags);
300
301         hcp->setTextAlignment(Qt::AlignCenter);
302         hcp->setFlags(Qt::NoItemFlags);
303         
304         scoreItem->setTextAlignment(Qt::AlignCenter);
305
306         if (i < 9) {
307             table->setItem(ROW_HOLE, i, holeNum);
308             table->setItem(ROW_PAR, i, par);
309             table->setItem(ROW_HCP, i, hcp);
310             table->setItem(ROW_SCORE, i, scoreItem);
311         }
312         else {
313             table->setItem(ROW_HOLE_2, i-9, holeNum);
314             table->setItem(ROW_PAR_2, i-9, par);
315             table->setItem(ROW_HCP_2, i-9, hcp);
316             table->setItem(ROW_SCORE_2, i-9, scoreItem);
317         }
318     }
319
320     // Set focus to 1st cell
321     table->setCurrentCell(ROW_SCORE, 0);
322     if (!score)
323         setDefaultScore(table);
324 }
325
326 // Set default score to par if not set
327 void ScoreDialog::setDefaultScore(QTableWidget *table)
328 {
329   int row = table->currentRow();
330   int col = table->currentColumn();
331   
332   if (row == ROW_SCORE)
333     row = ROW_PAR;
334   else if (row == ROW_SCORE_2)
335     row = ROW_PAR_2;
336   else {
337     qDebug() << "ERROR: unknown row in default score";
338     return;
339   }
340   QTableWidgetItem *par = table->item(row, col);
341   QTableWidgetItem *score = table->item(row + 2, col);
342
343   if (par && score && score->text() == "") {
344     QVariant value(par->text());
345     score->setData(Qt::DisplayRole, value);
346   }
347 }
348
349 void ScoreDialog::up(void)
350 {
351   QTableWidgetItem *item = table->currentItem();
352
353   if (!item) {
354     qWarning() << "ERROR: no current item";
355     return;
356   }
357
358   int i = (item->text()).toInt();
359   QVariant value(i+1);
360   item->setData(Qt::DisplayRole, value);
361 }
362
363 void ScoreDialog::down(void)
364 {
365   QTableWidgetItem *item = table->currentItem();
366
367   if (!item)
368     return;
369
370   int i = (item->text()).toInt();
371   QVariant value(i-1);
372   item->setData(Qt::DisplayRole, value);
373 }
374
375 void ScoreDialog::next(void)
376 {
377   if (table) {
378     QTableWidgetItem *item = table->currentItem();
379     moveToNextCell(item);
380     setDefaultScore(table);
381   }
382 }
383
384 void ScoreDialog::moveToNextCell(QTableWidgetItem *item)
385 {
386   if (!item)
387     return;
388
389   QTableWidget *table = item->tableWidget();
390
391   if (!table)
392     return;
393
394   int row = table->currentRow();
395   int col = table->currentColumn();
396
397   if (col < (COLS-1)) {
398     col++;
399   }
400   else if (col == (COLS-1)) {
401     col = 0;
402     row = (row == ROW_SCORE_2) ? ROW_SCORE : ROW_SCORE_2;
403   }
404   table->setCurrentCell(row, col);
405 }
406
407 void ScoreDialog::results(QVector<QString> &scores)
408 {
409     TRACE;
410     for (int i = 0; i < 9; i++) {
411         QTableWidgetItem *frontItem = table->item(ROW_SCORE, i);
412         QTableWidgetItem *backItem = table->item(ROW_SCORE_2, i);
413
414         if (frontItem)
415             scores[i] = frontItem->text();
416
417         if (backItem)
418             scores[i+9] = backItem->text();
419     }
420 }
421
422 bool ScoreDialog::validate(void)
423 {
424   for (int i=0; i<9; i++) {
425     QTableWidgetItem *frontItem = table->item(ROW_SCORE, i);
426     QTableWidgetItem *backItem = table->item(ROW_SCORE_2, i);
427     
428     if (!frontItem || !backItem)
429       return false;
430     
431     QString str1 = frontItem->text();
432     QString str2 = backItem->text();
433     
434     if (str1.isEmpty() || str2.isEmpty())
435       return false;
436   }
437   return true;
438 }
439
440 void ScoreDialog::finish(void)
441 {
442     if (validate())
443         done(1);
444     else {
445         showNote("Invalid data - cancel or correct");
446     }
447 }
448
449 void ScoreDialog::reject(void)
450 {
451   done(0);
452 }
453
454 void ScoreDialog::showNote(QString msg)
455 {
456 #ifdef Q_WS_MAEMO_5
457     QMaemo5InformationBox::information(this, 
458                                        msg,
459                                        QMaemo5InformationBox::DefaultTimeout);
460 #endif
461 }