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 "gameslistmodel.h"
20 #include "gametableview.h"
21 
22 const int GamesListModel::MODEL_ID_DEFAULT = 0;
23 const int GamesListModel::MODEL_ID_PREV    = 1;
24 const int GamesListModel::MODEL_ID_SAVED   = 2;
25 const int GamesListModel::MODEL_ID_HIGH    = 3;
26 
27 const int GamesListModel::COL_RANKING  = 0;
28 const int GamesListModel::COL_SCORE    = 1;
29 const int GamesListModel::COL_USERNAME = 2;
30 const int GamesListModel::COL_DELETE   = 3;
31 const int GamesListModel::COL_GAMENO   = 4;
32 const int GamesListModel::COL_DATE     = 5;
33 const int GamesListModel::COL_TIME     = 6;
34 const int GamesListModel::COL_CCNT     = 7;
35 const int GamesListModel::COL_PCNT     = 8;
36 const int GamesListModel::COL_DOUBLES  = 9;
37 
SortListScore(CCGame a,CCGame b)38 bool GamesListModel::SortListScore(CCGame a, CCGame b)
39 {
40     if (a.GetScore() > b.GetScore())
41     {
42         return true;
43     }
44     return false;
45 }
46 
SortListTime(CCGame a,CCGame b)47 bool GamesListModel::SortListTime(CCGame a, CCGame b)
48 {
49     if (a.mTime > b.mTime)
50     {
51         return true;
52     }
53     return false;
54 }
55 
GamesListModel(QObject * parent)56 GamesListModel::GamesListModel(QObject* parent) : QAbstractTableModel(parent)
57 {
58     mId = MODEL_ID_DEFAULT;
59     mEditIndex = QModelIndex();
60     mMaxSize = 20;
61     mHoverRow = -1;
62     mRowHFg = QApplication::palette().color(QPalette::Active, QPalette::ButtonText);
63     mRowHBg = QApplication::palette().color(QPalette::Active, QPalette::Button);
64 }
65 
GetId()66 int GamesListModel::GetId()
67 {
68     return mId;
69 }
70 
GetListStr() const71 QString GamesListModel::GetListStr() const
72 {
73     QStringList strl;
74     for (int i = 0; i < mGamesList.size(); ++i)
75     {
76         strl << mGamesList.at(i).ToString();
77     }
78     return strl.join(";");
79 }
80 
SetView(GameTableView * view)81 void GamesListModel::SetView(GameTableView* view)
82 {
83     mView = view;
84 }
85 
SetMaxSize(const int max)86 void GamesListModel::SetMaxSize(const int max)
87 {
88     if (max != mMaxSize)
89     {
90         mMaxSize = max;
91         LimitGamesListSize();
92     }
93 }
94 
SetRowHColors(QString fg,QString bg)95 void GamesListModel::SetRowHColors(QString fg, QString bg)
96 {
97     mRowHFg.setNamedColor(fg);
98     mRowHBg.setNamedColor(bg);
99 }
100 
InsertRow(CCGame g)101 void GamesListModel::InsertRow(CCGame g)
102 {
103     mView->clearSelection();
104 
105     bool found = false;
106     for (int i = 0; i < mGamesList.size(); ++i)
107     {
108         if (mGamesList.at(i).mGameNo == g.mGameNo)
109         {
110             mGamesList.replace(i, g);
111             found = true;
112             break;
113         }
114     }
115 
116     if (!found)
117     {
118         beginInsertRows(QModelIndex(), rowCount(), rowCount());
119         mGamesList.push_back(g);
120         endInsertRows();
121         QModelIndex mix = index(rowCount() - 1, GetColIx(COL_DELETE), QModelIndex());
122         mView->openPersistentEditor(mix);
123     }
124 
125     DoSort(mGamesList);
126     LimitGamesListSize();
127     emit layoutChanged();
128 }
129 
LimitGamesListSize()130 void GamesListModel::LimitGamesListSize()
131 {
132     if (!mGamesList.isEmpty() && mGamesList.size() > mMaxSize)
133     {
134         removeRows(mMaxSize, mGamesList.size() - mMaxSize);
135     }
136 }
137 
EditField()138 void GamesListModel::EditField()
139 {
140     if (mView != NULL && mEditIndex.isValid())
141     {
142         mView->setCurrentIndex(mEditIndex);
143         mView->selectRow(mEditIndex.row());
144         mView->edit(mEditIndex);
145     }
146 }
147 
SetEditIndex(QModelIndex ix)148 void GamesListModel::SetEditIndex(QModelIndex ix)
149 {
150     mEditIndex = ix;
151 }
152 
GetEditIndex() const153 QModelIndex GamesListModel::GetEditIndex() const
154 {
155     return mEditIndex;
156 }
157 
GetEditValue() const158 QString GamesListModel::GetEditValue() const
159 {
160     QString val = "";
161     const CCGame* eg;
162     if (mEditIndex.isValid())
163     {
164         eg = GetGameAt(mEditIndex.row());
165         val = eg->GetUserName();
166     }
167     return val;
168 }
169 
GetGameAt(const int row) const170 const CCGame* GamesListModel::GetGameAt(const int row) const
171 {
172     if (row > -1 && mGamesList.size() > row)
173     {
174         return &mGamesList.at(row);
175     }
176     return NULL;
177 }
178 
ReadList(const QString & str)179 void GamesListModel::ReadList(const QString &str)
180 {
181     mEditIndex = QModelIndex();
182     if (rowCount() > 0)
183     {
184         removeRows(0, rowCount());
185     }
186 
187     QStringList games = str.split(QString(";"));
188     CCGame* g;
189     QModelIndex mix;
190     for (int i = 0; i < games.size(); ++i)
191     {
192         g = new CCGame(games.at(i));
193         if (g->IsValidGame())
194         {
195             beginInsertRows(QModelIndex(), rowCount(), rowCount());
196             mGamesList.push_back(*g);
197             endInsertRows();
198 
199             mix = index(rowCount() - 1, GetColIx(COL_DELETE), QModelIndex());
200             mView->openPersistentEditor(mix);
201         }
202     }
203     DoSort(mGamesList);
204     LimitGamesListSize();
205     emit layoutChanged();
206 }
207 
HoverRowSlot(int row)208 void GamesListModel::HoverRowSlot(int row)
209 {
210     if (mHoverRow == row)
211     {
212         return;
213     }
214 
215     int tmprow;
216     if (row == -1)
217     {
218         tmprow = mHoverRow;
219     }
220     else
221     {
222         tmprow = row;
223     }
224 
225     mHoverRow = row;
226     emit dataChanged(index(tmprow, 0), index(tmprow, columnCount() - 1));
227 }
228 
removeRows(int row,int count,const QModelIndex & parent)229 bool GamesListModel::removeRows(int row, int count, const QModelIndex &parent)
230 {
231     if (row < 0 || row + count > rowCount() || count == 0)
232     {
233         return false;
234     }
235 
236     if (mEditIndex.isValid())
237     {
238         if (mEditIndex.row() >= row && mEditIndex.row() < row + count)
239         {
240             mEditIndex = QModelIndex();
241         }
242         else if (mEditIndex.row() >= row + count)
243         {
244             mEditIndex = createIndex(mEditIndex.row() - count, GetColIx(COL_USERNAME));
245         }
246     }
247     beginRemoveRows(parent, row, row + count - 1);
248     for (int i = row; i < row + count; ++i)
249     {
250         mGamesList.removeAt(row);
251     }
252     endRemoveRows();
253     return true;
254 }
255 
flags(const QModelIndex & index) const256 Qt::ItemFlags GamesListModel::flags(const QModelIndex &index) const
257 {
258     if (index.isValid() && index == mEditIndex)
259     {
260         return Qt::ItemIsEnabled|Qt::ItemIsEditable;
261     }
262 
263     return Qt::ItemIsEnabled;
264 }
265 
setData(const QModelIndex & index,const QVariant & value,int role)266 bool GamesListModel::setData(const QModelIndex &index, const QVariant &value, int role)
267 {
268     if (role == Qt::EditRole && index.isValid() && index.row() < rowCount())
269     {
270         if (index.column() == GetColIx(COL_USERNAME))
271         {
272             if (index == mEditIndex)
273             {
274                 CCGame g = mGamesList.at(index.row());
275                 g.SetUserName(value.toString());
276                 mGamesList.replace(index.row(), g);
277                 if (g.GetUserName() != "")
278                 {
279                     emit ValidNameCommitSignal();
280                 }
281             }
282         }
283         else if (index.column() == GetColIx(COL_DELETE))
284         {
285             bool ok;
286             int aid = value.toInt(&ok);
287             if (ok)
288             {
289                 if (aid == ButtonsCell::ACTIONID_DELETE)
290                 {
291                     removeRows(index.row(), 1);
292                 }
293                 else
294                 {
295                     CCGame g = mGamesList.at(index.row());
296 
297                     if (aid == ButtonsCell::ACTIONID_SAVE)
298                     {
299                         CCGame* gc = new CCGame(g.ToString());
300                         emit SaveListGameSignal(gc);
301                     }
302                     else if (aid == ButtonsCell::ACTIONID_PLAY)
303                     {
304                         CCGame* gc = new CCGame(g.ToString());
305                         emit NewGameInputSignal(gc);
306                     }
307                     else if (aid == ButtonsCell::ACTIONID_COPY)
308                     {
309                         QClipboard* cb = QApplication::clipboard();
310                         cb->setText(QString::number(g.mGameNo));
311                     }
312                 }
313             }
314         }
315 
316         return true;
317     }
318     return false;
319 }
320 
rowCount(const QModelIndex &) const321 int GamesListModel::rowCount(const QModelIndex &) const
322 {
323     return mGamesList.size();
324 }
325 
columnCount(const QModelIndex &) const326 int GamesListModel::columnCount(const QModelIndex &) const
327 {
328     return GetMaxColCnt();
329 }
330 
data(const QModelIndex & index,int role) const331 QVariant GamesListModel::data(const QModelIndex &index, int role) const
332 {
333     if (!(index.row() < mGamesList.size()) || !index.isValid())
334     {
335         return QVariant();
336     }
337     else if (role == Qt::TextAlignmentRole)
338     {
339         if (index.column() == GetColIx(COL_USERNAME)
340             || index.column() == GetColIx(COL_DATE)
341             || index.column() == GetColIx(COL_TIME)
342             || index.column() == GetColIx(COL_DOUBLES))
343         {
344             return QVariant(Qt::AlignHCenter | Qt::AlignVCenter);
345         }
346         return QVariant(Qt::AlignRight | Qt::AlignVCenter);
347     }
348     else if (role == Qt::BackgroundRole)
349     {
350         if (index == mEditIndex)
351         {
352             return QVariant(QApplication::palette().color(QPalette::Active, QPalette::Highlight));
353         }
354         else if (index.row() == mHoverRow)
355         {
356             return QVariant(mRowHBg);
357         }
358     }
359     else if (role == Qt::ForegroundRole)
360     {
361         if (index == mEditIndex)
362         {
363             return QVariant(QApplication::palette().color(QPalette::Active, QPalette::HighlightedText));
364         }
365         else if (index.row() == mHoverRow)
366         {
367             return QVariant(mRowHFg);
368         }
369     }
370     else if (role == Qt::DisplayRole || role == Qt::EditRole)
371     {
372         CCGame g = mGamesList.at(index.row());
373         if (index.column() == GetColIx(COL_RANKING))
374         {
375             return index.row() + 1;
376         }
377         else if (index.column() == GetColIx(COL_USERNAME))
378         {
379             return g.GetUserName();
380         }
381         else if (index.column() == GetColIx(COL_SCORE))
382         {
383             return g.GetScore();
384         }
385         else if (index.column() == GetColIx(COL_DATE))
386         {
387             return g.GetDatePartStr();
388         }
389         else if (index.column() == GetColIx(COL_TIME))
390         {
391             return g.GetTimePartStr();
392         }
393         else if (index.column() == GetColIx(COL_CCNT))
394         {
395             return g.mColorCnt;
396         }
397         else if (index.column() == GetColIx(COL_PCNT))
398         {
399             return g.mPegCnt;
400         }
401         else if (index.column() == GetColIx(COL_GAMENO))
402         {
403             return g.mGameNo;
404         }
405         else if (index.column() == GetColIx(COL_DOUBLES))
406         {
407             return (g.mDoubles == 1) ? tr("Yes") : tr("No");
408         }
409         else
410         {
411             return QVariant();
412         }
413     }
414 
415     return QVariant();
416 }
417 
headerData(int section,Qt::Orientation orientation,int role) const418 QVariant GamesListModel::headerData(int section, Qt::Orientation orientation, int role) const
419 {
420     if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
421     {
422         return GetHHeaderLabel(section);
423     }
424     else if (role == Qt::DecorationRole && orientation == Qt::Horizontal)
425     {
426         if (section == GetColIx(COL_DOUBLES))
427         {
428             return QVariant(QIcon(":/img/same_color_header.png"));
429         }
430     }
431     else if (role == Qt::ToolTipRole && orientation == Qt::Horizontal)
432     {
433         if (section == GetColIx(COL_DOUBLES))
434         {
435             return QVariant(QString(tr("Pegs of Same Color")));
436         }
437         else if (section == GetColIx(COL_DELETE))
438         {
439             return QVariant(QString(tr("Actions")));
440         }
441         else if (section == GetColIx(COL_RANKING))
442         {
443             return QVariant(QString(tr("Rank")));
444         }
445     }
446     return QVariant();
447 }
448 
GetHHeaderLabel(const int col) const449 QString GamesListModel::GetHHeaderLabel(const int col) const
450 {
451     QString str;
452     if (col == GetColIx(COL_RANKING))
453     {
454         str = "";
455     }
456     else if (col == GetColIx(COL_USERNAME))
457     {
458         str = tr("User");
459     }
460     else if (col == GetColIx(COL_SCORE))
461     {
462         str = tr("Score");
463     }
464     else if (col == GetColIx(COL_DATE))
465     {
466         str = tr("Date");
467     }
468     else if (col == GetColIx(COL_TIME))
469     {
470         str = tr("Time");
471     }
472     else if (col == GetColIx(COL_CCNT))
473     {
474         str = tr("Colors");
475     }
476     else if (col == GetColIx(COL_PCNT))
477     {
478         str = tr("Slots");
479     }
480     else if (col == GetColIx(COL_GAMENO))
481     {
482         str = tr("Game No.");
483     }
484     else
485     {
486         str = "";
487     }
488     return str;
489 }
490