source: trunk/demos/boxes/qtbox.cpp@ 372

Last change on this file since 372 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 14.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the demonstration applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qtbox.h"
43
44const qreal ROTATE_SPEED_X = 30.0 / 1000.0;
45const qreal ROTATE_SPEED_Y = 20.0 / 1000.0;
46const qreal ROTATE_SPEED_Z = 40.0 / 1000.0;
47const int MAX_ITEM_SIZE = 512;
48const int MIN_ITEM_SIZE = 16;
49
50//============================================================================//
51// ItemBase //
52//============================================================================//
53
54ItemBase::ItemBase(int size, int x, int y) : m_size(size), m_isResizing(false)
55{
56 setFlag(QGraphicsItem::ItemIsMovable, true);
57 setFlag(QGraphicsItem::ItemIsSelectable, true);
58 setFlag(QGraphicsItem::ItemIsFocusable, true);
59 setAcceptHoverEvents(true);
60 setPos(x, y);
61 m_startTime = QTime::currentTime();
62}
63
64ItemBase::~ItemBase()
65{
66}
67
68QRectF ItemBase::boundingRect() const
69{
70 return QRectF(-m_size / 2, -m_size / 2, m_size, m_size);
71}
72
73void ItemBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
74{
75 if (option->state & QStyle::State_Selected) {
76 painter->setRenderHint(QPainter::Antialiasing, true);
77 if (option->state & QStyle::State_HasFocus)
78 painter->setPen(Qt::yellow);
79 else
80 painter->setPen(Qt::white);
81 painter->drawRect(boundingRect());
82
83 painter->drawLine(m_size / 2 - 9, m_size / 2, m_size / 2, m_size / 2 - 9);
84 painter->drawLine(m_size / 2 - 6, m_size / 2, m_size / 2, m_size / 2 - 6);
85 painter->drawLine(m_size / 2 - 3, m_size / 2, m_size / 2, m_size / 2 - 3);
86
87 painter->setRenderHint(QPainter::Antialiasing, false);
88 }
89}
90
91void ItemBase::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
92{
93 if (!isSelected() && scene()) {
94 scene()->clearSelection();
95 setSelected(true);
96 }
97
98 QMenu menu;
99 QAction *delAction = menu.addAction("Delete");
100 QAction *newAction = menu.addAction("New");
101 QAction *growAction = menu.addAction("Grow");
102 QAction *shrinkAction = menu.addAction("Shrink");
103
104 QAction *selectedAction = menu.exec(event->screenPos());
105
106 if (selectedAction == delAction)
107 deleteSelectedItems(scene());
108 else if (selectedAction == newAction)
109 duplicateSelectedItems(scene());
110 else if (selectedAction == growAction)
111 growSelectedItems(scene());
112 else if (selectedAction == shrinkAction)
113 shrinkSelectedItems(scene());
114}
115
116void ItemBase::duplicateSelectedItems(QGraphicsScene *scene)
117{
118 if (!scene)
119 return;
120
121 QList<QGraphicsItem *> selected;
122 selected = scene->selectedItems();
123
124 foreach (QGraphicsItem *item, selected) {
125 ItemBase *itemBase = dynamic_cast<ItemBase *>(item);
126 if (itemBase)
127 scene->addItem(itemBase->createNew(itemBase->m_size, itemBase->pos().x() + itemBase->m_size, itemBase->pos().y()));
128 }
129}
130
131void ItemBase::deleteSelectedItems(QGraphicsScene *scene)
132{
133 if (!scene)
134 return;
135
136 QList<QGraphicsItem *> selected;
137 selected = scene->selectedItems();
138
139 foreach (QGraphicsItem *item, selected) {
140 ItemBase *itemBase = dynamic_cast<ItemBase *>(item);
141 if (itemBase)
142 delete itemBase;
143 }
144}
145
146void ItemBase::growSelectedItems(QGraphicsScene *scene)
147{
148 if (!scene)
149 return;
150
151 QList<QGraphicsItem *> selected;
152 selected = scene->selectedItems();
153
154 foreach (QGraphicsItem *item, selected) {
155 ItemBase *itemBase = dynamic_cast<ItemBase *>(item);
156 if (itemBase) {
157 itemBase->prepareGeometryChange();
158 itemBase->m_size *= 2;
159 if (itemBase->m_size > MAX_ITEM_SIZE)
160 itemBase->m_size = MAX_ITEM_SIZE;
161 }
162 }
163}
164
165void ItemBase::shrinkSelectedItems(QGraphicsScene *scene)
166{
167 if (!scene)
168 return;
169
170 QList<QGraphicsItem *> selected;
171 selected = scene->selectedItems();
172
173 foreach (QGraphicsItem *item, selected) {
174 ItemBase *itemBase = dynamic_cast<ItemBase *>(item);
175 if (itemBase) {
176 itemBase->prepareGeometryChange();
177 itemBase->m_size /= 2;
178 if (itemBase->m_size < MIN_ITEM_SIZE)
179 itemBase->m_size = MIN_ITEM_SIZE;
180 }
181 }
182}
183
184void ItemBase::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
185{
186 if (m_isResizing) {
187 int dx = int(2.0 * event->pos().x());
188 int dy = int(2.0 * event->pos().y());
189 prepareGeometryChange();
190 m_size = (dx > dy ? dx : dy);
191 if (m_size < MIN_ITEM_SIZE)
192 m_size = MIN_ITEM_SIZE;
193 else if (m_size > MAX_ITEM_SIZE)
194 m_size = MAX_ITEM_SIZE;
195 } else {
196 QGraphicsItem::mouseMoveEvent(event);
197 }
198}
199
200void ItemBase::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
201{
202 if (m_isResizing || (isInResizeArea(event->pos()) && isSelected()))
203 setCursor(Qt::SizeFDiagCursor);
204 else
205 setCursor(Qt::ArrowCursor);
206 QGraphicsItem::hoverMoveEvent(event);
207}
208
209void ItemBase::mousePressEvent(QGraphicsSceneMouseEvent *event)
210{
211 static qreal z = 0.0;
212 setZValue(z += 1.0);
213 if (event->button() == Qt::LeftButton && isInResizeArea(event->pos())) {
214 m_isResizing = true;
215 } else {
216 QGraphicsItem::mousePressEvent(event);
217 }
218}
219
220void ItemBase::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
221{
222 if (event->button() == Qt::LeftButton && m_isResizing) {
223 m_isResizing = false;
224 } else {
225 QGraphicsItem::mouseReleaseEvent(event);
226 }
227}
228
229void ItemBase::keyPressEvent(QKeyEvent *event)
230{
231 switch (event->key()) {
232 case Qt::Key_Delete:
233 deleteSelectedItems(scene());
234 break;
235 case Qt::Key_Insert:
236 duplicateSelectedItems(scene());
237 break;
238 case Qt::Key_Plus:
239 growSelectedItems(scene());
240 break;
241 case Qt::Key_Minus:
242 shrinkSelectedItems(scene());
243 break;
244 default:
245 QGraphicsItem::keyPressEvent(event);
246 break;
247 }
248}
249
250void ItemBase::wheelEvent(QGraphicsSceneWheelEvent *event)
251{
252 prepareGeometryChange();
253 m_size = int(m_size * exp(-event->delta() / 600.0));
254 if (m_size > MAX_ITEM_SIZE)
255 m_size = MAX_ITEM_SIZE;
256 else if (m_size < MIN_ITEM_SIZE)
257 m_size = MIN_ITEM_SIZE;
258}
259
260bool ItemBase::isInResizeArea(const QPointF &pos)
261{
262 return (-pos.y() < pos.x() - m_size + 9);
263}
264
265//============================================================================//
266// QtBox //
267//============================================================================//
268
269QtBox::QtBox(int size, int x, int y) : ItemBase(size, x, y), m_texture(0)
270{
271 for (int i = 0; i < 8; ++i) {
272 m_vertices[i][0] = (i & 1 ? 0.5f : -0.5f);
273 m_vertices[i][1] = (i & 2 ? 0.5f : -0.5f);
274 m_vertices[i][2] = (i & 4 ? 0.5f : -0.5f);
275 }
276 for (int i = 0; i < 4; ++i) {
277 m_texCoords[i][0] = (i & 1 ? 1.0f : 0.0f);
278 m_texCoords[i][1] = (i & 2 ? 1.0f : 0.0f);
279 }
280 memset(m_normals, 0, sizeof(m_normals));
281 for (int i = 0; i < 3; ++i) {
282 m_normals[2 * i + 0][i] = -1.0f;
283 m_normals[2 * i + 1][i] = 1.0f;
284 }
285}
286
287QtBox::~QtBox()
288{
289 if (m_texture)
290 delete m_texture;
291}
292
293ItemBase *QtBox::createNew(int size, int x, int y)
294{
295 return new QtBox(size, x, y);
296}
297
298void QtBox::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
299{
300 QRectF rect = boundingRect().translated(pos());
301 float width = float(painter->device()->width());
302 float height = float(painter->device()->height());
303
304 float left = 2.0f * float(rect.left()) / width - 1.0f;
305 float right = 2.0f * float(rect.right()) / width - 1.0f;
306 float top = 1.0f - 2.0f * float(rect.top()) / height;
307 float bottom = 1.0f - 2.0f * float(rect.bottom()) / height;
308 float moveToRectMatrix[] = {
309 0.5f * (right - left), 0.0f, 0.0f, 0.0f,
310 0.0f, 0.5f * (bottom - top), 0.0f, 0.0f,
311 0.0f, 0.0f, 1.0f, 0.0f,
312 0.5f * (right + left), 0.5f * (bottom + top), 0.0f, 1.0f
313 };
314
315 glMatrixMode(GL_PROJECTION);
316 glPushMatrix();
317 glLoadMatrixf(moveToRectMatrix);
318 gluPerspective(60.0, 1.0, 0.01, 10.0);
319
320 glMatrixMode(GL_MODELVIEW);
321 glPushMatrix();
322 glLoadIdentity();
323
324 //glEnable(GL_DEPTH_TEST);
325 glEnable(GL_CULL_FACE);
326 glEnable(GL_LIGHTING);
327 glEnable(GL_COLOR_MATERIAL);
328 glEnable(GL_NORMALIZE);
329
330 if(m_texture == 0)
331 m_texture = new GLTexture2D(":/res/boxes/qt-logo.jpg", 64, 64);
332 m_texture->bind();
333 glEnable(GL_TEXTURE_2D);
334
335 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
336 float lightColour[] = {1.0f, 1.0f, 1.0f, 1.0f};
337 float lightDir[] = {0.0f, 0.0f, 1.0f, 0.0f};
338 glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColour);
339 glLightfv(GL_LIGHT0, GL_POSITION, lightDir);
340 glEnable(GL_LIGHT0);
341
342 glTranslatef(0.0f, 0.0f, -1.5f);
343 glRotatef(ROTATE_SPEED_X * m_startTime.msecsTo(QTime::currentTime()), 1.0f, 0.0f, 0.0f);
344 glRotatef(ROTATE_SPEED_Y * m_startTime.msecsTo(QTime::currentTime()), 0.0f, 1.0f, 0.0f);
345 glRotatef(ROTATE_SPEED_Z * m_startTime.msecsTo(QTime::currentTime()), 0.0f, 0.0f, 1.0f);
346 int dt = m_startTime.msecsTo(QTime::currentTime());
347 if (dt < 500)
348 glScalef(dt / 500.0f, dt / 500.0f, dt / 500.0f);
349
350 for (int dir = 0; dir < 3; ++dir) {
351 glColor4f(1.0f, 1.0f, 1.0f, 1.0);
352
353 glBegin(GL_TRIANGLE_STRIP);
354 glNormal3fv(m_normals[2 * dir + 0].bits());
355 for (int i = 0; i < 2; ++i) {
356 for (int j = 0; j < 2; ++j) {
357 glTexCoord2fv(m_texCoords[(j << 1) | i].bits());
358 glVertex3fv(m_vertices[(i << ((dir + 2) % 3)) | (j << ((dir + 1) % 3))].bits());
359 }
360 }
361 glEnd();
362
363 glBegin(GL_TRIANGLE_STRIP);
364 glNormal3fv(m_normals[2 * dir + 1].bits());
365 for (int i = 0; i < 2; ++i) {
366 for (int j = 0; j < 2; ++j) {
367 glTexCoord2fv(m_texCoords[(j << 1) | i].bits());
368 glVertex3fv(m_vertices[(1 << dir) | (i << ((dir + 1) % 3)) | (j << ((dir + 2) % 3))].bits());
369 }
370 }
371 glEnd();
372 }
373 m_texture->unbind();
374
375 //glDisable(GL_DEPTH_TEST);
376 glDisable(GL_CULL_FACE);
377 glDisable(GL_LIGHTING);
378 glDisable(GL_COLOR_MATERIAL);
379 glDisable(GL_TEXTURE_2D);
380 glDisable(GL_LIGHT0);
381 glDisable(GL_NORMALIZE);
382
383 glPopMatrix();
384
385 glMatrixMode(GL_PROJECTION);
386 glPopMatrix();
387
388 ItemBase::paint(painter, option, widget);
389}
390
391//============================================================================//
392// CircleItem //
393//============================================================================//
394
395CircleItem::CircleItem(int size, int x, int y) : ItemBase(size, x, y)
396{
397 m_color = QColor::fromHsv(rand() % 360, 255, 255);
398}
399
400void CircleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
401{
402 int dt = m_startTime.msecsTo(QTime::currentTime());
403
404 qreal r0 = 0.5 * m_size * (1.0 - exp(-0.001 * ((dt + 3800) % 4000)));
405 qreal r1 = 0.5 * m_size * (1.0 - exp(-0.001 * ((dt + 0) % 4000)));
406 qreal r2 = 0.5 * m_size * (1.0 - exp(-0.001 * ((dt + 1800) % 4000)));
407 qreal r3 = 0.5 * m_size * (1.0 - exp(-0.001 * ((dt + 2000) % 4000)));
408
409 if (r0 > r1)
410 r0 = 0.0;
411 if (r2 > r3)
412 r2 = 0.0;
413
414 QPainterPath path;
415 path.moveTo(r1, 0.0);
416 path.arcTo(-r1, -r1, 2 * r1, 2 * r1, 0.0, 360.0);
417 path.lineTo(r0, 0.0);
418 path.arcTo(-r0, -r0, 2 * r0, 2 * r0, 0.0, -360.0);
419 path.closeSubpath();
420 path.moveTo(r3, 0.0);
421 path.arcTo(-r3, -r3, 2 * r3, 2 * r3, 0.0, 360.0);
422 path.lineTo(r0, 0.0);
423 path.arcTo(-r2, -r2, 2 * r2, 2 * r2, 0.0, -360.0);
424 path.closeSubpath();
425 painter->setRenderHint(QPainter::Antialiasing, true);
426 painter->setBrush(QBrush(m_color));
427 painter->setPen(Qt::NoPen);
428 painter->drawPath(path);
429 painter->setBrush(Qt::NoBrush);
430 painter->setPen(Qt::SolidLine);
431 painter->setRenderHint(QPainter::Antialiasing, false);
432
433 ItemBase::paint(painter, option, widget);
434}
435
436ItemBase *CircleItem::createNew(int size, int x, int y)
437{
438 return new CircleItem(size, x, y);
439}
440
441//============================================================================//
442// SquareItem //
443//============================================================================//
444
445SquareItem::SquareItem(int size, int x, int y) : ItemBase(size, x, y)
446{
447 m_image = QPixmap(":/res/boxes/square.jpg");
448}
449
450void SquareItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
451{
452 int dt = m_startTime.msecsTo(QTime::currentTime());
453 QTransform oldTransform = painter->worldTransform();
454 int dtMod = dt % 2000;
455 qreal amp = 0.002 * (dtMod < 1000 ? dtMod : 2000 - dtMod) - 1.0;
456
457 qreal scale = 0.6 + 0.2 * amp * amp;
458 painter->setWorldTransform(QTransform().rotate(15.0 * amp).scale(scale, scale), true);
459
460 painter->drawPixmap(-m_size / 2, -m_size / 2, m_size, m_size, m_image);
461
462 painter->setWorldTransform(oldTransform, false);
463 ItemBase::paint(painter, option, widget);
464}
465
466ItemBase *SquareItem::createNew(int size, int x, int y)
467{
468 return new SquareItem(size, x, y);
469}
Note: See TracBrowser for help on using the repository browser.