From 3d0c7311ebed17f81381b264e767374a9e5d0ab4 Mon Sep 17 00:00:00 2001 From: timoph Date: Sat, 27 Mar 2010 13:02:59 +0000 Subject: [PATCH] Save and restore git-svn-id: file:///svnroot/impuzzle/trunk@16 e6bec12f-0854-4cc4-ad26-6875f1509f77 --- debian/changelog | 4 +- debian/control | 89 +-------------------- debian/rules | 2 +- src/defines.h | 3 + src/gameview.cpp | 205 ++++++++++++++++++++++++++++++++++++++++++++++-- src/gameview.h | 7 +- src/mainwindow.cpp | 4 + src/mainwindow.h | 1 + src/puzzleitem.cpp | 5 ++ src/puzzleitem.h | 1 + src/settings.cpp | 11 +++ src/settings.h | 4 + src/settingsdialog.cpp | 6 +- 13 files changed, 247 insertions(+), 95 deletions(-) diff --git a/debian/changelog b/debian/changelog index 602490d..326c3b2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,9 @@ impuzzle (0.3-2maemo1) unstable; urgency=low - * Added application icon * Added bug tracking link to control + * Dependency changes required by pr1.2 autobuilder - -- Timo Härkönen Tue, 09 Mar 2010 19:09:13 +0200 + -- Timo Härkönen Wed, 24 Mar 2010 17:51:13 +0200 impuzzle (0.3-2maemo0) unstable; urgency=low diff --git a/debian/control b/debian/control index d61be9a..c5f80ea 100644 --- a/debian/control +++ b/debian/control @@ -2,94 +2,13 @@ Source: impuzzle Section: user/games Priority: optional Maintainer: Timo Härkönen -Build-Depends: debhelper (>= 5), libqt4-maemo5-dev +Build-Depends: debhelper (>= 5), libqt4-dev (>= 4.6.0) Standards-Version: 3.7.2 XSBC-Bugtracker: mailto:timop.harkonen@gmail.com Package: impuzzle Architecture: any -Depends: libqt4-maemo5-core, libqt4-maemo5-gui +Depends: libqt4-core (>= 4.6.0), libqt4-gui (>= 4.6.0) Description: Image puzzle game -XB-Maemo-Icon-26: -MB5!.1PT*&@H````-24A$4@```#`````P"`8```!7`OF'`````7-21T(`KLX< -MZ0````9B2T=$`+``,0`QG?,\]@````EP2%ES```+$P``"Q,!`)J<&`````=T -M24U%!]H#"1$"$'>\&Q(````9=$58=$-O;6UE;G0`0W)E871E9"!W:71H($=) -M35!7@0X7```-DDE$051HWM6:2XYDV7%$C_F]+S*SNBE^-]``(:@'$K0M:2)` -M(^U!,VI?FA(D"`B:$P1%UBG -M3_SCAP^DC3'J7TX@7,_=-MMF`6!$?@B8@0@9!D2[J, -MGVW6;00R3`DA0F59,1&5O*!CDNP.'\"'YUH:W$\QR0%-R1&`JRQ'E&,#3 -MJ*@&E1TAQ:-L*OK898;H$M*C>I]#R&+:E3T+RZ3%LI'-0D`"5Z"20.5``)/@ -MN1S@D'P;P:&XG*C:KCY@M4V7`U-2O6E%O/YUEUW9:963OCI.[F*";SH#HXU/ -M@6UV.[B!T>\7ANHM\.7`B."&?$CY'.U(!%.A+B.%Y)"4X&5;$I8,Z(@HP]N) -M`4P$JM1+53!5-:[R\GMI?>C>H?-KQ+;!K@QD7ADF(B$-!.'-G!(',(5?(O(E -MQ',,;A&Z29X1#'7:@)1T-CID6W`C'(&^=B*`<940%2V%B>X!;(Y.QC(/$;X*<1SA&X1U0]C,`03Q06-RZHW[1+Z1H'+0(&@2B<;[R/3*:"B/I964ZTII1'025'#(X1/"EX&H/9 -M]3Q&N$M$B^J!:!S\\1RF<%ETY%,0AJ?N"=N/1CZZO*X,C,9&9W)@(@+WP(H> -MG`=`H]-A/"5VF'F(UYND0YH-H;HA9H0F<"A\&Z$K[9*\A68AC`&^':,\*2>\ -M0*,-/2+(K)$UNYYGE]O;`\+%P(P((N'$9`1G5J2'"FT>`0CAA)-@/D5\>9*> -MCE",,6)&>)1#-0M"3.098M;$C4/RU`6K\&$,I*JG#3S;[]3!]AR#J'ZBAS2Y -MMX^>:B\1[(35T=^-.D/!H22V'P/5X.5@*1F8.>'U.>+VA/(&FJ`K2C."6Q24 -M3JFB'O($3HRR:8TLHDJ(8=@.0@E)P4*%QGY`1O] -M6_LS__GY^3?/$3]^AI>7.>-'$?%AC/QP''Z2=-0\&"-"0T+5*I+$B-!__.8W -M\S__X?N-4]O5R!%1,R,*D0(()ZJH*7K**I-__=WO]*OOOK,!K\4;Z'5O[@6I -M7C;W3+;-6R9WN_YF48V9L!,R(GR+T(+*A_@B]7ZG7.Q$`=)#)$2TP7M -MS#%XB<@GR4\1#HD80Y*D&"@*0JG/QDX5_8+$S8Z+O/F"&H$S8;031'&:H.N[ -MRP"1^!&66Y%'WBX(;<-GP`NP-=@UH==TA(Z(]4U$_&B,?1N#`$=$Z9+^<&)P -M$>&J"CL;!C?O`L8/RAF@[.CKD9FP'\\-]-`B``HQS#4DF448&<`3D!ID6['M -M]9JY9TH_OT5\^O8X]C&&6T)*$D2XZ7T+$,*V+!G%\,6-V[JDI*9KX!6)Z:Q$ -M8^Z#;OLK['@HGI[,JO*X0A9C7$,4`Y\SO?;VMG,^1[S\W9Q/W\QYGQ%YT0-% -MH`@I`B)*#^V*:,%WTO0(7]19Q5#'@T8'48U?[-0U.BX:\7"A!8TRK:\,UR6_ -M&HK/O5GUBKUMIW3.7\SY]O/G9Q]C9-A6A/2>5=N.*"J@=TZ/W$J)IM7CTKT( -M-?M4,]BX],+>+=9Y4(\JL0K;E2$B(+,XT!BP%I;("+YD6,V-O^OSDBUD%1;^TM,HO,J]S))E38(J(> -MA^IQ[G;`C*[_`"(W&O'@+Z4+KME;)>%,1Z?@8J-I,PI$:IX`"_C36IPV<\X] -M]LX[V#67_C#G&$5<]@YWO5W*M?D,`H61,J4(PD3L)#J"H_E)&9\M5O2H0VQ< -M@MU57K";[0*X2TRM]*[7?;K?6<`Q!CLSS[5H="0@7B)>IHO:NM!.71129M86 -M"(2M[@W&E1]?DK%*I_D.(T8WI:^)5@9V*6DMB"!T[1A:FKJ>-X"]=\'E&+SM -MC6L21U94N8W!RYP3^Z=3F5L01%BYV6G1Q@,H+95Q"@6"B$>Y=`UW9?0RJ(SI -MB8OB@?V/IFUTR.S/:'1IY$,2K^?)DC@S&1*[7SHB4A%GP.N"->M]:Q6X$4AM#:ZAEPF&J.*9J_*0+-4/DQATK_\:WLF(I@Y.:>ULXD,U&F"MF+9NAR`$(1O)=V_G"2 -M=AU?D5=I288&V49?Y<+77: -MR5E&%U4H(@41QDW`(G:O60;2:]@?)\"Y5M[WQGM+N:5*UV/ZVZZY^\-%\+L# -M%UDS#%K`="U?S/1JP,S\*PIAEV;.G6S:>NS9Z-0L>]&]T=O[EU[^.__K^^U2)%:^]M<$GL)N-YMI89-JU2Y/6 -MA+>T7^>G^_W/K^?YLU'U+Y46EAL*:Z*5:B@VU$NMT@,7M>I)V_M;6ZMV0ZXM -M6Y6#`6425XB[A+[.O=G@U>*>""^;E=M6*'.3=FJ,>(KX\NV*Z1NA1F87CW9`N9HALKYH57GMSVH^:SQ8G5U_<;:[7 -MWVUVVB=X=W-G.W9FZLPDO7<=.^0\U_(QYU,F\\O>?TC[%[?,I[/1)FSMXC"* -M3#)"/VBXAR2L#+S9W-K'7&>M"'N9Y1YT:LH@\'F>^*LF?MW;^\I$IK)7-,MF -M[>T[<-_;NQ=G`:]::_[I/'\ZS[U^GSN_,_3,1=..D2E'Q*YH$V01V*;(`N8N -M=OZ:R9NM#;[O7>*PB=]U1X@(OZWUR(`O=ENO]W4'2U>G7#>QMTR?)>ZU,M>9 -M)O#Q1^GWG];Z,-_2GVS?4[(R-<:(LZGUQ32C-CK(B;.V8T5\ -M1/6QTXGPO88C+G99._2O5-C'=CHSL?1PYNJ%^]Y>H&5B.?>GS)<_KO7TY[6^ -MF?>]GVT[2\C'S-19Q"U6&@4$B3=8LA1*NRXJ37$^GJL.=JVXXIV>$*Y3T+[* -MHM?EB?LF`!_W]N-TDZG3]K:Y.W&62+YGYC;QELFGW.?'O7YZVM_.5_M)=GCG -M;8[0"8HT.T"DM1&2)2DEQ+84\L(/!_8BP:/@T9=H'[U0-B)=AB_5$B![Z@)\ -M7&LX,T-R]N]6H^#*318[T9O3IQEID\G3,IIO>XK$ -M5!/5&PF-VD'P>9>"F^`ZD0JBSWA]S%M--&@JT4D3Q'U\;!#V.VY*_6O4WB>:5)%+.7H)- -MC+<>]ZYLP[,T0.R&WM4.W--*>G?JP@J`,\VVM;R]3&RC>]IW.Q;UN_EE[]/2 -M#`6;O-:'GO+%0+_:)L@2.HM<^<+6>RB*$3@N52BJ)W5?'Y=J,9=]OKL%\ -M.K6^NM2'[86UTBQ;Y00LITY;IZWE)&W/SSL_.S13C!OBB-#PUD-!78=N6_%0 -MQQ:NKQUY3$WNTE]!TX:>FC7!$Z72[CL71A>UNSN5Y8"*]-7UJJXV -M2=HZ\SH"HM-06;#F@K\7C`6Q,^\K%)/P[.-&U-71DE"VZ(KZ&L!U)_YB1VT; -M$ER"??4VXWTO<55'2ZRB'NYFC0?_J7]#Z#[WK<"V2N\ZO.:T+W8P/_#Z8YR6G";59[`````$E%3D2N0F"" -` + impuzzle is a picture puzzle game that let's you + use your own pictures as the game board. \ No newline at end of file diff --git a/debian/rules b/debian/rules index 53a24ae..cb1cf1e 100755 --- a/debian/rules +++ b/debian/rules @@ -4,7 +4,7 @@ builddir: mkdir -p builddir builddir/Makefile: builddir - cd builddir && /opt/qt4-maemo5/bin/qmake-qt4 PREFIX=/usr ../$(APPNAME).pro + cd builddir && qmake-qt4 PREFIX=/usr ../$(APPNAME).pro build: build-stamp diff --git a/src/defines.h b/src/defines.h index d4dd36b..9dc6baf 100644 --- a/src/defines.h +++ b/src/defines.h @@ -34,4 +34,7 @@ #define RANDOM_IMAGE_TXT "Random image" #define SELECT_IMAGE_TXT "Select image..." +#define RESTORE_FILE "impuzzle.restore" +#define HOME_DIRECTORY ".impuzzle" + #endif // DEFINES_H diff --git a/src/gameview.cpp b/src/gameview.cpp index 2089637..ee44f0a 100644 --- a/src/gameview.cpp +++ b/src/gameview.cpp @@ -20,6 +20,8 @@ #include "puzzleitem.h" #include "defines.h" #include "introitem.h" +#include "imageimporter.h" +#include "settings.h" #include #include @@ -28,6 +30,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -42,12 +48,21 @@ GameView::GameView(QWidget *parent) : introItem_ = new IntroItem; introItem_->setText("Select new game from menu to play"); - scene_->addItem(introItem_); verticalStep_ = 0; horizontalStep_ = 0; qsrand(QDateTime::currentDateTime().toTime_t()); + + if(QFile::exists(QString("%1/%2/%3") + .arg(QDir::homePath()).arg(HOME_DIRECTORY).arg(RESTORE_FILE))) { + if(!restoreGame()) { + setPieces(ImageImporter::instance()->newPieces(Settings::instance()->image(), Settings::instance()->pieceCount())); + } + } + else { + scene_->addItem(introItem_); + } } GameView *GameView::instance() @@ -64,7 +79,7 @@ QList GameView::pieces() const return pieces_; } -void GameView::setPieces(const QList pieces) +void GameView::setPieces(const QList pieces, bool shuffle) { if(pieces.isEmpty()) { qDebug() << "Empty list @ GameView::setPieces"; @@ -114,8 +129,10 @@ void GameView::setPieces(const QList pieces) } } - // Wait - QTimer::singleShot(750, this, SLOT(shufflePieces())); + // Wait and shuffle if desired + if(shuffle) { + QTimer::singleShot(750, this, SLOT(shufflePieces())); + } } void GameView::shufflePieces() @@ -140,7 +157,6 @@ void GameView::shufflePieces() } } - // TODO Animate transitions to new locations QParallelAnimationGroup *animationGroup = new QParallelAnimationGroup(this); for(int i = 0; i < pieces_.count(); ++i) { QPropertyAnimation *animation = new QPropertyAnimation(pieces_.at(i), "pos"); @@ -236,3 +252,182 @@ void GameView::setMovingPieces() } } } + +bool GameView::restoreGame() +{ + // Read settings from file + QFile file(QString("%1/%2/%3") + .arg(QDir::homePath()) + .arg(HOME_DIRECTORY) + .arg(RESTORE_FILE)); + + if(!file.open(QIODevice::ReadOnly)) { + qDebug() << "Failed to open restore file for reading"; + return false; + } + + QTextStream in(&file); + + QStringList list; + + list = in.readLine().split(";;"); + + qDebug() << "restore list count: " << list.count(); + + if(!list.isEmpty()) { + Settings::instance()->setPieceCount(list.at(0).toInt()); + + QString im = list.at(1); + if(im == "default" || im.isEmpty()) { + Settings::instance()->setImage(0); + Settings::instance()->setImagePath("default"); + } + else { + Settings::instance()->setImagePath(im); + Settings::instance()->setImage(QPixmap(im)); + } + PuzzleItem::setMoveCount(list.at(2).toInt()); + + setPieces(ImageImporter::instance()->newPieces(Settings::instance()->image(), Settings::instance()->pieceCount()), false); + + qDebug() << "pieces_ count after restoring image: " << pieces_.count(); + + if(list.count() >= pieces_.count() + 3) { + for(int j = 0; j < pieces_.count(); ++j) { + if(!list.at(j + 3).isNull()) { + QStringList points = list.at(j + 3).split("#"); + //if(points.count() == 2) + QPointF point(points.at(0).toInt(), points.at(1).toInt()); + + qDebug() << "Setting piece " << pieces_.at(j)->pieceNumber(); + qDebug() << "x: " << point.x() << " y: " << point.y(); + + pieces_.at(j)->setCurrentPlace(point); + } + } + } + else { + file.close(); + file.remove(); + return false; + } + + QStringList hidden = list.last().split("#"); + + if(hidden.count() == 3) { + for(int m = 0; m < pieces_.count(); ++m) { + pieces_.at(m)->setPos(pieces_.at(m)->currentPlace()); + if(pieces_.at(m)->pieceNumber() == hidden.at(2).toInt()) { + qDebug() << "Hiding piece number " << hidden; + hiddenIndex_ = m; + } + } + + setEmptyPlace(QPointF(hidden.at(0).toInt(), hidden.at(1).toInt())); + + pieces_.at(hiddenIndex_)->setVisible(false); + + setMovingPieces(); + } + else { + // TODO: revert + setPieces(ImageImporter::instance()->newPieces(Settings::instance()->image(), Settings::instance()->pieceCount())); + file.close(); + file.remove(); + return false; + } + } + else { + qDebug() << "Invalid restore file"; + file.close(); + file.remove(); + return false; + } + + file.close(); + file.remove(); + + return true; +} + +bool GameView::saveGame() +{ + if(pieces_.isEmpty() || pieces_.count() < EASY_PIECE_COUNT) { + return false; + } + + QDir dir; + if(!dir.exists(QString("%1/%2") + .arg(QDir::homePath()) + .arg(HOME_DIRECTORY))) { + dir.mkpath(QString("%1/%2") + .arg(QDir::homePath()) + .arg(HOME_DIRECTORY)); + } + + QFile file(QString("%1/%2/%3") + .arg(QDir::homePath()) + .arg(HOME_DIRECTORY) + .arg(RESTORE_FILE)); + + if(!file.open(QIODevice::WriteOnly)) { + qDebug() << "Failed to open restore file for writing"; + return false; + } + + QTextStream out(&file); + + out << Settings::instance()->pieceCount(); + out << ";;"; + if(Settings::instance()->imagePath().isEmpty()) { + out << "default"; + } + else { + out << Settings::instance()->imagePath(); + } + out << ";;"; + out << PuzzleItem::moveCount(); + out << ";;"; + + // piece positions + int number = 0; + int hiddenNo = 0; + + while(number != pieces_.count()) { + for(int i = 0; i < pieces_.count(); ++i) { + if(pieces_.at(i)->pieceNumber() == number + 1) { + out << pieces_.at(i)->currentPlace().x(); + out << "#"; + out << pieces_.at(i)->currentPlace().y(); + out << ";;"; + pieces_.at(i)->pieceNumber(); + if(!pieces_.at(i)->isVisible()) { + hiddenNo = number + 1; + } + number++; + break; + } + } + } + + out << QString("%1#%2#%3").arg(emptyPlace().x()).arg(emptyPlace().y()).arg(hiddenNo); + + out << "\n"; + + file.close(); + + return true; +} + +void GameView::closeEvent(QCloseEvent *event) +{ + int answer = QMessageBox::question(this, tr("Save game status?"), + tr("Saved status will be automatically loaded when you start the application next time"), + QMessageBox::Yes, QMessageBox::No); + + if(answer == QMessageBox::Yes) { + saveGame(); + } + + event->accept(); +} diff --git a/src/gameview.h b/src/gameview.h index 60af555..54e3393 100644 --- a/src/gameview.h +++ b/src/gameview.h @@ -38,8 +38,13 @@ public: void setMovingPieces(); public slots: - void setPieces(const QList pieces); + void setPieces(const QList pieces, bool shuffle = true); void shufflePieces(); + bool restoreGame(); + bool saveGame(); + +protected: + void closeEvent(QCloseEvent *event); private: GameView(QWidget *parent = 0); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index df39b20..dbb6910 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -43,6 +43,7 @@ void MainWindow::createMenu() { menu_ = menuBar()->addMenu(""); menu_->addAction(newGameAction_); + menu_->addAction(saveAction_); menu_->addAction(importAction_); } @@ -57,6 +58,9 @@ void MainWindow::createActions() settingsAction_ = new QAction(tr("Settings"), this); connect(settingsAction_, SIGNAL(triggered()), this, SLOT(settingsClicked())); + + saveAction_ = new QAction(tr("Save game"), this); + connect(saveAction_, SIGNAL(triggered()), GameView::instance(), SLOT(saveGame())); } void MainWindow::importClicked() diff --git a/src/mainwindow.h b/src/mainwindow.h index df704e4..756cb43 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -44,6 +44,7 @@ private: QAction *newGameAction_; QAction *importAction_; QAction *settingsAction_; + QAction *saveAction_; QMenu *menu_; diff --git a/src/puzzleitem.cpp b/src/puzzleitem.cpp index de9d3dc..93e5675 100644 --- a/src/puzzleitem.cpp +++ b/src/puzzleitem.cpp @@ -164,3 +164,8 @@ bool PuzzleItem::drawNumber() const { return drawNumber_; } + +void PuzzleItem::setMoveCount(int count) +{ + moveCount_ = count; +} diff --git a/src/puzzleitem.h b/src/puzzleitem.h index 3e8297e..b1abf8b 100644 --- a/src/puzzleitem.h +++ b/src/puzzleitem.h @@ -39,6 +39,7 @@ public: void setMovable(bool canMove); void moveMeTo(const QPointF &location); static int moveCount(); + static void setMoveCount(const int count); static void resetMoveCount(); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void setPieceNumber(const int pieceNumber); diff --git a/src/settings.cpp b/src/settings.cpp index 62801af..93af8ba 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -8,6 +8,7 @@ Settings::Settings(QObject *parent) : { pieceCount_ = EASY_PIECE_COUNT; image_ = 0; + imagePath_ = ""; } Settings *Settings::instance() @@ -38,3 +39,13 @@ void Settings::setImage(const QPixmap &image) { image_ = image; } + +QString Settings::imagePath() const +{ + return imagePath_; +} + +void Settings::setImagePath(const QString &path) +{ + imagePath_ = path; +} diff --git a/src/settings.h b/src/settings.h index 06b1a54..4d69150 100644 --- a/src/settings.h +++ b/src/settings.h @@ -17,6 +17,9 @@ public: QPixmap image() const; void setImage(const QPixmap &image); + QString imagePath() const; + void setImagePath(const QString &path); + private: Settings(QObject *parent = 0); @@ -24,5 +27,6 @@ private: int pieceCount_; QPixmap image_; + QString imagePath_; }; #endif diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp index 6507153..778666d 100644 --- a/src/settingsdialog.cpp +++ b/src/settingsdialog.cpp @@ -87,7 +87,9 @@ void SettingsDialog::imageSelectionChanged(const QString &txt) qDebug() << QString("pics list contains %1 entries").arg(pics.count()); - Settings::instance()->setImage(QPixmap(QDir::homePath() + QLatin1String("/MyDocs/.images/") + pics.at(qrand() % pics.count()))); + QString path = QDir::homePath() + QLatin1String("/MyDocs/.images/") + pics.at(qrand() % pics.count()); + Settings::instance()->setImage(QPixmap(path)); + Settings::instance()->setImagePath(path); if(selectedImageLabel_->isVisible()) { selectedImageLabel_->setVisible(false); @@ -102,6 +104,7 @@ void SettingsDialog::imageSelectionChanged(const QString &txt) tr("Images (*.png *.xpm *.jpg)")); Settings::instance()->setImage(QPixmap(fileName)); + Settings::instance()->setImagePath(fileName); selectedImageLabel_->setText(fileName); @@ -113,6 +116,7 @@ void SettingsDialog::imageSelectionChanged(const QString &txt) qDebug() << "Default image selected"; Settings::instance()->setImage(0); + Settings::instance()->setImagePath("default"); if(selectedImageLabel_->isVisible()) { selectedImageLabel_->setVisible(false); -- 1.7.9.5