1 /****************************************************************************
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the demonstration applications of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "mainwindow.h"
43 #include "menumanager.h"
46 #include "demotextitem.h"
47 #include "imageitem.h"
49 #include "demoscene.h"
54 //#define QT_NO_OPENGL
56 MainWindow::MainWindow(QWidget
*parent
) : QGraphicsView(parent
), updateTimer(this)
58 this->currentFps
= Colors::fps
;
62 this->pausedLabel
= 0;
63 this->doneAdapt
= false;
64 this->useTimer
= false;
65 this->updateTimer
.setSingleShot(true);
66 this->companyLogo
= 0;
70 this->setupSceneItems();
71 this->drawBackgroundToPixmap();
74 MainWindow::~MainWindow()
76 delete this->companyLogo
;
80 void MainWindow::setupWidget()
82 QRect screenRect
= QApplication::desktop()->screenGeometry(QApplication::desktop()->primaryScreen());
83 QRect
windowRect(0, 0, 800, 600);
84 if (screenRect
.width() < 800)
85 windowRect
.setWidth(screenRect
.width());
86 if (screenRect
.height() < 600)
87 windowRect
.setHeight(screenRect
.height());
88 windowRect
.moveCenter(screenRect
.center());
89 this->setGeometry(windowRect
);
90 this->setMinimumSize(80, 60);
91 setWindowTitle(tr("Qt Examples and Demos"));
92 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
93 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
94 setFrameStyle(QFrame::NoFrame
);
95 this->setRenderingSystem();
96 connect(&this->updateTimer
, SIGNAL(timeout()), this, SLOT(tick()));
99 void MainWindow::setRenderingSystem()
101 QWidget
*viewport
= 0;
104 if (Colors::openGlRendering
) {
105 QGLWidget
*glw
= new QGLWidget(QGLFormat(QGL::SampleBuffers
));
106 if (Colors::noScreenSync
)
107 glw
->format().setSwapInterval(0);
108 glw
->setAutoFillBackground(false);
110 setCacheMode(QGraphicsView::CacheNone
);
112 qDebug() << "- using OpenGL";
113 } else // software rendering
116 // software rendering
117 viewport
= new QWidget
;
118 setCacheMode(QGraphicsView::CacheBackground
);
120 qDebug() << "- using software rendering";
123 setViewport(viewport
);
126 void MainWindow::start()
128 this->switchTimerOnOff(true);
129 this->demoStartTime
.restart();
130 MenuManager::instance()->itemSelected(MenuManager::ROOT
, Colors::rootMenuName
);
132 qDebug("- starting demo");
135 void MainWindow::enableMask(bool enable
)
137 if (!enable
|| Colors::noWindowMask
)
163 this->setMask(QRegion(region
));
167 void MainWindow::setupScene()
169 this->scene
= new DemoScene(this);
170 this->scene
->setSceneRect(0, 0, 800, 600);
171 setScene(this->scene
);
172 this->scene
->setItemIndexMethod(QGraphicsScene::NoIndex
);
175 void MainWindow::drawItems(QPainter
*painter
, int numItems
, QGraphicsItem
**items
, const QStyleOptionGraphicsItem
* options
)
177 QGraphicsView::drawItems(painter
, numItems
, items
, options
);
180 void MainWindow::switchTimerOnOff(bool on
)
182 bool ticker
= MenuManager::instance()->ticker
&& MenuManager::instance()->ticker
->scene();
184 MenuManager::instance()->ticker
->tickOnPaint
= !on
|| Colors::noTimerUpdate
;
186 if (on
&& !Colors::noTimerUpdate
){
187 this->useTimer
= true;
188 this->setViewportUpdateMode(QGraphicsView::NoViewportUpdate
);
189 this->fpsTime
= QTime::currentTime();
190 this->updateTimer
.start(int(1000 / Colors::fps
));
193 this->useTimer
= false;
194 this->updateTimer
.stop();
195 if (Colors::softwareRendering
)
196 if (Colors::noTicker
)
197 this->setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate
);
199 this->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate
);
201 this->setViewportUpdateMode(QGraphicsView::FullViewportUpdate
);
205 bool MainWindow::measureFps()
207 // Calculate time diff:
208 float t
= this->fpsTime
.msecsTo(QTime::currentTime());
211 this->currentFps
= (1000.0f
/ t
);
212 this->fpsHistory
+= this->currentFps
;
213 this->fpsTime
= QTime::currentTime();
216 int size
= this->fpsHistory
.size();
218 qSort(this->fpsHistory
.begin(), this->fpsHistory
.end());
219 this->fpsMedian
= this->fpsHistory
.at(int(size
/2));
220 if (this->fpsMedian
== 0)
221 this->fpsMedian
= 0.01f
;
222 this->fpsHistory
.clear();
229 Used for adaption in case things are so slow
230 that no median yet has been calculated
232 void MainWindow::forceFpsMedianCalculation()
234 if (this->fpsMedian
!= -1)
237 int size
= this->fpsHistory
.size();
239 this->fpsMedian
= 0.01f
;
243 qSort(this->fpsHistory
.begin(), this->fpsHistory
.end());
244 this->fpsMedian
= this->fpsHistory
.at(int(size
/2));
245 if (this->fpsMedian
== 0)
246 this->fpsMedian
= 0.01f
;
249 void MainWindow::tick()
251 bool medianChanged
= this->measureFps();
254 if (medianChanged
&& this->fpsLabel
&& Colors::showFps
)
255 this->fpsLabel
->setText(QString("FPS: ") + QString::number(int(this->currentFps
)));
257 if (MenuManager::instance()->ticker
)
258 MenuManager::instance()->ticker
->tick();
260 this->viewport()->update();
262 this->updateTimer
.start(int(1000 / Colors::fps
));
265 void MainWindow::setupSceneItems()
267 if (Colors::showFps
){
268 this->fpsLabel
= new DemoTextItem(QString("FPS: --"), Colors::buttonFont(), Qt::white
, -1, this->scene
, 0, DemoTextItem::DYNAMIC_TEXT
);
269 this->fpsLabel
->setZValue(100);
270 this->fpsLabel
->setPos(Colors::stageStartX
, 600 - QFontMetricsF(Colors::buttonFont()).height() - 5);
273 this->companyLogo
= new ImageItem(QImage(":/images/trolltech-logo.png"), 1000, 1000, this->scene
, 0, true, 0.5f
);
274 this->qtLogo
= new ImageItem(QImage(":/images/qtlogo_small.png"), 1000, 1000, this->scene
, 0, true, 0.5f
);
275 this->companyLogo
->setZValue(100);
276 this->qtLogo
->setZValue(100);
277 this->pausedLabel
= new DemoTextItem(QString("PAUSED"), Colors::buttonFont(), Qt::white
, -1, this->scene
, 0);
278 this->pausedLabel
->setZValue(100);
279 QFontMetricsF
fm(Colors::buttonFont());
280 this->pausedLabel
->setPos(Colors::stageWidth
- fm
.width("PAUSED"), 590 - fm
.height());
281 this->pausedLabel
->setRecursiveVisible(false);
284 void MainWindow::checkAdapt()
287 || Colors::noTimerUpdate
288 || this->demoStartTime
.elapsed() < 2000)
291 this->doneAdapt
= true;
292 this->forceFpsMedianCalculation();
293 Colors::benchmarkFps
= this->fpsMedian
;
295 qDebug() << "- benchmark:" << QString::number(Colors::benchmarkFps
) << "FPS";
300 if (this->fpsMedian
< 30){
301 if (MenuManager::instance()->ticker
&& MenuManager::instance()->ticker
->scene()){
302 this->scene
->removeItem(MenuManager::instance()->ticker
);
303 Colors::noTimerUpdate
= true;
304 this->switchTimerOnOff(false);
306 this->fpsLabel
->setText(QString("FPS: (") + QString::number(this->fpsMedian
) + QString(")"));
308 qDebug() << "- benchmark adaption: removed ticker (fps < 30)";
311 if (this->fpsMedian
< 20){
312 Colors::noAnimations
= true;
314 qDebug() << "- benchmark adaption: animations switched off (fps < 20)";
317 Colors::adapted
= true;
321 int MainWindow::performBenchmark()
326 while (time.elapsed() < 2000)
327 QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
332 void MainWindow::drawBackgroundToPixmap()
334 const QRectF r
= this->scene
->sceneRect();
335 this->background
= QPixmap(qRound(r
.width()), qRound(r
.height()));
336 this->background
.fill(Qt::black
);
337 QPainter
painter(&this->background
);
339 if (false && Colors::useEightBitPalette
){
340 painter
.fillRect(r
, Colors::sceneBg1
);
342 QImage
bg(":/images/demobg.png");
343 painter
.drawImage(0, 0, bg
);
347 void MainWindow::drawBackground(QPainter
*painter
, const QRectF
&rect
)
350 painter
->drawPixmap(QPoint(0, 0), this->background
);
353 void MainWindow::showEvent(QShowEvent
* event
)
356 QGraphicsView::showEvent(event
);
359 void MainWindow::toggleFullscreen()
361 if (this->isFullScreen()){
362 this->enableMask(true);
364 if (MenuManager::instance()->ticker
)
365 MenuManager::instance()->ticker
->pause(false);
368 this->enableMask(false);
369 this->showFullScreen();
373 void MainWindow::keyPressEvent(QKeyEvent
*event
)
375 if (event
->key() == Qt::Key_Escape
){
377 QApplication::quit();
379 else if (event
->key() == Qt::Key_1
){
381 s
+= "Rendering system: ";
382 if (Colors::openGlRendering
)
388 s
+= Colors::noAdapt
? "off" : "on";
389 s
+= "\nAdaption occured: ";
390 s
+= Colors::adapted
? "yes" : "no";
391 s
+= "\nOpenGL version: ";
392 s
+= Colors::glVersion
;
394 s
+= "\nColor bit depth: ";
395 s
+= QString::number(w
.depth());
396 s
+= "\nWanted FPS: ";
397 s
+= QString::number(Colors::fps
);
398 s
+= "\nBenchmarked FPS: ";
399 s
+= Colors::benchmarkFps
!= -1 ? QString::number(Colors::benchmarkFps
) : "not calculated";
400 s
+= "\nAnimations: ";
401 s
+= Colors::noAnimations
? "off" : "on";
403 s
+= Colors::useEightBitPalette
? "off" : "on";
405 s
+= Colors::noTicker
? "off" : "on";
407 s
+= Colors::usePixmaps
? "on" : "off";
408 s
+= "\nRescale images on resize: ";
409 s
+= Colors::noRescale
? "off" : "on";
410 s
+= "\nTimer based updates: ";
411 s
+= Colors::noTimerUpdate
? "off" : "on";
412 s
+= "\nSeparate loop: ";
413 s
+= Colors::useLoop
? "yes" : "no";
414 s
+= "\nScreen sync: ";
415 s
+= Colors::noScreenSync
? "no" : "yes";
416 QMessageBox::information(0, QString("Current configuration"), s
);
420 void MainWindow::focusInEvent(QFocusEvent
*)
425 if (MenuManager::instance()->ticker
)
426 MenuManager::instance()->ticker
->pause(false);
428 int code
= MenuManager::instance()->currentMenuCode
;
429 if (code
== MenuManager::ROOT
|| code
== MenuManager::MENU1
)
430 this->switchTimerOnOff(true);
432 this->pausedLabel
->setRecursiveVisible(false);
435 void MainWindow::focusOutEvent(QFocusEvent
*)
440 if (MenuManager::instance()->ticker
)
441 MenuManager::instance()->ticker
->pause(true);
443 int code
= MenuManager::instance()->currentMenuCode
;
444 if (code
== MenuManager::ROOT
|| code
== MenuManager::MENU1
)
445 this->switchTimerOnOff(false);
447 this->pausedLabel
->setRecursiveVisible(true);
450 void MainWindow::resizeEvent(QResizeEvent
*event
)
455 this->scale(event
->size().width() / 800.0, event
->size().height() / 600.0);
456 QGraphicsView::resizeEvent(event
);
457 DemoItem::setMatrix(this->matrix());
459 if (this->companyLogo
){
460 const QRectF r
= this->scene
->sceneRect();
461 QRectF ttb
= this->companyLogo
->boundingRect();
462 this->companyLogo
->setPos(int((r
.width() - ttb
.width()) / 2), 595 - ttb
.height());
463 QRectF qtb
= this->qtLogo
->boundingRect();
464 this->qtLogo
->setPos(802 - qtb
.width(), 0);
467 // Changing size will almost always
468 // hurt FPS during the changing. So
470 this->fpsHistory
.clear();