]>
Commit | Line | Data |
---|---|---|
1 | /**************************************************************************** | |
2 | ** | |
3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). | |
4 | ** Contact: http://www.qt-project.org/legal | |
5 | ** | |
6 | ** This file is part of the QtGui module of the Qt Toolkit. | |
7 | ** | |
8 | ** $QT_BEGIN_LICENSE:LGPL$ | |
9 | ** Commercial License Usage | |
10 | ** Licensees holding valid commercial Qt licenses may use this file in | |
11 | ** accordance with the commercial license agreement provided with the | |
12 | ** Software or, alternatively, in accordance with the terms contained in | |
13 | ** a written agreement between you and Digia. For licensing terms and | |
14 | ** conditions see http://qt.digia.com/licensing. For further information | |
15 | ** use the contact form at http://qt.digia.com/contact-us. | |
16 | ** | |
17 | ** GNU Lesser General Public License Usage | |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | |
19 | ** General Public License version 2.1 as published by the Free Software | |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the | |
21 | ** packaging of this file. Please review the following information to | |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements | |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | |
24 | ** | |
25 | ** In addition, as a special exception, Digia gives you certain additional | |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception | |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | |
28 | ** | |
29 | ** GNU General Public License Usage | |
30 | ** Alternatively, this file may be used under the terms of the GNU | |
31 | ** General Public License version 3.0 as published by the Free Software | |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the | |
33 | ** packaging of this file. Please review the following information to | |
34 | ** ensure the GNU General Public License version 3.0 requirements will be | |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. | |
36 | ** | |
37 | ** | |
38 | ** $QT_END_LICENSE$ | |
39 | ** | |
40 | ****************************************************************************/ | |
41 | ||
42 | #include <QPainter> | |
43 | #include <QPaintEvent> | |
44 | #include <QStyle> | |
45 | #include <QStyleOptionFrame> | |
46 | ||
47 | #include "wellarray.h" | |
48 | ||
49 | void QWellArray::paintEvent(QPaintEvent *e) | |
50 | { | |
51 | QRect r = e->rect(); | |
52 | int cx = r.x(); | |
53 | int cy = r.y(); | |
54 | int ch = r.height(); | |
55 | int cw = r.width(); | |
56 | int colfirst = columnAt(cx); | |
57 | int collast = columnAt(cx + cw); | |
58 | int rowfirst = rowAt(cy); | |
59 | int rowlast = rowAt(cy + ch); | |
60 | ||
61 | if (isRightToLeft()) { | |
62 | int t = colfirst; | |
63 | colfirst = collast; | |
64 | collast = t; | |
65 | } | |
66 | ||
67 | QPainter painter(this); | |
68 | QPainter *p = &painter; | |
69 | QRect rect(0, 0, cellWidth(), cellHeight()); | |
70 | ||
71 | ||
72 | if (collast < 0 || collast >= ncols) | |
73 | collast = ncols-1; | |
74 | if (rowlast < 0 || rowlast >= nrows) | |
75 | rowlast = nrows-1; | |
76 | ||
77 | // Go through the rows | |
78 | for (int r = rowfirst; r <= rowlast; ++r) { | |
79 | // get row position and height | |
80 | int rowp = rowY(r); | |
81 | ||
82 | // Go through the columns in the row r | |
83 | // if we know from where to where, go through [colfirst, collast], | |
84 | // else go through all of them | |
85 | for (int c = colfirst; c <= collast; ++c) { | |
86 | // get position and width of column c | |
87 | int colp = columnX(c); | |
88 | // Translate painter and draw the cell | |
89 | rect.translate(colp, rowp); | |
90 | paintCell(p, r, c, rect); | |
91 | rect.translate(-colp, -rowp); | |
92 | } | |
93 | } | |
94 | } | |
95 | ||
96 | struct QWellArrayData { | |
97 | QBrush *brush; | |
98 | }; | |
99 | ||
100 | QWellArray::QWellArray(int rows, int cols, QWidget *parent) | |
101 | : QWidget(parent) | |
102 | ,nrows(rows), ncols(cols) | |
103 | { | |
104 | d = 0; | |
105 | setFocusPolicy(Qt::StrongFocus); | |
106 | cellw = 28; | |
107 | cellh = 24; | |
108 | curCol = 0; | |
109 | curRow = 0; | |
110 | selCol = -1; | |
111 | selRow = -1; | |
112 | } | |
113 | ||
114 | QSize QWellArray::sizeHint() const | |
115 | { | |
116 | ensurePolished(); | |
117 | return gridSize().boundedTo(QSize(640, 480)); | |
118 | } | |
119 | ||
120 | ||
121 | void QWellArray::paintCell(QPainter* p, int row, int col, const QRect &rect) | |
122 | { | |
123 | int b = 3; //margin | |
124 | ||
125 | const QPalette & g = palette(); | |
126 | QStyleOptionFrame opt; | |
127 | int dfw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); | |
128 | opt.lineWidth = dfw; | |
129 | opt.midLineWidth = 1; | |
130 | opt.rect = rect.adjusted(b, b, -b, -b); | |
131 | opt.palette = g; | |
132 | opt.state = QStyle::State_Enabled | QStyle::State_Sunken; | |
133 | style()->drawPrimitive(QStyle::PE_Frame, &opt, p, this); | |
134 | b += dfw; | |
135 | ||
136 | if ((row == curRow) && (col == curCol)) { | |
137 | if (hasFocus()) { | |
138 | QStyleOptionFocusRect opt; | |
139 | opt.palette = g; | |
140 | opt.rect = rect; | |
141 | opt.state = QStyle::State_None | QStyle::State_KeyboardFocusChange; | |
142 | style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, this); | |
143 | } | |
144 | } | |
145 | paintCellContents(p, row, col, opt.rect.adjusted(dfw, dfw, -dfw, -dfw)); | |
146 | } | |
147 | ||
148 | /*! | |
149 | Reimplement this function to change the contents of the well array. | |
150 | */ | |
151 | void QWellArray::paintCellContents(QPainter *p, int row, int col, const QRect &r) | |
152 | { | |
153 | if (d) { | |
154 | p->fillRect(r, d->brush[row*numCols()+col]); | |
155 | } else { | |
156 | p->fillRect(r, Qt::white); | |
157 | p->setPen(Qt::black); | |
158 | p->drawLine(r.topLeft(), r.bottomRight()); | |
159 | p->drawLine(r.topRight(), r.bottomLeft()); | |
160 | } | |
161 | } | |
162 | ||
163 | void QWellArray::mousePressEvent(QMouseEvent *e) | |
164 | { | |
165 | // The current cell marker is set to the cell the mouse is pressed in | |
166 | QPoint pos = e->pos(); | |
167 | setCurrent(rowAt(pos.y()), columnAt(pos.x())); | |
168 | } | |
169 | ||
170 | void QWellArray::mouseReleaseEvent(QMouseEvent * /* event */) | |
171 | { | |
172 | // The current cell marker is set to the cell the mouse is clicked in | |
173 | setSelected(curRow, curCol); | |
174 | } | |
175 | ||
176 | ||
177 | /* | |
178 | Sets the cell currently having the focus. This is not necessarily | |
179 | the same as the currently selected cell. | |
180 | */ | |
181 | ||
182 | void QWellArray::setCurrent(int row, int col) | |
183 | { | |
184 | if ((curRow == row) && (curCol == col)) | |
185 | return; | |
186 | ||
187 | if (row < 0 || col < 0) | |
188 | row = col = -1; | |
189 | ||
190 | int oldRow = curRow; | |
191 | int oldCol = curCol; | |
192 | ||
193 | curRow = row; | |
194 | curCol = col; | |
195 | ||
196 | updateCell(oldRow, oldCol); | |
197 | updateCell(curRow, curCol); | |
198 | } | |
199 | ||
200 | /* | |
201 | Sets the currently selected cell to \a row, \a column. If \a row or | |
202 | \a column are less than zero, the current cell is unselected. | |
203 | ||
204 | Does not set the position of the focus indicator. | |
205 | */ | |
206 | void QWellArray::setSelected(int row, int col) | |
207 | { | |
208 | int oldRow = selRow; | |
209 | int oldCol = selCol; | |
210 | ||
211 | if (row < 0 || col < 0) | |
212 | row = col = -1; | |
213 | ||
214 | selCol = col; | |
215 | selRow = row; | |
216 | ||
217 | updateCell(oldRow, oldCol); | |
218 | updateCell(selRow, selCol); | |
219 | if (row >= 0) | |
220 | Q_EMIT selected(row, col); | |
221 | } | |
222 | ||
223 | void QWellArray::focusInEvent(QFocusEvent*) | |
224 | { | |
225 | updateCell(curRow, curCol); | |
226 | } | |
227 | ||
228 | void QWellArray::setCellBrush(int row, int col, const QBrush &b) | |
229 | { | |
230 | if (!d) { | |
231 | d = new QWellArrayData; | |
232 | int i = numRows()*numCols(); | |
233 | d->brush = new QBrush[i]; | |
234 | } | |
235 | if (row >= 0 && row < numRows() && col >= 0 && col < numCols()) | |
236 | d->brush[row*numCols()+col] = b; | |
237 | } | |
238 | ||
239 | /* | |
240 | Returns the brush set for the cell at \a row, \a column. If no brush is | |
241 | set, Qt::NoBrush is returned. | |
242 | */ | |
243 | ||
244 | QBrush QWellArray::cellBrush(int row, int col) | |
245 | { | |
246 | if (d && row >= 0 && row < numRows() && col >= 0 && col < numCols()) | |
247 | return d->brush[row*numCols()+col]; | |
248 | return Qt::NoBrush; | |
249 | } | |
250 | ||
251 | ||
252 | ||
253 | /*!\reimp | |
254 | */ | |
255 | ||
256 | void QWellArray::focusOutEvent(QFocusEvent*) | |
257 | { | |
258 | updateCell(curRow, curCol); | |
259 | } | |
260 | ||
261 | /*\reimp | |
262 | */ | |
263 | void QWellArray::keyPressEvent(QKeyEvent* e) | |
264 | { | |
265 | switch(e->key()) { // Look at the key code | |
266 | case Qt::Key_Left: // If 'left arrow'-key, | |
267 | if(curCol > 0) // and cr't not in leftmost col | |
268 | setCurrent(curRow, curCol - 1); // set cr't to next left column | |
269 | break; | |
270 | case Qt::Key_Right: // Correspondingly... | |
271 | if(curCol < numCols()-1) | |
272 | setCurrent(curRow, curCol + 1); | |
273 | break; | |
274 | case Qt::Key_Up: | |
275 | if(curRow > 0) | |
276 | setCurrent(curRow - 1, curCol); | |
277 | break; | |
278 | case Qt::Key_Down: | |
279 | if(curRow < numRows()-1) | |
280 | setCurrent(curRow + 1, curCol); | |
281 | break; | |
282 | case Qt::Key_Space: | |
283 | setSelected(curRow, curCol); | |
284 | break; | |
285 | default: // If not an interesting key, | |
286 | e->ignore(); // we don't accept the event | |
287 | return; | |
288 | } | |
289 | ||
290 | } |