3465e78090c31ea503d112bad6a8f7378ce3d94e
[colorflood] / colorflood / src / field.cpp
1 /*
2   Copyright 2010 Serge Ziryukin <ftrvxmtrx@gmail.com>
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 of the License.
7
8   This program is distributed in the hope that it will be useful,
9   but WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11   GNU General Public License for more details.
12 */
13
14 #include <QtGui>
15 #include "field.hpp"
16 #include "colorscheme.hpp"
17
18 static const int fieldWidth = 420;
19
20 const int Field::rects[Field::NUM_SIZES] = { 14, 21, 28 };
21 const int Field::turns[Field::NUM_SIZES] = { 25, 35, 50 };
22
23 // we declare out QVector<FieldRect> metatype
24 // and stream operators to save whole field to settings
25 Q_DECLARE_METATYPE(Field::RectVector);
26
27 static QDataStream &operator<< (QDataStream &out, const Field::RectVector &rv)
28 {
29     for (QVector<Field::FieldRect>::const_iterator rect = rv.begin();
30          rect != rv.end();
31          rect++)
32     {
33         out << (*rect).brush;
34         out << (*rect).flood;
35     }
36
37     return out;
38 }
39
40 static QDataStream &operator>> (QDataStream &in, Field::RectVector &rv)
41 {
42     Field::FieldRect r;
43
44     rv.clear();
45
46     for (; !in.atEnd() ;)
47     {
48         in >> r.brush >> r.flood;
49         rv << r;
50     }
51
52     rv.pop_back();
53
54     return in;
55 }
56
57 Field::Field (QWidget *parent)
58     : QWidget (parent)
59 {
60     setFixedSize(fieldWidth, fieldWidth);
61
62     // restore field size and field itself from settings
63
64     qRegisterMetaType<RectVector>("Field::RectVector");
65     qRegisterMetaTypeStreamOperators<RectVector>("Field::RectVector");
66
67     QSettings settings;
68
69     int size = settings.value("field/fieldSize", SIZE_SMALL).toInt();
70
71     if (size < SIZE_SMALL || size >= NUM_SIZES)
72         size = SIZE_SMALL;
73
74     this->size = (FieldSize)size;
75
76     if (settings.contains("field/data"))
77         data = settings.value("field/data").value<RectVector>();
78
79     if (data.size() != rects[size] * rects[size])
80         randomize();
81 }
82
83 Field::~Field ()
84 {
85     QSettings settings;
86
87     settings.setValue("field/size", size);
88
89     QVariant v;
90     v.setValue(data);
91     settings.setValue("field/data", v);
92 }
93
94 Field::FieldSize Field::getSize () const
95 {
96     return size;
97 }
98
99 void Field::randomize ()
100 {
101     FieldRect rect;
102     rect.flood = false;
103
104     data.clear();
105     data = RectVector(rects[size] * rects[size], rect);
106
107     qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
108
109     int numBrushes = ColorScheme::instance().getScheme().size();
110
111     for (QVector<FieldRect>::iterator rect = data.begin();
112          rect != data.end();
113          rect++)
114     {
115         (*rect).brush = qrand() % numBrushes;
116     }
117
118     update();
119 }
120
121 int Field::getNumRectsOfSize (FieldSize size)
122 {
123     return rects[size];
124 }
125
126 int Field::getNumTurnsOfSize (FieldSize size)
127 {
128     return turns[size];
129 }
130
131 int Field::getRectSize (FieldSize size)
132 {
133     return fieldWidth / rects[size];
134 }
135
136 void Field::paintEvent (QPaintEvent *event)
137 {
138     QPainter painter;
139     painter.begin(this);
140
141     QRect rect = QRect(0, 0, getRectSize(size), getRectSize(size));
142
143     const QVector<QBrush> &scheme = ColorScheme::instance().getScheme();
144
145     for (int y = 0; y < rects[size] ;y++)
146     {
147         int n = y * rects[size];
148
149         for (int x = 0; x < rects[size] ;x++, n++)
150         {
151             rect.moveTo(x * rect.width(), y * rect.height());
152
153             if (rect.intersects(event->rect()))
154                 painter.fillRect(rect, scheme.at(data[n].brush));
155         }
156     }
157
158     painter.end();
159 }