1 /* ColorCode, a free MasterMind clone with built in solver
2  * Copyright (C) 2009  Dirk Laebisch
3  * http://www.laebisch.com/
4  *
5  * ColorCode is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * ColorCode is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with ColorCode. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "gametablesdialog.h"
20 #include "ui_gametablesdialog.h"
21 #include "gametableview.h"
22 #include "highscoresmodel.h"
23 #include "prevgamesmodel.h"
24 #include "savedgamesmodel.h"
25 #include "buttondelegate.h"
26 #include "ccsolver.h"
27 #include "ccgame.h"
28 #include "settings.h"
29 
30 const int GameTablesDialog::TABIX_INPUT      = 0;
31 const int GameTablesDialog::TABIX_PREVIOUS   = 1;
32 const int GameTablesDialog::TABIX_BOOKMARKS  = 2;
33 const int GameTablesDialog::TABIX_HIGHSCORES = 3;
34 
35 
GameTablesDialog(QWidget * parent,Qt::WindowFlags f)36 GameTablesDialog::GameTablesDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f), ui(new Ui::GameTablesDialog)
37 {
38     ui->setupUi(this);
39     Init();
40 }
41 
~GameTablesDialog()42 GameTablesDialog::~GameTablesDialog()
43 {
44     delete ui;
45 }
46 
Init()47 void GameTablesDialog::Init()
48 {
49     setModal(true);
50     setMouseTracking(true);
51     setAttribute(Qt::WA_Hover, true);
52     setAttribute(Qt::WA_AlwaysShowToolTips, true);
53 
54     mLastGameProperties = NULL;
55 
56     ui->mDescriptionTe->setFocusPolicy(Qt::NoFocus);
57     ui->mDescriptionTe->setAttribute(Qt::WA_TransparentForMouseEvents);
58     ui->mDescriptionTe->setText(tr("Insert an arbitrary game number greater than 0 in the input field above. <br><br>"
59                                    "The game properties like color count, slot count etc. will be displayed in the corresponding area above.<br><br>"
60                                    "Click the Play button or press key Enter, to play the game. If a game is currently running, it will be aborted."));
61 
62     ui->mGameNoLe->setValidator(new QIntValidator(1, INT_MAX, this));
63 
64     connect(ui->mGameNoLe, SIGNAL(textChanged(const QString)), this, SLOT(GameNoInpChangedSlot(const QString)));
65 
66 
67     mPrevTableView = new GameTableView();
68     mPrevTableView->SetGamesListModel(GetPrevGamesModel());
69     mPrevTableView->setColumnWidth(GetPrevGamesModel()->GetColIx(GamesListModel::COL_RANKING), 20);
70     mPrevTableView->setColumnWidth(GetPrevGamesModel()->GetColIx(GamesListModel::COL_DATE), 90);
71     mPrevTableView->setColumnWidth(GetPrevGamesModel()->GetColIx(GamesListModel::COL_TIME), 90);
72     mPrevTableView->setColumnWidth(GetPrevGamesModel()->GetColIx(GamesListModel::COL_DELETE), 40);
73 
74     mPrevTableView->setItemDelegateForColumn(GetPrevGamesModel()->GetColIx(GamesListModel::COL_RANKING), new ButtonDelegate());
75     mPrevTableView->setItemDelegateForColumn(GetPrevGamesModel()->GetColIx(GamesListModel::COL_DATE), new ButtonDelegate());
76     mPrevTableView->setItemDelegateForColumn(GetPrevGamesModel()->GetColIx(GamesListModel::COL_TIME), new ButtonDelegate());
77     mPrevTableView->setItemDelegateForColumn(GetPrevGamesModel()->GetColIx(GamesListModel::COL_DELETE), new ButtonDelegate());
78 
79     GetPrevGamesModel()->SetView(mPrevTableView);
80 
81     ui->mPrevTab->layout()->addWidget(mPrevTableView);
82 
83     connect(mPrevTableView, SIGNAL(HoverRowSignal(int)), this, SLOT(HoverRowSlot(int)));
84     connect(GetPrevGamesModel(), SIGNAL(CloseEditorSignal(QModelIndex)), mPrevTableView, SLOT(CloseEditorSlot(QModelIndex)));
85     connect(GetPrevGamesModel(), SIGNAL(NewGameInputSignal(CCGame*)), this, SLOT(NewGameInputSlot(CCGame*)));
86 
87 
88     mSavedTableView = new GameTableView();
89     mSavedTableView->SetGamesListModel(GetSavedGamesModel());
90     mSavedTableView->setColumnWidth(GetSavedGamesModel()->GetColIx(GamesListModel::COL_GAMENO), 70);
91     mSavedTableView->setColumnWidth(GetSavedGamesModel()->GetColIx(GamesListModel::COL_CCNT), 50);
92     mSavedTableView->setColumnWidth(GetSavedGamesModel()->GetColIx(GamesListModel::COL_PCNT), 50);
93     mSavedTableView->setColumnWidth(GetSavedGamesModel()->GetColIx(GamesListModel::COL_DOUBLES), 30);
94     mSavedTableView->setColumnWidth(GetSavedGamesModel()->GetColIx(GamesListModel::COL_DELETE), 40);
95 
96     mSavedTableView->setItemDelegateForColumn(GetSavedGamesModel()->GetColIx(GamesListModel::COL_GAMENO), new ButtonDelegate());
97     mSavedTableView->setItemDelegateForColumn(GetSavedGamesModel()->GetColIx(GamesListModel::COL_CCNT), new ButtonDelegate());
98     mSavedTableView->setItemDelegateForColumn(GetSavedGamesModel()->GetColIx(GamesListModel::COL_PCNT), new ButtonDelegate());
99     mSavedTableView->setItemDelegateForColumn(GetSavedGamesModel()->GetColIx(GamesListModel::COL_DOUBLES), new ButtonDelegate());
100     mSavedTableView->setItemDelegateForColumn(GetSavedGamesModel()->GetColIx(GamesListModel::COL_DELETE), new ButtonDelegate());
101 
102     GetSavedGamesModel()->SetView(mSavedTableView);
103 
104     ui->mSavedTab->layout()->addWidget(mSavedTableView);
105 
106     connect(mSavedTableView, SIGNAL(HoverRowSignal(int)), this, SLOT(HoverRowSlot(int)));
107     connect(GetSavedGamesModel(), SIGNAL(CloseEditorSignal(QModelIndex)), mSavedTableView, SLOT(CloseEditorSlot(QModelIndex)));
108     connect(GetSavedGamesModel(), SIGNAL(NewGameInputSignal(CCGame*)), this, SLOT(NewGameInputSlot(CCGame*)));
109 
110 
111     mHighTableView = new GameTableView();
112     mHighTableView->SetGamesListModel(GetHighScoresModel());
113     mHighTableView->setColumnWidth(GetHighScoresModel()->GetColIx(GamesListModel::COL_RANKING), 20);
114     mHighTableView->setColumnWidth(GetHighScoresModel()->GetColIx(GamesListModel::COL_SCORE), 60);
115     mHighTableView->setColumnWidth(GetHighScoresModel()->GetColIx(GamesListModel::COL_USERNAME), 120);
116     mHighTableView->setColumnWidth(GetHighScoresModel()->GetColIx(GamesListModel::COL_DELETE), 40);
117 
118     mHighTableView->setItemDelegateForColumn(GetHighScoresModel()->GetColIx(GamesListModel::COL_RANKING), new ButtonDelegate());
119     mHighTableView->setItemDelegateForColumn(GetHighScoresModel()->GetColIx(GamesListModel::COL_SCORE), new ButtonDelegate());
120     mHighTableView->setItemDelegateForColumn(GetHighScoresModel()->GetColIx(GamesListModel::COL_USERNAME), new ButtonDelegate());
121     mHighTableView->setItemDelegateForColumn(GetHighScoresModel()->GetColIx(GamesListModel::COL_DELETE), new ButtonDelegate());
122 
123     GetHighScoresModel()->SetView(mHighTableView);
124 
125     ui->mHighTab->layout()->addWidget(mHighTableView);
126 
127     connect(mHighTableView, SIGNAL(HoverRowSignal(int)), this, SLOT(HoverRowSlot(int)));
128     connect(GetHighScoresModel(), SIGNAL(CloseEditorSignal(QModelIndex)), mHighTableView, SLOT(CloseEditorSlot(QModelIndex)));
129     connect(GetHighScoresModel(), SIGNAL(NewGameInputSignal(CCGame*)), this, SLOT(NewGameInputSlot(CCGame*)));
130     connect(GetHighScoresModel(), SIGNAL(ValidNameCommitSignal()), this, SLOT(ValidNameCommitSlot()));
131 
132 
133     connect(GetPrevGamesModel(), SIGNAL(SaveListGameSignal(CCGame*)), this, SLOT(InsertSavedGameSlot(CCGame*)));
134     connect(GetHighScoresModel(), SIGNAL(SaveListGameSignal(CCGame*)), this, SLOT(InsertSavedGameSlot(CCGame*)));
135 
136 
137     connect(ui->mTabsWidget, SIGNAL(currentChanged(int)), this, SLOT(CurrentTabChanged(int)));
138 
139     connect(ui->mCloseBtn, SIGNAL(clicked()), this, SLOT(OkBtnSlot()));
140     connect(ui->mClearBtn, SIGNAL(clicked()), this, SLOT(ClearListSlot()));
141     connect(ui->mPlayBtn, SIGNAL(clicked()), this, SLOT(PlayInputSlot()));
142 }
143 
ShowTab(int tabix)144 void GameTablesDialog::ShowTab(int tabix)
145 {
146     if (ui->mTabsWidget->currentIndex() != tabix)
147     {
148         ui->mTabsWidget->setCurrentIndex(tabix);
149     }
150     else
151     {
152         CurrentTabChanged(tabix);
153     }
154     show();
155 }
156 
ShowInputSlot()157 void GameTablesDialog::ShowInputSlot()
158 {
159     ShowTab(TABIX_INPUT);
160 }
161 
ShowPrevSlot()162 void GameTablesDialog::ShowPrevSlot()
163 {
164     ShowTab(TABIX_PREVIOUS);
165 }
166 
ShowSavedSlot()167 void GameTablesDialog::ShowSavedSlot()
168 {
169     ShowTab(TABIX_BOOKMARKS);
170 }
171 
ShowHighSlot()172 void GameTablesDialog::ShowHighSlot()
173 {
174     ShowTab(TABIX_HIGHSCORES);
175 }
176 
177 
HoverRowSlot(const int row)178 void GameTablesDialog::HoverRowSlot(const int row)
179 {
180     if (row > -1)
181     {
182         GamesListModel* glm = GetCurModel();
183         if (glm != NULL)
184         {
185             SetGameProperties(glm->GetGameAt(row));
186         }
187         else
188         {
189             SetGameProperties(NULL);
190         }
191     }
192     else
193     {
194         SetGameProperties(NULL);
195     }
196 }
197 
GetCurModel() const198 GamesListModel* GameTablesDialog::GetCurModel() const
199 {
200     GamesListModel* glm;
201 
202     int ix = ui->mTabsWidget->currentIndex();
203     if (ix == TABIX_PREVIOUS)
204     {
205         glm = qobject_cast<GamesListModel*>(GetPrevGamesModel());
206     }
207     else if (ix == TABIX_BOOKMARKS)
208     {
209         glm = qobject_cast<GamesListModel*>(GetSavedGamesModel());
210     }
211     else if (ix == TABIX_HIGHSCORES)
212     {
213         glm = qobject_cast<GamesListModel*>(GetHighScoresModel());
214     }
215     else
216     {
217         glm = NULL;
218     }
219 
220     return glm;
221 }
222 
GetCurView() const223 GameTableView* GameTablesDialog::GetCurView() const
224 {
225     GameTableView* gtv;
226 
227     int ix = ui->mTabsWidget->currentIndex();
228     if (ix == TABIX_PREVIOUS)
229     {
230         gtv = qobject_cast<GameTableView*>(mPrevTableView);
231     }
232     else if (ix == TABIX_BOOKMARKS)
233     {
234         gtv = qobject_cast<GameTableView*>(mSavedTableView);
235     }
236     else if (ix == TABIX_HIGHSCORES)
237     {
238         gtv = qobject_cast<GameTableView*>(mHighTableView);
239     }
240     else
241     {
242         gtv = NULL;
243     }
244 
245     return gtv;
246 }
247 
SetGameProperties(const CCGame * g)248 void GameTablesDialog::SetGameProperties(const CCGame* g)
249 {
250     if (g != NULL && g->IsValidGame())
251     {
252         if (mLastGameProperties == NULL || mLastGameProperties != g)
253         {
254             mLastGameProperties = const_cast<CCGame*>(g);
255 
256             int ix = ui->mTabsWidget->currentIndex();
257             switch (ix)
258             {
259                 case TABIX_PREVIOUS:
260                 case TABIX_BOOKMARKS:
261                     ui->mUserValLbl->setText("");
262                     ui->mDurationValLbl->setText("");
263                     ui->mDateValLbl->setText(g->GetDateTimeStr());
264                 break;
265                 case TABIX_HIGHSCORES:
266                     ui->mUserValLbl->setText(g->GetUserName());
267                     ui->mDurationValLbl->setText(FormatDuration(g->mDuration));
268                     ui->mDateValLbl->setText(g->GetDateTimeStr());
269                 break;
270                 case TABIX_INPUT:
271                     ui->mDateValLbl->setText("");
272                 break;
273             }
274 
275             ui->mColorCntValLbl->setText(QString::number(g->mColorCnt));
276             ui->mPegCntValLbl->setText(QString::number(g->mPegCnt));
277             QString str = (g->mDoubles == 1) ? tr("Yes") : tr("No");
278             ui->mDoublesValLbl->setText(str);
279             ui->mGameNoValLbl->setText(QString::number(g->mGameNo));
280         }
281     }
282     else
283     {
284         mLastGameProperties = NULL;
285 
286         ui->mUserValLbl->setText("");
287         ui->mColorCntValLbl->setText("");
288         ui->mPegCntValLbl->setText("");
289         ui->mDoublesValLbl->setText("");
290         ui->mGameNoValLbl->setText("");
291         ui->mDateValLbl->setText("");
292         ui->mDurationValLbl->setText("");
293     }
294 }
295 
FormatDuration(const uint dur) const296 QString GameTablesDialog::FormatDuration(const uint dur) const
297 {
298     QTime t(0, 0, 0, 0);
299     t = t.addMSecs(int(dur));
300     QString tstr = QString("%1 : %2 : %3 : %4").arg( t.toString("hh"), t.toString("mm"), t.toString("ss"), t.toString("zzz"));
301     return tstr;
302 }
303 
ReadSettingsGamesSlot()304 void GameTablesDialog::ReadSettingsGamesSlot()
305 {
306     SetSettingsSlot();
307 
308     GetPrevGamesModel()->ReadList(GetSettings()->mPrevGamesStr);
309     GetSavedGamesModel()->ReadList(GetSettings()->mSavedGamesStr);
310     GetHighScoresModel()->ReadList(GetSettings()->mHighGamesStr);
311     clearFocus();
312 }
313 
SetSettingsSlot()314 void GameTablesDialog::SetSettingsSlot()
315 {
316     GetPrevGamesModel()->SetMaxSize(GetSettings()->mGamesListMaxCnt);
317     GetSavedGamesModel()->SetMaxSize(GetSettings()->mGamesListMaxCnt);
318     GetHighScoresModel()->SetMaxSize(GetSettings()->mGamesListMaxCnt);
319     GetPrevGamesModel()->SetRowHColors(GetSettings()->GetActiveRowHFg(), GetSettings()->GetActiveRowHBg());
320     GetSavedGamesModel()->SetRowHColors(GetSettings()->GetActiveRowHFg(), GetSettings()->GetActiveRowHBg());
321     GetHighScoresModel()->SetRowHColors(GetSettings()->GetActiveRowHFg(), GetSettings()->GetActiveRowHBg());
322 }
323 
InsertHighScoreSlot(CCGame * g)324 void GameTablesDialog::InsertHighScoreSlot(CCGame* g)
325 {
326     if (GetSettings()->mHighScoreHandling == Settings::HIGHSCORE_NO)
327     {
328         return;
329     }
330 
331     if (GetHighScoresModel()->IsValidHighScore(g->mScore))
332     {
333         CCGame game = *g;
334         game.SetUserName(GetSettings()->mHighScoreUserName);
335         if (GetSettings()->mHighScoreHandling != Settings::HIGHSCORE_AUTO || GetSettings()->mHighScoreUserName == "")
336         {
337             ShowTab(GameTablesDialog::TABIX_HIGHSCORES);
338         }
339         GetHighScoresModel()->InsertRow(game);
340     }
341 }
342 
InsertPrevGameSlot(CCGame * g)343 void GameTablesDialog::InsertPrevGameSlot(CCGame* g)
344 {
345     CCGame game = *g;
346     game.Anonymize();
347     GetPrevGamesModel()->InsertRow(game);
348 }
349 
InsertSavedGameSlot(CCGame * g)350 void GameTablesDialog::InsertSavedGameSlot(CCGame* g)
351 {
352     CCGame game = *g;
353     game.Anonymize();
354     game.mTime = QDateTime::currentDateTime().toTime_t();
355     GetSavedGamesModel()->InsertRow(game);
356 }
357 
OkBtnSlot()358 void GameTablesDialog::OkBtnSlot()
359 {
360     close();
361 }
362 
ClearListSlot()363 void GameTablesDialog::ClearListSlot()
364 {
365     GamesListModel* glm = GetCurModel();
366     if (glm == NULL)
367     {
368         return;
369     }
370 
371     int rcnt = glm->rowCount();
372     if (rcnt <= 0)
373     {
374         return;
375     }
376 
377     int r = QMessageBox::warning( this,
378                                    tr("Message"),
379                                    tr("This will permanently remove all entries from the List.\nDo You want to proceed?"),
380                                    QMessageBox::Yes | QMessageBox::No,
381                                    QMessageBox::Yes);
382 
383     if (r == QMessageBox::Yes)
384     {
385         rcnt = glm->rowCount();
386         if (rcnt > 0)
387         {
388             glm->removeRows(0, rcnt);
389         }
390     }
391 }
392 
PlayInputSlot()393 void GameTablesDialog::PlayInputSlot()
394 {
395     if (ui->mTabsWidget->currentIndex() == TABIX_INPUT
396         && ui->mGameNoLe->text() != "")
397     {
398         uint gameno = ui->mGameNoLe->text().toUInt();
399         if (gameno > 0)
400         {
401             const int* props = ColorCode::INSTANCE->GetCCSolver()->GetGameByNo(gameno);
402             CCGame* g = new CCGame("", 0, 0, gameno, 0, 0, 0, ColorCode::MODE_HVM, props[1], props[2], props[3]);
403             NewGameInputSlot(g);
404         }
405     }
406 }
407 
GameNoInpChangedSlot(const QString & txt)408 void GameTablesDialog::GameNoInpChangedSlot(const QString &txt)
409 {
410     if (txt != "" && txt.toUInt() > 0)
411     {
412         const int* props = ColorCode::INSTANCE->GetCCSolver()->GetGameByNo(txt.toUInt());
413         CCGame* g = new CCGame("", 0, 0, txt.toUInt(), 0, 0, 0, ColorCode::MODE_HVM, props[1], props[2], props[3]);
414         SetGameProperties(g);
415     }
416     else
417     {
418         SetGameProperties(NULL);
419     }
420 }
421 
NewGameInputSlot(CCGame * g)422 void GameTablesDialog::NewGameInputSlot(CCGame* g)
423 {
424     emit NewGameInputSignal(g);
425     close();
426 }
427 
ValidNameCommitSlot()428 void GameTablesDialog::ValidNameCommitSlot()
429 {
430     if (ui->mTabsWidget->currentIndex() == TABIX_HIGHSCORES)
431     {
432         ui->mCloseBtn->setFocus();
433     }
434 }
435 
SetRowHeight()436 void GameTablesDialog::SetRowHeight()
437 {
438     for (int i = 0; i < GetHighScoresModel()->rowCount(); ++i)
439     {
440         mHighTableView->setRowHeight(i, 18);
441     }
442 }
443 
CurrentTabChanged(int ix)444 void GameTablesDialog::CurrentTabChanged(int ix)
445 {
446     mLastGameProperties = NULL;
447     SetGameProperties(NULL);
448 
449     QString str = "";
450     QIcon ico;
451     switch (ix)
452     {
453         case TABIX_INPUT:
454             ui->mPlayBtn->setVisible(true);
455             ui->mClearBtn->setVisible(false);
456             ui->mGameNoLe->setFocus();
457             ui->mUserLbl->setEnabled(false);
458             ui->mDurationLbl->setEnabled(false);
459             ui->mDateLbl->setEnabled(false);
460             GameNoInpChangedSlot(ui->mGameNoLe->text());
461             str = tr("Game Number Input");
462             ico = QIcon(":/img/document-new.png");
463         break;
464         case TABIX_PREVIOUS:
465             ui->mPlayBtn->setVisible(false);
466             ui->mClearBtn->setVisible(true);
467             ui->mUserLbl->setEnabled(false);
468             ui->mDurationLbl->setEnabled(false);
469             ui->mDateLbl->setEnabled(true);
470             str = tr("Recent Games");
471             ico = QIcon(":/img/history.png");
472         break;
473         case TABIX_BOOKMARKS:
474             ui->mPlayBtn->setVisible(false);
475             ui->mClearBtn->setVisible(true);
476             ui->mUserLbl->setEnabled(false);
477             ui->mDurationLbl->setEnabled(false);
478             ui->mDateLbl->setEnabled(true);
479             str = tr("Bookmarked Games");
480             ico = QIcon(":/img/bookmark.png");
481         break;
482         case TABIX_HIGHSCORES:
483             ui->mPlayBtn->setVisible(false);
484             ui->mClearBtn->setVisible(true);
485             ui->mUserLbl->setEnabled(true);
486             ui->mDurationLbl->setEnabled(true);
487             ui->mDateLbl->setEnabled(true);
488             str = tr("High Score List");
489             ico = QIcon(":/img/games-highscores.png");
490         break;
491         default:
492             str = tr("Game Lists");
493         break;
494     }
495     setWindowTitle(str);
496     setWindowIcon(ico);
497 }
498 
closeEvent(QCloseEvent * e)499 void GameTablesDialog::closeEvent(QCloseEvent* e)
500 {
501     GetHighScoresModel()->EditField();
502     if (GetHighScoresModel()->GetEditIndex().isValid() && GetHighScoresModel()->GetEditValue() == "")
503     {
504         e->ignore();
505 
506         int r = QMessageBox::warning( this,
507         tr("Message"),
508         tr("Please provide a name!\nOtherwise your score won't be saved."),
509         QMessageBox::Ok | QMessageBox::Discard,
510         QMessageBox::Ok);
511 
512         if (r == QMessageBox::Discard)
513         {
514             GetHighScoresModel()->removeRows(GetHighScoresModel()->GetEditIndex().row(), 1);
515             e->accept();
516         }
517         else
518         {
519             GetHighScoresModel()->EditField();
520         }
521     }
522     else
523     {
524         GetHighScoresModel()->SetEditIndex(QModelIndex());
525         e->accept();
526     }
527 }
528 
reject()529 void GameTablesDialog::reject()
530 {
531     close();
532 }
533 
changeEvent(QEvent * e)534 void GameTablesDialog::changeEvent(QEvent *e)
535 {
536     QDialog::changeEvent(e);
537     switch (e->type())
538     {
539         case QEvent::LanguageChange:
540             ui->retranslateUi(this);
541             break;
542         default:
543             break;
544     }
545 }
546