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 "colorpeg.h"
22 #include "pegrow.h"
23 #include "rowhint.h"
24
25 using namespace std;
26
PegRow(QObject *)27 PegRow::PegRow(QObject*)
28 {
29 setAcceptedMouseButtons(0);
30
31 mIx = -1;
32 mPegCnt = 0;
33 mXOffs = 0;
34 mPend = QColor("#646568");
35 mPenl = QColor("#ecedef");
36 mGrad0 = QColor("#cccdcf");
37 mGrad1 = QColor("#fcfdff");
38
39 mColorPegs = NULL;
40
41 Reset(0, 0);
42 }
43
~PegRow()44 PegRow::~PegRow()
45 {
46 for (int i = 0; i < mPegCnt; ++i)
47 {
48 delete mColorPegs[i];
49 }
50 delete [] mColorPegs;
51 mColorPegs = NULL;
52 }
53
IsActive() const54 bool PegRow::IsActive() const
55 {
56 return mIsActive;
57 }
58
Reset(const int pegcnt,const int gamemode)59 void PegRow::Reset(const int pegcnt, const int gamemode)
60 {
61 ClearRow();
62 mSolution.clear();
63 SetActive(false);
64 mSolved = false;
65 SetPegCnt(pegcnt);
66 SetGameMode(gamemode);
67 }
68
ClearRow()69 void PegRow::ClearRow()
70 {
71 if (mColorPegs == NULL) { return; };
72
73 for (int i = 0; i < mPegCnt; ++i)
74 {
75 if (mColorPegs[i] != NULL)
76 {
77 emit(RemovePegSignal(mColorPegs[i]));
78 }
79 }
80 }
81
GetIx() const82 int PegRow::GetIx() const
83 {
84 return mIx;
85 }
86
SetIx(const int ix)87 void PegRow::SetIx(const int ix)
88 {
89 mIx = ix;
90 }
91
SetPegCnt(const int pegcnt)92 void PegRow::SetPegCnt(const int pegcnt)
93 {
94 ClearRow();
95 for (int i = 0; i < mPegCnt; ++i)
96 {
97 delete mColorPegs[i];
98 }
99 delete [] mColorPegs;
100 mColorPegs = NULL;
101
102 mPegCnt = pegcnt;
103 mColorPegs = new ColorPeg* [mPegCnt];
104 for (int i = 0; i < mPegCnt; ++i)
105 {
106 mColorPegs[i] = NULL;
107 }
108 SetXOffs();
109 }
110
SetGameMode(const int gamemode)111 void PegRow::SetGameMode(const int gamemode)
112 {
113 mGameMode = gamemode;
114 }
115
SetXOffs()116 void PegRow::SetXOffs()
117 {
118 mXOffs = 100 - mPegCnt * 20;
119 }
120
GetPegCnt() const121 int PegRow::GetPegCnt() const
122 {
123 if (mColorPegs == NULL) { return 0; };
124
125 int cnt = 0;
126 int i = 0;
127 for (i = 0; i < mPegCnt; ++i)
128 {
129 if (mColorPegs[i] != NULL)
130 {
131 ++cnt;
132 }
133 }
134 return cnt;
135 }
136
GetPegs()137 ColorPeg** PegRow::GetPegs()
138 {
139 return mColorPegs;
140 }
141
SetActive(const bool b)142 void PegRow::SetActive(const bool b)
143 {
144 mIsActive = b;
145 update(boundingRect());
146 }
147
SnapCP(ColorPeg * cp)148 bool PegRow::SnapCP(ColorPeg *cp)
149 {
150 if (mColorPegs == NULL)
151 {
152 return false;
153 }
154
155 bool snapped = false;
156 if (mIsActive)
157 {
158 QPointF p = mapFromParent(cp->pos());
159
160 p.rx() += 18;
161 p.ry() += 18;
162
163 int ix = -1;
164 int i;
165
166 if (p.y() >= 0 && p.y() <= 40)
167 {
168 for (i = 0; i < mPegCnt; ++i)
169 {
170 if (p.x() >= mXOffs + i * 40 && p.x() < mXOffs + (i + 1) * 40)
171 {
172 if (mColorPegs[i] != NULL)
173 {
174 emit RemovePegSignal(mColorPegs[i]);
175 mColorPegs[i] = NULL;
176 }
177 mColorPegs[i] = cp;
178 cp->SetPegRow(this);
179 ix = i;
180 cp->setPos(mapToParent(mXOffs + i * 40 + 2, 2));
181 break;
182 }
183 }
184 }
185
186 snapped = ix > -1;
187 CheckSolution();
188 }
189
190 return snapped;
191 }
192
ForceSnap(ColorPeg * cp,int posix)193 void PegRow::ForceSnap(ColorPeg* cp, int posix)
194 {
195 if (mColorPegs == NULL)
196 {
197 return;
198 }
199
200 if (posix > mPegCnt - 1)
201 {
202 return;
203 }
204
205 if (mIsActive)
206 {
207 if (mColorPegs[posix] != NULL)
208 {
209 emit RemovePegSignal(mColorPegs[posix]);
210 mColorPegs[posix] = NULL;
211 }
212 mColorPegs[posix] = cp;
213 cp->setSelected(false);
214 cp->SetPegRow(this);
215 cp->setPos(mapToParent(mXOffs + posix * 40 + 2, 2));
216
217 CheckSolution();
218 }
219 }
220
CloseRow()221 void PegRow::CloseRow()
222 {
223 mSolved = true;
224 if (mColorPegs == NULL)
225 {
226 ;
227 }
228 else
229 {
230 for (int i = 0; i < mPegCnt; ++i)
231 {
232 if (mColorPegs[i] != NULL)
233 {
234 mColorPegs[i]->SetEnabled(false);
235 }
236 }
237 }
238 SetActive(false);
239 }
240
OpenRow()241 void PegRow::OpenRow()
242 {
243 mSolved = false;
244 if (mColorPegs == NULL)
245 {
246 ;
247 }
248 else
249 {
250 for (int i = 0; i < mPegCnt; ++i)
251 {
252 if (mColorPegs[i] != NULL)
253 {
254 mColorPegs[i]->SetEnabled(true);
255 }
256 }
257 }
258 SetActive(true);
259 }
260
CheckSolution()261 void PegRow::CheckSolution()
262 {
263 mSolution.clear();
264 if (mColorPegs == NULL)
265 {
266 ;
267 }
268 else
269 {
270 for (int i = 0; i < mPegCnt; ++i)
271 {
272 if (mColorPegs[i] != NULL)
273 {
274 mSolution.push_back(mColorPegs[i]->GetPegType()->ix);
275 }
276 }
277 }
278 emit RowSolutionSignal(mIx);
279 }
280
GetSolution() const281 std::vector<int> PegRow::GetSolution() const
282 {
283 return mSolution;
284 }
285
RemovePeg(ColorPeg * cp)286 void PegRow::RemovePeg(ColorPeg *cp)
287 {
288 if (mColorPegs == NULL)
289 {
290 return;
291 }
292
293 for (int i = 0; i < mPegCnt; ++i)
294 {
295 if (mColorPegs[i] == cp)
296 {
297 mColorPegs[i] = NULL;
298 if (mIsActive)
299 {
300 CheckSolution();
301 }
302 }
303 }
304 }
305
shape() const306 QPainterPath PegRow::shape() const
307 {
308 QPainterPath path;
309 path.addRect(boundingRect());
310 return path;
311 }
312
boundingRect() const313 QRectF PegRow::boundingRect() const
314 {
315 const int Margin = 1;
316 return outlineRect().adjusted(-Margin, -Margin, +Margin, +Margin);
317 }
318
outlineRect() const319 QRectF PegRow::outlineRect() const
320 {
321 return QRectF(0.0, 0.0, 200.0, 40.0);
322 }
323
paint(QPainter * painter,const QStyleOptionGraphicsItem *,QWidget *)324 void PegRow::paint(QPainter* painter, const QStyleOptionGraphicsItem* , QWidget* )
325 {
326 if (mPegCnt == 0)
327 {
328 return;
329 }
330
331 painter->setRenderHint(QPainter::Antialiasing, true);
332
333 if (mIsActive)
334 {
335 mPend.setAlpha(0xff);
336 mPenl.setAlpha(0xff);
337 mGrad0.setAlpha(0xff);
338 mGrad1.setAlpha(0xff);
339 }
340 else if (mSolved)
341 {
342 mPend.setAlpha(0xa0);
343 mPenl.setAlpha(0xa0);
344 mGrad0.setAlpha(0xa0);
345 mGrad1.setAlpha(0xa0);
346 }
347 else
348 {
349 mPend.setAlpha(0x32);
350 mPenl.setAlpha(0x50);
351 mGrad0.setAlpha(0x32);
352 mGrad1.setAlpha(0x32);
353 }
354 painter->setPen(Qt::NoPen);
355 int i;
356 for (i = 0; i < mPegCnt; i++)
357 {
358 painter->setBrush(QBrush(mPenl));
359 painter->drawRect(QRectF(mXOffs + i * 40, 0.0, 39, 1));
360 painter->drawRect(QRectF(mXOffs + i * 40, 0.0, 1, 39));
361 painter->setBrush(QBrush(mPend));
362 painter->drawRect(QRectF(mXOffs + i * 40, 39.0, 40, 1));
363 painter->drawRect(QRectF(mXOffs + i * 40 + 39, 0.0, 1, 40));
364
365 QRadialGradient grad(QPointF(mXOffs + i * 40 + 10, 10), 100);
366 grad.setColorAt(0, mGrad0);
367 grad.setColorAt(1, mGrad1);
368 painter->setBrush(QBrush(grad));
369 painter->drawRect(QRectF(mXOffs + i * 40 + 1, 1.0, 38.0, 38.0));
370 }
371 }
372