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 <QtWidgets>
20 
21 #include "rowhint.h"
22 
23 using namespace std;
24 
25 const int RowHint::mPegPos[4][5][3] = {
26                                             {
27                                                 {  6, 14, 12 },
28                                                 { 22, 14, 12 },
29                                                 {  0,  0,  0 },
30                                                 {  0,  0,  0 },
31                                                 {  0,  0,  0 },
32                                             },
33                                             {
34                                                 {  6,  7, 12 },
35                                                 { 22,  7, 12 },
36                                                 { 14, 21, 12 },
37                                                 {  0,  0,  0 },
38                                                 {  0,  0,  0 },
39                                             },
40                                             {
41                                                 {  6,  6, 12 },
42                                                 { 22,  6, 12 },
43                                                 {  6, 22, 12 },
44                                                 { 22, 22, 12 },
45                                                 {  0,  0,  0 },
46                                             },
47                                             {
48                                                 {  4,  4, 12 },
49                                                 { 24,  4, 12 },
50                                                 { 14, 14, 12 },
51                                                 {  4, 24, 12 },
52                                                 { 24, 24, 12 }
53                                             }
54                                         };
55 
RowHint(QObject *)56 RowHint::RowHint(QObject*)
57 {
58     mIx = -1;
59     mPegCnt = 0;
60 
61     mPen = QPen(QColor("#808080"));
62     mPen.setWidth(2);
63 
64     QRadialGradient grad(QPointF(10, 10), 100);
65     grad.setColorAt(0, QColor("#d8d8d8"));
66     grad.setColorAt(1, QColor("#ffffff"));
67     mBrush1 = QBrush(grad);
68     grad.setColorAt(0, QColor(216, 216, 216, 51));
69     grad.setColorAt(1, QColor(255, 255, 255, 51));
70     mBrush0 = QBrush(grad);
71 
72     Reset(0, 0);
73 }
74 
~RowHint()75 RowHint::~RowHint()
76 {
77     scene()->removeItem(this);
78 }
79 
Reset(const int pegcnt,const int gamemode)80 void RowHint::Reset(const int pegcnt, const int gamemode)
81 {
82     mActive = true;
83     mSolved = false;
84     SetPegCnt(pegcnt);
85     mHints.clear();
86     mHints.assign(mPegCnt, 0);
87     SetGameMode(gamemode);
88     SetActive(false);
89 }
90 
GetIx() const91 int RowHint::GetIx() const
92 {
93     return mIx;
94 }
95 
SetIx(const int ix)96 void RowHint::SetIx(const int ix)
97 {
98     mIx = ix;
99 }
100 
SetPegCnt(const int pegcnt)101 void RowHint::SetPegCnt(const int pegcnt)
102 {
103     mPegCnt = pegcnt;
104 }
105 
SetGameMode(const int gamemode)106 void RowHint::SetGameMode(const int gamemode)
107 {
108     mGameMode = gamemode;
109 }
110 
IsActive() const111 bool RowHint::IsActive() const
112 {
113     return mActive;
114 }
115 
SetActive(bool b)116 void RowHint::SetActive(bool b)
117 {
118     if (b == mActive)
119     {
120         return;
121     }
122 
123     mActive = b;
124     setAcceptHoverEvents(b);
125     setEnabled(b);
126     if (b)
127     {
128         if (mGameMode == ColorCode::MODE_HVM)
129         {
130             setCursor(Qt::PointingHandCursor);
131             setToolTip(tr("Commit Your solution"));
132         }
133         else if (mGameMode == ColorCode::MODE_MVH)
134         {
135             mSolved = true;
136             mHints.assign(mPegCnt, 0);
137             setCursor(Qt::ArrowCursor);
138             setToolTip(tr("Click the circles to rate my guess.\nHit Ctrl+H or the corresponding toolbar button to let an impartial part of me do this for you ;-)"));
139         }
140     }
141     else
142     {
143         setCursor(Qt::ArrowCursor);
144         setToolTip(QString(""));
145     }
146 
147     update(boundingRect());
148 }
149 
SetPaused(const bool b)150 void RowHint::SetPaused(const bool b)
151 {
152     if (b)
153     {
154         setCursor(Qt::ArrowCursor);
155         setToolTip(QString(""));
156     }
157     else if (mActive)
158     {
159         setCursor(Qt::PointingHandCursor);
160         setToolTip(tr("Commit Your solution"));
161     }
162     update(boundingRect());
163 }
164 
GetHints()165 std::vector<int> RowHint::GetHints()
166 {
167     return mHints;
168 }
169 
DrawHints(std::vector<int> res)170 void RowHint::DrawHints(std::vector<int> res)
171 {
172     mHints.clear();
173     mHints.assign(mPegCnt, 0);
174     for (unsigned i = 0; i < res.size(); ++i)
175     {
176         mHints.at(i) = res.at(i);
177     }
178     mSolved = true;
179     update(boundingRect());
180 }
181 
mousePressEvent(QGraphicsSceneMouseEvent * e)182 void RowHint::mousePressEvent(QGraphicsSceneMouseEvent* e)
183 {
184     if (ColorCode::INSTANCE->GetGameState() == ColorCode::STATE_PAUSED)
185     {
186         return;
187     }
188 
189     if (e->button() != Qt::LeftButton)
190     {
191         return;
192     }
193 
194     if (mGameMode == ColorCode::MODE_HVM)
195     {
196         bool disabled = false;
197         if (mActive && !mSolved)
198         {
199             if (e->button() == Qt::LeftButton)
200             {
201                 SetActive(false);
202                 emit HintPressedSignal(mIx);
203                 disabled = true;
204             }
205         }
206 
207         if (!disabled)
208         {
209             QGraphicsItem::mousePressEvent(e);
210         }
211     }
212     else if (mGameMode == ColorCode::MODE_MVH)
213     {
214         qreal xm = e->pos().x();
215         qreal ym = e->pos().y();
216 
217         int posix = mPegCnt - 2;
218         for (int i = 0; i < mPegCnt; i++)
219         {
220             if ( xm >= mPegPos[posix][i][0] && xm <= mPegPos[posix][i][0] + mPegPos[posix][i][2]
221                  && ym >= mPegPos[posix][i][1] && ym <= mPegPos[posix][i][1] + mPegPos[posix][i][2])
222             {
223                 ++mHints.at(i);
224                 if (mHints.at(i) > 2)
225                 {
226                     mHints.at(i) = 0;
227                 }
228             }
229         }
230         update(boundingRect());
231     }
232 }
233 
shape() const234 QPainterPath RowHint::shape() const
235 {
236     QPainterPath path;
237     path.addRect(boundingRect());
238     return path;
239 }
240 
boundingRect() const241 QRectF RowHint::boundingRect() const
242 {
243     const int margin = 1;
244     return outlineRect().adjusted(-margin, -margin, 2 * margin, 2 * margin);
245 }
246 
outlineRect() const247 QRectF RowHint::outlineRect() const
248 {
249     return QRectF(0.0, 0.0, 40.0, 40.0);
250 }
251 
paint(QPainter * painter,const QStyleOptionGraphicsItem *,QWidget *)252 void RowHint::paint(QPainter* painter, const QStyleOptionGraphicsItem* , QWidget* )
253 {
254     if (mPegCnt == 0)
255     {
256         return;
257     }
258 
259     int i;
260 
261     QColor pend = QColor("#646568");
262     QColor penl = QColor("#ecedef");
263     QColor grad0 = QColor("#cccdcf");
264     QColor grad1 = QColor("#fcfdff");
265     if (mActive)
266     {
267         pend.setAlpha(0xff);
268         penl.setAlpha(0xff);
269         grad0.setAlpha(0xff);
270         grad1.setAlpha(0xff);
271     }
272     else if (mSolved)
273     {
274         pend.setAlpha(0xa0);
275         penl.setAlpha(0xa0);
276         grad0.setAlpha(0xa0);
277         grad1.setAlpha(0xa0);
278     }
279     else
280     {
281         pend.setAlpha(0x32);
282         penl.setAlpha(0x50);
283         grad0.setAlpha(0x32);
284         grad1.setAlpha(0x32);
285     }
286     painter->setPen(Qt::NoPen);
287 
288     painter->setBrush(QBrush(penl));
289     painter->drawRect(QRectF(0.0, 0.0, 39, 1));
290     painter->drawRect(QRectF(0.0, 0.0, 1, 39));
291     painter->setBrush(QBrush(pend));
292     painter->drawRect(QRectF(0.0, 39.0, 40, 1));
293     painter->drawRect(QRectF(39, 0.0, 1, 40));
294 
295     QRadialGradient grad(QPointF(10, 10), 100);
296     grad.setColorAt(0, grad0);
297     grad.setColorAt(1, grad1);
298     painter->setBrush(QBrush(grad));
299     painter->drawRect(QRectF(1, 1.0, 38.0, 38.0));
300 
301     painter->setBrush(Qt::NoBrush);
302 
303     int posix = mPegCnt - 2;
304     QPointF x0;
305     for (i = 0; i < mPegCnt; i++)
306     {
307         x0 = QPointF(mPegPos[posix][i][0], mPegPos[posix][i][1]);
308         QLinearGradient lgrad(x0, QPointF(x0.x() + 10, x0.y() + 10));
309         lgrad.setColorAt(0.0, QColor(0, 0, 0, 0xa0));
310         lgrad.setColorAt(1.0, QColor(0xff, 0xff, 0xff, 0xa0));
311         painter->setPen(QPen(QBrush(lgrad), 0.5));
312         painter->drawEllipse(QRectF(mPegPos[posix][i][0], mPegPos[posix][i][1], mPegPos[posix][i][2], mPegPos[posix][i][2]));
313     }
314 
315     if (mSolved && ColorCode::INSTANCE->GetGameState() != ColorCode::STATE_PAUSED)
316     {
317         painter->setPen(Qt::NoPen);
318         for (unsigned i = 0; i < mHints.size(); i++)
319         {
320             if (mHints.at(i) == 0)
321             {
322                 continue;
323             }
324 
325             if (mHints.at(i) == 2)
326             {
327                 painter->setBrush(QBrush(Qt::black));
328             }
329             else
330             {
331                 painter->setBrush(QBrush(Qt::white));
332             }
333             painter->drawEllipse(QRectF(mPegPos[posix][i][0], mPegPos[posix][i][1], mPegPos[posix][i][2], mPegPos[posix][i][2]));
334         }
335     }
336 }
337