]>
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 <QPaintEvent> | |
43 | #include <QPainter> | |
44 | #include <QStyle> | |
45 | #include <QStyleOptionFrame> | |
46 | ||
47 | #include "wellarray.hpp" | |
48 | ||
49 | namespace pv { | |
50 | namespace widgets { | |
51 | ||
52 | void WellArray::paintEvent(QPaintEvent *event) | |
53 | { | |
54 | QRect r = event->rect(); | |
55 | int cx = r.x(); | |
56 | int cy = r.y(); | |
57 | int ch = r.height(); | |
58 | int cw = r.width(); | |
59 | int colfirst = columnAt(cx); | |
60 | int collast = columnAt(cx + cw); | |
61 | int rowfirst = rowAt(cy); | |
62 | int rowlast = rowAt(cy + ch); | |
63 | ||
64 | if (isRightToLeft()) { | |
65 | int t = colfirst; | |
66 | colfirst = collast; | |
67 | collast = t; | |
68 | } | |
69 | ||
70 | QPainter painter(this); | |
71 | QPainter *p = &painter; | |
72 | QRect rect(0, 0, cellWidth(), cellHeight()); | |
73 | ||
74 | ||
75 | if (collast < 0 || collast >= ncols) | |
76 | collast = ncols-1; | |
77 | if (rowlast < 0 || rowlast >= nrows) | |
78 | rowlast = nrows-1; | |
79 | ||
80 | // Go through the rows | |
81 | for (int r = rowfirst; r <= rowlast; ++r) { | |
82 | // get row position and height | |
83 | int rowp = rowY(r); | |
84 | ||
85 | // Go through the columns in the row r | |
86 | // if we know from where to where, go through [colfirst, collast], | |
87 | // else go through all of them | |
88 | for (int c = colfirst; c <= collast; ++c) { | |
89 | // get position and width of column c | |
90 | int colp = columnX(c); | |
91 | // Translate painter and draw the cell | |
92 | rect.translate(colp, rowp); | |
93 | paintCell(p, r, c, rect); | |
94 | rect.translate(-colp, -rowp); | |
95 | } | |
96 | } | |
97 | } | |
98 | ||
99 | struct WellArrayData { | |
100 | QBrush *brush; | |
101 | }; | |
102 | ||
103 | WellArray::WellArray(int rows, int cols, QWidget *parent) | |
104 | : QWidget(parent) | |
105 | ,nrows(rows), ncols(cols) | |
106 | { | |
107 | d = nullptr; | |
108 | setFocusPolicy(Qt::StrongFocus); | |
109 | cellw = 28; | |
110 | cellh = 24; | |
111 | curCol = 0; | |
112 | curRow = 0; | |
113 | selCol = -1; | |
114 | selRow = -1; | |
115 | } | |
116 | ||
117 | QSize WellArray::sizeHint() const | |
118 | { | |
119 | ensurePolished(); | |
120 | return gridSize().boundedTo(QSize(640, 480)); | |
121 | } | |
122 | ||
123 | ||
124 | void WellArray::paintCell(QPainter* p, int row, int col, const QRect &rect) | |
125 | { | |
126 | int b = 3; //margin | |
127 | ||
128 | const QPalette& g = palette(); | |
129 | QStyleOptionFrame opt; | |
130 | int dfw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); | |
131 | opt.lineWidth = dfw; | |
132 | opt.midLineWidth = 1; | |
133 | opt.rect = rect.adjusted(b, b, -b, -b); | |
134 | opt.palette = g; | |
135 | opt.state = QStyle::State_Enabled | QStyle::State_Sunken; | |
136 | style()->drawPrimitive(QStyle::PE_Frame, &opt, p, this); | |
137 | b += dfw; | |
138 | ||
139 | if ((row == curRow) && (col == curCol)) { | |
140 | if (hasFocus()) { | |
141 | QStyleOptionFocusRect opt; | |
142 | opt.palette = g; | |
143 | opt.rect = rect; | |
144 | opt.state = QStyle::State_None | QStyle::State_KeyboardFocusChange; | |
145 | style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, this); | |
146 | } | |
147 | } | |
148 | paintCellContents(p, row, col, opt.rect.adjusted(dfw, dfw, -dfw, -dfw)); | |
149 | } | |
150 | ||
151 | /*! | |
152 | Reimplement this function to change the contents of the well array. | |
153 | */ | |
154 | void WellArray::paintCellContents(QPainter *p, int row, int col, const QRect &r) | |
155 | { | |
156 | if (d) { | |
157 | p->fillRect(r, d->brush[row*numCols()+col]); | |
158 | } else { | |
159 | p->fillRect(r, Qt::white); | |
160 | p->setPen(Qt::black); | |
161 | p->drawLine(r.topLeft(), r.bottomRight()); | |
162 | p->drawLine(r.topRight(), r.bottomLeft()); | |
163 | } | |
164 | } | |
165 | ||
166 | void WellArray::mousePressEvent(QMouseEvent *event) | |
167 | { | |
168 | // The current cell marker is set to the cell the mouse is pressed in | |
169 | QPoint pos = event->pos(); | |
170 | setCurrent(rowAt(pos.y()), columnAt(pos.x())); | |
171 | } | |
172 | ||
173 | void WellArray::mouseReleaseEvent(QMouseEvent * /* event */) | |
174 | { | |
175 | // The current cell marker is set to the cell the mouse is clicked in | |
176 | setSelected(curRow, curCol); | |
177 | } | |
178 | ||
179 | ||
180 | /* | |
181 | Sets the cell currently having the focus. This is not necessarily | |
182 | the same as the currently selected cell. | |
183 | */ | |
184 | ||
185 | void WellArray::setCurrent(int row, int col) | |
186 | { | |
187 | if ((curRow == row) && (curCol == col)) | |
188 | return; | |
189 | ||
190 | if (row < 0 || col < 0) | |
191 | row = col = -1; | |
192 | ||
193 | int oldRow = curRow; | |
194 | int oldCol = curCol; | |
195 | ||
196 | curRow = row; | |
197 | curCol = col; | |
198 | ||
199 | updateCell(oldRow, oldCol); | |
200 | updateCell(curRow, curCol); | |
201 | } | |
202 | ||
203 | /* | |
204 | Sets the currently selected cell to \a row, \a column. If \a row or | |
205 | \a column are less than zero, the current cell is unselected. | |
206 | ||
207 | Does not set the position of the focus indicator. | |
208 | */ | |
209 | void WellArray::setSelected(int row, int col) | |
210 | { | |
211 | int oldRow = selRow; | |
212 | int oldCol = selCol; | |
213 | ||
214 | if (row < 0 || col < 0) | |
215 | row = col = -1; | |
216 | ||
217 | selCol = col; | |
218 | selRow = row; | |
219 | ||
220 | updateCell(oldRow, oldCol); | |
221 | updateCell(selRow, selCol); | |
222 | if (row >= 0) | |
223 | selected(row, col); | |
224 | } | |
225 | ||
226 | void WellArray::focusInEvent(QFocusEvent*) | |
227 | { | |
228 | updateCell(curRow, curCol); | |
229 | } | |
230 | ||
231 | void WellArray::setCellBrush(int row, int col, const QBrush &b) | |
232 | { | |
233 | if (!d) { | |
234 | d = new WellArrayData; | |
235 | int i = numRows()*numCols(); | |
236 | d->brush = new QBrush[i]; | |
237 | } | |
238 | if (row >= 0 && row < numRows() && col >= 0 && col < numCols()) | |
239 | d->brush[row*numCols()+col] = b; | |
240 | } | |
241 | ||
242 | /* | |
243 | Returns the brush set for the cell at \a row, \a column. If no brush is | |
244 | set, Qt::NoBrush is returned. | |
245 | */ | |
246 | ||
247 | QBrush WellArray::cellBrush(int row, int col) | |
248 | { | |
249 | if (d && row >= 0 && row < numRows() && col >= 0 && col < numCols()) | |
250 | return d->brush[row*numCols()+col]; | |
251 | return Qt::NoBrush; | |
252 | } | |
253 | ||
254 | ||
255 | ||
256 | /*!\reimp | |
257 | */ | |
258 | ||
259 | void WellArray::focusOutEvent(QFocusEvent*) | |
260 | { | |
261 | updateCell(curRow, curCol); | |
262 | } | |
263 | ||
264 | /*\reimp | |
265 | */ | |
266 | void WellArray::keyPressEvent(QKeyEvent* event) | |
267 | { | |
268 | switch (event->key()) { // Look at the key code | |
269 | case Qt::Key_Left: // If 'left arrow'-key, | |
270 | if (curCol > 0) // and cr't not in leftmost col | |
271 | setCurrent(curRow, curCol - 1); // set cr't to next left column | |
272 | break; | |
273 | case Qt::Key_Right: // Correspondingly... | |
274 | if (curCol < numCols()-1) | |
275 | setCurrent(curRow, curCol + 1); | |
276 | break; | |
277 | case Qt::Key_Up: | |
278 | if (curRow > 0) | |
279 | setCurrent(curRow - 1, curCol); | |
280 | break; | |
281 | case Qt::Key_Down: | |
282 | if (curRow < numRows()-1) | |
283 | setCurrent(curRow + 1, curCol); | |
284 | break; | |
285 | case Qt::Key_Space: | |
286 | setSelected(curRow, curCol); | |
287 | break; | |
288 | default: // If not an interesting key, | |
289 | event->ignore(); // we don't accept the event | |
290 | return; | |
291 | } | |
292 | ||
293 | } | |
294 | ||
295 | } // namespace widgets | |
296 | } // namespace pv |