1 #include "mainwindow.h"
2 #include "ui_mainwindow.h"
3 #include "jigsawpuzzleboard.h"
4 #include "jigsawpuzzleitem.h"
8 #if defined(Q_WS_MAEMO_5)
10 #include <hildon-extras-1/hildon-extras/qt-he-wrapper.h>
13 #if defined(HAVE_OPENGL)
17 #if defined(Q_OS_SYMBIAN)
24 MainWindow::MainWindow(QWidget *parent) :
26 ui(new Ui::MainWindow),
27 timer(new QTimer(this)),
28 settings(new SettingsDialog(this)),
29 newgame(new NewGameDialog(this)),
30 highscores(new HighScoresDialog(this)),
31 board(new JigsawPuzzleBoard(this)),
41 ui->actionPause->setVisible(false);
42 ui->btnSurrender->hide();
43 ui->actionSurrender->setVisible(false);
47 timer->setInterval(1000);
48 connect(timer, SIGNAL(timeout()), this, SLOT(updateElapsedTimeLabel()));
49 ui->graphicsView->setResizeAnchor(QGraphicsView::AnchorViewCenter);
52 QColor bg = SettingsDialog::boardBackground();
53 board->setBackgroundBrush(QBrush(bg));
54 intro = new QGraphicsTextItem(tr("Please press the new game button!"));
55 intro->setDefaultTextColor(QColor(0xFFFFFF - bg.rgb()));
56 board->addItem(intro);
58 ui->graphicsView->setScene(board);
59 #if defined(HAVE_OPENGL)
60 ui->graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::DoubleBuffer), this));
64 ui->graphicsView->setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing);
65 ui->graphicsView->setOptimizationFlag(QGraphicsView::DontSavePainterState);
66 ui->graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
69 ui->horizontalLayout->setContentsMargins(10, 0, 10, 0);
72 #if defined(Q_WS_MAEMO_5)
74 setAttribute(Qt::WA_Maemo5AutoOrientation);
75 ui->btnFullscreen->setIcon(QIcon::fromTheme("general_fullsize"));
78 #if defined(Q_OS_SYMBIAN)
79 ui->btnFullscreen->hide();
85 MainWindow::~MainWindow()
90 void MainWindow::closeEvent(QCloseEvent *event)
92 if (QMessageBox::Yes == QMessageBox::question(this, tr("Are you sure?"), tr("Do you want to exit the game?"), QMessageBox::Yes, QMessageBox::No))
95 QApplication::instance()->quit();
100 bool MainWindow::event(QEvent *event)
102 bool result = QMainWindow::event(event);
103 if (_canPause && _isPlaying && !_wasPaused && _isPaused && event->type() == QEvent::WindowActivate)
107 else if (_canPause && _isPlaying && event->type() == QEvent::WindowDeactivate)
109 // If the game was paused before deactivating, it will be paused after activating.
110 _wasPaused = _isPaused;
116 void MainWindow::resizeEvent(QResizeEvent *event)
119 QMainWindow::resizeEvent(event);
121 #if defined(MOBILE) && !defined(Q_OS_SYMBIAN)
124 ui->horizontalLayout->removeWidget(ui->btnFullscreen);
125 ui->btnFullscreen->move(width() - ui->btnFullscreen->width(), height() - ui->btnFullscreen->height());
126 ui->btnFullscreen->show();
130 #if defined(Q_OS_SYMBIAN)
131 if (height() > width())
133 ui->verticalLayout->insertWidget(0, ui->lblTime);
134 ui->btnAbout->hide();
138 ui->horizontalLayout->insertWidget(0, ui->lblTime);
139 ui->btnAbout->show();
146 // Scaling the graphics view's content
148 QSizeF oldscenesize = board->sceneRect().size();
150 if (SettingsDialog::enableScaling())
152 // Calculating scale ratio
153 qreal oldScaleRatio = _currentScaleRatio;
154 QSize scaledPixmapSize = board->originalPixmapSize();
155 scaledPixmapSize.scale(ui->graphicsView->size(), Qt::KeepAspectRatio);
156 _currentScaleRatio = min<qreal>((qreal)scaledPixmapSize.width() / (qreal)board->originalPixmapSize().width(),
157 (qreal)scaledPixmapSize.height() / (qreal)board->originalPixmapSize().height());
159 //qDebug() << "new size" << ui->graphicsView->size() << "ratio" << _currentScaleRatio;
161 // Setting scene rect and scale
162 board->setSceneRect(0, 0, ui->graphicsView->width() / _currentScaleRatio, ui->graphicsView->height() / _currentScaleRatio);
163 if (0.98 < _currentScaleRatio && 1.02 > _currentScaleRatio)
164 ui->graphicsView->resetTransform();
166 ui->graphicsView->scale(_currentScaleRatio / oldScaleRatio, _currentScaleRatio / oldScaleRatio);
170 ui->graphicsView->resetTransform();
171 board->setSceneRect(0, 0, ui->graphicsView->width(), ui->graphicsView->height());
174 // Making sure every piece is visible and has a nice position
175 QSizeF p = (board->sceneRect().size() - oldscenesize) / 2;
176 foreach (QGraphicsItem *item, board->items())
178 QPointF newPos(item->pos().x() + p.width(),
179 item->pos().y() + p.height());
180 item->setPos(newPos);
181 if (JigsawPuzzleItem *jpi = dynamic_cast<JigsawPuzzleItem*>(item))
184 jpi->verifyPosition();
190 //qDebug() << "current scale ratio is" << _currentScaleRatio;
193 void MainWindow::showHighScores()
198 void MainWindow::newGame()
202 if (!QDialog::Accepted == newgame->exec())
205 int rows = SettingsDialog::rows(), cols = SettingsDialog::columns();
209 if ((SettingsDialog::startInFullscreen() && !isFullScreen()))// || !SettingsDialog::startInFullscreen() && isFullScreen())
212 applyViewportSettings();
215 if (pixmap.load(newgame->getPictureFile()) && !pixmap.isNull())
217 ui->btnOpenImage->hide();
218 ui->actionNew_game->setVisible(false);
221 ui->btnSurrender->show();
222 ui->actionSurrender->setVisible(true);
225 if (SettingsDialog::useAccelerometer())
226 fixCurrentOrientation();
229 QProgressDialog *progress = new QProgressDialog(tr("Generating puzzle..."), tr("Cancel"), 0, rows * cols, this);
230 progress->setWindowTitle(tr("Generating puzzle..."));
232 if (rows * cols < 20)
241 board->deleteLater();
244 ui->graphicsView->resetTransform();
245 board = new JigsawPuzzleBoard(ui->graphicsView);
246 board->setBackgroundBrush(QBrush(SettingsDialog::boardBackground()));
247 board->setSceneRect(0, 0, ui->graphicsView->width(), ui->graphicsView->height());
248 ui->graphicsView->setScene(board);
250 connect(board, SIGNAL(loadProgressChanged(int)), progress, SLOT(setValue(int)));
251 connect(board, SIGNAL(gameStarted()), progress, SLOT(deleteLater()));
252 connect(board, SIGNAL(gameStarted()), this, SLOT(initializeGame()));
253 connect(board, SIGNAL(gameWon()), this, SLOT(onWon()));
254 connect(board, SIGNAL(gameEnded()), this, SLOT(endGame()));
256 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
257 if (SettingsDialog::useDropShadow())
258 connect(board, SIGNAL(loaded()), board, SLOT(enableDropshadow()));
261 board->startGame(pixmap, rows, cols);
262 _currentScaleRatio = board->originalScaleRatio();
263 ui->graphicsView->scale(_currentScaleRatio, _currentScaleRatio);
267 QMessageBox::warning(this, tr("Error"), tr("Could not load the selected image."));
273 void MainWindow::surrender()
275 if (_isPlaying && QMessageBox::Yes == QMessageBox::question(this, tr("Are you sure?"), tr("Are you sure you want to abandon this game?"), QMessageBox::Yes, QMessageBox::Cancel))
281 board->surrenderGame();
285 void MainWindow::applyViewportSettings()
287 #if defined(HAVE_OPENGL)
288 if (SettingsDialog::useOpenGl() && !ui->graphicsView->viewport()->inherits("QGLWidget"))
290 ui->graphicsView->viewport()->deleteLater();
291 ui->graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::DoubleBuffer), this));
293 else if (!SettingsDialog::useOpenGl() && ui->graphicsView->viewport()->inherits("QGLWidget"))
295 ui->graphicsView->viewport()->deleteLater();
296 ui->graphicsView->setViewport(new QWidget(this));
301 void MainWindow::onWon()
305 // Showing congratulations
306 #if defined(Q_WS_MAEMO_5)
307 QMaemo5InformationBox::information(0, "<b>" + tr("You rock!") + "</b><br />" + tr("Congratulations!") + "<br />" + tr("You've successfully solved the given puzzle!"), 5000);
309 QMessageBox::information(this, tr("You rock!"), tr("Congratulations!") + "\n" + tr("You've successfully solved the given puzzle!"));
312 // Adding to high scores
313 highscores->addResult(QString::number(SettingsDialog::columns()) + QString::fromUtf8("×") + QString::number(SettingsDialog::rows()),
314 QDateTime::currentDateTime().toString(Qt::SystemLocaleLongDate) + " - " + QString::number(_secsElapsed) + " seconds");
317 void MainWindow::initializeGame()
320 updateElapsedTimeLabel();
323 // This is to set the correct icon on the button and to start the timer
326 #if defined (MOBILE) && !defined(Q_OS_SYMBIAN)
329 ui->btnPause->show();
330 ui->btnSurrender->show();
331 ui->actionPause->setVisible(true);
334 ui->btnPause->show();
335 ui->btnSurrender->show();
336 ui->actionPause->setVisible(true);
340 if (JigsawPuzzleBoard *jpb = qobject_cast<JigsawPuzzleBoard*>(board))
341 jpb->setTolerance(SettingsDialog::tolerance());
344 void MainWindow::endGame()
350 #if defined(MOBILE) && !defined(Q_OS_SYMBIAN)
354 ui->btnOpenImage->show();
356 ui->btnPause->hide();
358 ui->actionNew_game->setVisible(true);
359 ui->btnSurrender->hide();
360 ui->actionSurrender->setVisible(false);
361 ui->btnPause->hide();
362 ui->actionPause->setVisible(false);
364 if (SettingsDialog::useAccelerometer())
366 board->disableAccelerometer();
367 unfixCurrentOrientation();
371 void MainWindow::showSettings()
376 QColor bg = SettingsDialog::boardBackground();
377 if (board->backgroundBrush().color() != bg)
379 board->setBackgroundBrush(QBrush(bg));
381 intro->setDefaultTextColor(QColor(0xFFFFFF - bg.rgb()));
386 if (JigsawPuzzleBoard *jpb = qobject_cast<JigsawPuzzleBoard*>(board))
387 jpb->setTolerance(SettingsDialog::tolerance());
389 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
391 if (SettingsDialog::useDropShadow() && !board->isDropshadowActive() && intro.isNull())
392 board->enableDropshadow();
393 else if (!SettingsDialog::useDropShadow() && board->isDropshadowActive())
394 board->disableDropshadow();
397 if (_isPlaying && SettingsDialog::useAccelerometer())
399 board->enableAccelerometer();
400 fixCurrentOrientation();
404 board->disableAccelerometer();
405 unfixCurrentOrientation();
409 applyViewportSettings();
412 void MainWindow::about()
414 #if defined(Q_WS_MAEMO_5)
415 QtHeWrapper::showHeAboutDialog(this,
416 tr("Fun and addictive jigsaw puzzle game"),
417 tr("Licensed under the terms of EUPL 1.1 - 2011, Timur Kristóf"),
418 "http://gitorious.org/colorful-apps/pages/PuzzleMaster",
419 "http://talk.maemo.org/showthread.php?t=67139",
420 "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=venemo%40msn%2ecom&lc=US&item_name=to%20Timur%20Kristof%2c%20for%20Puzzle%20Master%20development¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted",
423 QMessageBox::information(this, tr("About"), fetchAboutString(), QMessageBox::Ok);
427 void MainWindow::updateElapsedTimeLabel()
435 str = tr("Game paused!");
436 else if (_secsElapsed == 1)
437 str = tr("Elapsed %1 second").arg(QString::number(_secsElapsed));
439 str = tr("Elapsed %1 seconds").arg(QString::number(_secsElapsed));
444 ui->lblTime->setText(str);
447 void MainWindow::toggleFullscreen()
449 #if defined(Q_OS_SYMBIAN)
456 ui->horizontalLayout->addWidget(ui->btnFullscreen);
457 ui->btnAbout->show();
458 ui->btnFullscreen->show();
459 //ui->btnHelp->show();
461 ui->btnOpenImage->show();
462 ui->btnPause->show();
463 ui->btnSettings->show();
465 ui->btnSurrender->show();
475 ui->btnAbout->hide();
476 ui->btnFullscreen->hide();
477 //ui->btnHelp->hide();
478 ui->btnOpenImage->hide();
479 ui->btnPause->hide();
480 ui->btnSettings->hide();
481 ui->btnSurrender->hide();
487 // This is what it takes to fully update the appearance
488 QApplication *app = (QApplication*) QApplication::instance();
489 app->processEvents();
491 app->processEvents();
493 app->processEvents();
497 void MainWindow::pause()
499 //qDebug() << "game paused";
503 ui->btnPause->setIcon(QIcon(QPixmap(":/unpause.png")));
504 ui->actionPause->setText(tr("Resume"));
506 // Stopping accelerometer
507 if (SettingsDialog::useAccelerometer())
508 board->disableAccelerometer();
511 void MainWindow::unpause()
513 //qDebug() << "game resumed";
517 ui->btnPause->setIcon(QIcon(QPixmap(":/pause.png")));
518 ui->actionPause->setText(tr("Pause"));
520 // Starting accelerometer
521 if (SettingsDialog::useAccelerometer())
522 board->enableAccelerometer();
525 void MainWindow::togglePause()
532 #if defined(Q_WS_MAEMO_5)
533 QMaemo5InformationBox::information(this, "<b>" + tr("Game paused!") + "</b><br />" + tr("You now can't move the pieces."), 2000);
534 #elif defined (MOBILE)
535 QMessageBox::information(this, tr("Game paused!"), tr("You now can't move the pieces."), QMessageBox::Ok);
537 updateElapsedTimeLabel();
541 #if defined(Q_WS_MAEMO_5)
542 QMaemo5InformationBox::information(this, "<b>" + tr("Game resumed!") + "</b><br />" + tr("Now you can move the pieces again."), 2000);
543 #elif defined (MOBILE)
544 QMessageBox::information(this, tr("Game resumed!"), tr("Now you can move the pieces again."), QMessageBox::Ok);
546 updateElapsedTimeLabel();
552 void MainWindow::fixCurrentOrientation()
554 #if defined(Q_WS_MAEMO_5)
555 if (width() > height())
556 setAttribute(Qt::WA_Maemo5LandscapeOrientation);
558 setAttribute(Qt::WA_Maemo5PortraitOrientation);
559 #elif defined(Q_OS_SYMBIAN)
560 CAknAppUi* appUi = dynamic_cast<CAknAppUi*> (CEikonEnv::Static()->AppUi());
561 if (width() > height())
562 appUi->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape);
564 appUi->SetOrientationL(CAknAppUi::EAppUiOrientationPortrait);
568 void MainWindow::unfixCurrentOrientation()
570 #if defined(Q_WS_MAEMO_5)
571 setAttribute(Qt::WA_Maemo5AutoOrientation);
572 #elif defined(Q_OS_SYMBIAN)
573 CAknAppUi* appUi = dynamic_cast<CAknAppUi*> (CEikonEnv::Static()->AppUi());
574 appUi->SetOrientationL(CAknAppUi::EAppUiOrientationAutomatic);
578 void MainWindow::exitTriggered()