You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
610 lines
17 KiB
610 lines
17 KiB
15 years ago
|
/* -------------------------------------------------------------
|
||
|
KDE Tuberling
|
||
|
Play ground widget
|
||
|
mailto:e.bischoff@noos.fr
|
||
|
------------------------------------------------------------- */
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include <kmessagebox.h>
|
||
|
#include <klocale.h>
|
||
|
#include <kstandarddirs.h>
|
||
|
#include <kprinter.h>
|
||
|
|
||
|
#include <qfile.h>
|
||
|
#include <qpainter.h>
|
||
|
#include <qimage.h>
|
||
|
#include <qcursor.h>
|
||
|
#include <qdom.h>
|
||
|
|
||
|
#include "playground.moc"
|
||
|
#include "toplevel.h"
|
||
|
|
||
|
#define XMARGIN 5
|
||
|
#define YMARGIN 5
|
||
|
|
||
|
// Constructor
|
||
|
PlayGround::PlayGround(TopLevel *parent, const char *name, uint selectedGameboard)
|
||
|
: QWidget(parent, name)
|
||
|
{
|
||
|
topLevel = parent;
|
||
|
|
||
|
textsLayout = objectsLayout = 0;
|
||
|
textsList = soundsList = 0;
|
||
|
draggedCursor = 0;
|
||
|
|
||
|
toDraw.setAutoDelete(true);
|
||
|
history.setAutoDelete(true);
|
||
|
|
||
|
setBackgroundColor(white);
|
||
|
|
||
|
QDomDocument layoutsDocument;
|
||
|
bool ok = topLevel->loadLayout(layoutsDocument);
|
||
|
if (ok) ok = registerPlayGrounds(layoutsDocument);
|
||
|
if (ok) ok = loadPlayGround(layoutsDocument, selectedGameboard);
|
||
|
if (!ok) loadFailure();
|
||
|
|
||
|
currentAction = 0;
|
||
|
setupGeometry();
|
||
|
}
|
||
|
|
||
|
// Destructor
|
||
|
PlayGround::~PlayGround()
|
||
|
{
|
||
|
delete [] textsLayout;
|
||
|
delete [] objectsLayout;
|
||
|
|
||
|
delete [] textsList;
|
||
|
delete [] soundsList;
|
||
|
|
||
|
delete draggedCursor;
|
||
|
}
|
||
|
|
||
|
// Reset the play ground
|
||
|
void PlayGround::reset()
|
||
|
{
|
||
|
toDraw.clear();
|
||
|
history.clear();
|
||
|
currentAction = 0;
|
||
|
}
|
||
|
|
||
|
// Change the gameboard
|
||
|
void PlayGround::change(uint selectedGameboard)
|
||
|
{
|
||
|
QDomDocument layoutsDocument;
|
||
|
bool ok = topLevel->loadLayout(layoutsDocument);
|
||
|
if (ok) ok = loadPlayGround(layoutsDocument, selectedGameboard);
|
||
|
if (!ok) loadFailure();
|
||
|
|
||
|
toDraw.clear();
|
||
|
history.clear();
|
||
|
currentAction = 0;
|
||
|
|
||
|
setupGeometry();
|
||
|
|
||
|
update();
|
||
|
}
|
||
|
|
||
|
// Repaint all the editable area
|
||
|
void PlayGround::repaintAll()
|
||
|
{
|
||
|
QRect dirtyArea
|
||
|
(editableArea.left() - 10,
|
||
|
editableArea.top() - 10,
|
||
|
editableArea.width() + 20,
|
||
|
editableArea.height() + 20);
|
||
|
|
||
|
repaint(dirtyArea, false);
|
||
|
}
|
||
|
|
||
|
// Undo last action
|
||
|
// Returns true if everything went fine
|
||
|
bool PlayGround::undo()
|
||
|
{
|
||
|
ToDraw *newObject;
|
||
|
Action *undone;
|
||
|
int zOrder;
|
||
|
|
||
|
if (!(undone = history.at(--currentAction)))
|
||
|
return false;
|
||
|
|
||
|
zOrder = undone->ZOrderAfter();
|
||
|
if (zOrder != -1)
|
||
|
{
|
||
|
// Undo an "add" or a "move" action
|
||
|
if (!toDraw.remove(zOrder)) return false;
|
||
|
}
|
||
|
|
||
|
zOrder = undone->ZOrderBefore();
|
||
|
if (zOrder != -1)
|
||
|
{
|
||
|
// Undo a "delete" or a "move" action
|
||
|
newObject = new ToDraw(undone->DrawnBefore());
|
||
|
if (!toDraw.insert(zOrder, newObject))
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Redo next action
|
||
|
// Returns true if everything went fine
|
||
|
bool PlayGround::redo()
|
||
|
{
|
||
|
ToDraw *newObject;
|
||
|
Action *undone;
|
||
|
int zOrder;
|
||
|
|
||
|
if (!(undone = history.at(currentAction++)))
|
||
|
return false;
|
||
|
|
||
|
zOrder = undone->ZOrderBefore();
|
||
|
if (zOrder != -1)
|
||
|
{
|
||
|
// Redo a "delete" or a "move" action
|
||
|
if (!toDraw.remove(zOrder)) return false;
|
||
|
}
|
||
|
|
||
|
zOrder = undone->ZOrderAfter();
|
||
|
if (zOrder != -1)
|
||
|
{
|
||
|
// Redo an "add" or a "move" action
|
||
|
newObject = new ToDraw(undone->DrawnAfter());
|
||
|
if (!toDraw.insert(zOrder, newObject))
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Save objects laid down on the editable area
|
||
|
bool PlayGround::saveAs(const QString & name)
|
||
|
{
|
||
|
FILE *fp;
|
||
|
const ToDraw *currentObject;
|
||
|
|
||
|
if (!(fp = fopen((const char *) QFile::encodeName(name), "w"))) return false;
|
||
|
|
||
|
fprintf(fp, "%d\n", topLevel->getSelectedGameboard());
|
||
|
for (currentObject = toDraw.first(); currentObject; currentObject = toDraw.next())
|
||
|
currentObject->save(fp);
|
||
|
|
||
|
return !fclose(fp);
|
||
|
}
|
||
|
|
||
|
// Print gameboard's picture
|
||
|
bool PlayGround::printPicture(KPrinter &printer) const
|
||
|
{
|
||
|
QPainter artist;
|
||
|
QPixmap picture(getPicture());
|
||
|
|
||
|
if (!artist.begin(&printer)) return false;
|
||
|
artist.drawPixmap(QPoint(32, 32), picture);
|
||
|
if (!artist.end()) return false;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Get a pixmap containing the current picture
|
||
|
QPixmap PlayGround::getPicture() const
|
||
|
{
|
||
|
QPixmap result(editableArea.size());
|
||
|
QPainter artist(&result);
|
||
|
QRect transEditableArea(editableArea);
|
||
|
|
||
|
transEditableArea.moveBy(-XMARGIN, -YMARGIN);
|
||
|
artist.translate(XMARGIN - editableArea.left(),
|
||
|
YMARGIN - editableArea.top());
|
||
|
drawGameboard(artist, transEditableArea);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
// Draw some text
|
||
|
void PlayGround::drawText(QPainter &artist, QRect &area, QString &textId) const
|
||
|
{
|
||
|
QString label;
|
||
|
|
||
|
label=i18n(textId.latin1());
|
||
|
|
||
|
artist.drawText(area, AlignCenter, label);
|
||
|
}
|
||
|
|
||
|
// Paint the current picture to the given device
|
||
|
void PlayGround::drawGameboard( QPainter &artist, const QRect &area ) const
|
||
|
{
|
||
|
artist.drawPixmap(area.topLeft(), gameboard, area);
|
||
|
|
||
|
artist.setPen(white);
|
||
|
for (int text = 0; text < texts; text++)
|
||
|
drawText(artist, textsLayout[text], textsList[text]);
|
||
|
|
||
|
artist.setPen(black);
|
||
|
for (QPtrListIterator<ToDraw> currentObject(toDraw);
|
||
|
currentObject.current();
|
||
|
++currentObject)
|
||
|
currentObject.current()->draw(artist, area, objectsLayout, &gameboard, &masks);
|
||
|
}
|
||
|
|
||
|
// Painting event
|
||
|
void PlayGround::paintEvent( QPaintEvent *event )
|
||
|
{
|
||
|
QPoint destination(event->rect().topLeft()),
|
||
|
position(destination.x() - XMARGIN,
|
||
|
destination.y() - YMARGIN);
|
||
|
QRect area(position, QSize(event->rect().size()));
|
||
|
QPixmap cache(gameboard.size());
|
||
|
QPainter artist(&cache);
|
||
|
|
||
|
if (destination.x() < XMARGIN) destination.setX(XMARGIN);
|
||
|
if (destination.y() < YMARGIN) destination.setY(YMARGIN);
|
||
|
area = QRect(0, 0, gameboard.width(), gameboard.height()).intersect(area);
|
||
|
if (area.isEmpty()) return;
|
||
|
|
||
|
drawGameboard(artist, area);
|
||
|
|
||
|
bitBlt(this, destination, &cache, area, Qt::CopyROP);
|
||
|
}
|
||
|
|
||
|
// Mouse pressed event
|
||
|
void PlayGround::mousePressEvent( QMouseEvent *event )
|
||
|
{
|
||
|
if (draggedCursor) return;
|
||
|
|
||
|
QPoint position(event->x() - XMARGIN,
|
||
|
event->y() - YMARGIN);
|
||
|
if (!zone(position)) return;
|
||
|
|
||
|
int draggedNumber = draggedObject.getNumber();
|
||
|
QPixmap object(objectsLayout[draggedNumber].size());
|
||
|
QBitmap shape(objectsLayout[draggedNumber].size());
|
||
|
bitBlt(&object, QPoint(0, 0), &gameboard, objectsLayout[draggedNumber], Qt::CopyROP);
|
||
|
bitBlt(&shape, QPoint(0, 0), &masks, objectsLayout[draggedNumber], Qt::CopyROP);
|
||
|
object.setMask(shape);
|
||
|
|
||
|
draggedCursor = new QCursor(object, position.x(), position.y());
|
||
|
setCursor(*draggedCursor);
|
||
|
|
||
|
topLevel->playSound(soundsList[draggedNumber]);
|
||
|
}
|
||
|
|
||
|
// Mouse released event
|
||
|
void PlayGround::mouseReleaseEvent( QMouseEvent *event )
|
||
|
{
|
||
|
// If we are not dragging an object, ignore the event
|
||
|
if (!draggedCursor) return;
|
||
|
|
||
|
QCursor arrow;
|
||
|
int draggedNumber = draggedObject.getNumber();
|
||
|
QRect position(
|
||
|
event->x() - XMARGIN - draggedCursor->hotSpot().x(),
|
||
|
event->y() - YMARGIN - draggedCursor->hotSpot().y(),
|
||
|
objectsLayout[draggedNumber].width(),
|
||
|
objectsLayout[draggedNumber].height());
|
||
|
QRect dirtyArea
|
||
|
(editableArea.left() - 10,
|
||
|
editableArea.top() - 10,
|
||
|
editableArea.width() + 20,
|
||
|
editableArea.height() + 20);
|
||
|
ToDraw *newObject;
|
||
|
Action *newAction;
|
||
|
|
||
|
// We are not anymore dragging an object
|
||
|
delete draggedCursor;
|
||
|
draggedCursor = 0;
|
||
|
setCursor(arrow);
|
||
|
|
||
|
// If we are not moving the object to the editable area
|
||
|
if (!dirtyArea.contains(event->pos()))
|
||
|
{
|
||
|
// ... then register its deletion (if coming from the editable area), and return
|
||
|
if (draggedZOrder == -1) return;
|
||
|
|
||
|
while (history.count() > currentAction) history.removeLast();
|
||
|
newAction = new Action(&draggedObject, draggedZOrder, 0, -1);
|
||
|
history.append(newAction);
|
||
|
currentAction++;
|
||
|
topLevel->enableUndo(true);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Register that we have one more object to draw
|
||
|
newObject = new ToDraw(draggedNumber, position);
|
||
|
toDraw.append(newObject);
|
||
|
|
||
|
// Forget all subsequent actions in the undo buffer, and register object's addition (or its move)
|
||
|
while (history.count() > currentAction) history.removeLast();
|
||
|
newAction = new Action(&draggedObject, draggedZOrder, newObject, toDraw.count()-1);
|
||
|
history.append(newAction);
|
||
|
currentAction++;
|
||
|
topLevel->enableUndo(true);
|
||
|
|
||
|
// Repaint the editable area
|
||
|
position.moveBy(XMARGIN, YMARGIN);
|
||
|
repaint(position, false);
|
||
|
|
||
|
}
|
||
|
|
||
|
// Register the various playgrounds
|
||
|
bool PlayGround::registerPlayGrounds(QDomDocument &layoutDocument)
|
||
|
{
|
||
|
QDomNodeList playGroundsList, menuItemsList, labelsList;
|
||
|
QDomElement playGroundElement, menuItemElement, labelElement;
|
||
|
QDomAttr actionAttribute;
|
||
|
|
||
|
playGroundsList = layoutDocument.elementsByTagName("playground");
|
||
|
if (playGroundsList.count() < 1)
|
||
|
return false;
|
||
|
|
||
|
for (uint i = 0; i < playGroundsList.count(); i++)
|
||
|
{
|
||
|
playGroundElement = (const QDomElement &) playGroundsList.item(i).toElement();
|
||
|
|
||
|
menuItemsList = playGroundElement.elementsByTagName("menuitem");
|
||
|
if (menuItemsList.count() != 1)
|
||
|
return false;
|
||
|
|
||
|
menuItemElement = (const QDomElement &) menuItemsList.item(0).toElement();
|
||
|
|
||
|
labelsList = menuItemElement.elementsByTagName("label");
|
||
|
if (labelsList.count() != 1)
|
||
|
return false;
|
||
|
|
||
|
labelElement = (const QDomElement &) labelsList.item(0).toElement();
|
||
|
actionAttribute = menuItemElement.attributeNode("action");
|
||
|
topLevel->registerGameboard(labelElement.text(), actionAttribute.value().latin1());
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Load background and draggable objects masks
|
||
|
bool PlayGround::loadPlayGround(QDomDocument &layoutDocument, uint toLoad)
|
||
|
{
|
||
|
QDomNodeList playGroundsList,
|
||
|
editableAreasList, categoriesList, objectsList,
|
||
|
gameAreasList, maskAreasList, soundNamesList, labelsList;
|
||
|
QDomElement playGroundElement,
|
||
|
editableAreaElement, categoryElement, objectElement,
|
||
|
gameAreaElement, maskAreaElement, soundNameElement, labelElement;
|
||
|
QDomAttr gameboardAttribute, masksAttribute,
|
||
|
leftAttribute, topAttribute, rightAttribute, bottomAttribute,
|
||
|
refAttribute;
|
||
|
|
||
|
playGroundsList = layoutDocument.elementsByTagName("playground");
|
||
|
if (toLoad >= playGroundsList.count())
|
||
|
return false;
|
||
|
|
||
|
playGroundElement = (const QDomElement &) playGroundsList.item(toLoad).toElement();
|
||
|
|
||
|
gameboardAttribute = playGroundElement.attributeNode("gameboard");
|
||
|
if (!gameboard.load(locate("data", "ktuberling/pics/" + gameboardAttribute.value())))
|
||
|
return false;
|
||
|
|
||
|
masksAttribute = playGroundElement.attributeNode("masks");
|
||
|
if (!masks.load(locate("data", "ktuberling/pics/" + masksAttribute.value())))
|
||
|
return false;
|
||
|
|
||
|
editableAreasList = playGroundElement.elementsByTagName("editablearea");
|
||
|
if (editableAreasList.count() != 1)
|
||
|
return false;
|
||
|
|
||
|
editableAreaElement = (const QDomElement &) editableAreasList.item(0).toElement();
|
||
|
|
||
|
gameAreasList = editableAreaElement.elementsByTagName("position");
|
||
|
if (gameAreasList.count() != 1)
|
||
|
return false;
|
||
|
|
||
|
gameAreaElement = (const QDomElement &) gameAreasList.item(0).toElement();
|
||
|
leftAttribute = gameAreaElement.attributeNode("left");
|
||
|
topAttribute = gameAreaElement.attributeNode("top");
|
||
|
rightAttribute = gameAreaElement.attributeNode("right");
|
||
|
bottomAttribute = gameAreaElement.attributeNode("bottom");
|
||
|
|
||
|
editableArea.setCoords
|
||
|
(XMARGIN + leftAttribute.value().toInt(),
|
||
|
YMARGIN + topAttribute.value().toInt(),
|
||
|
XMARGIN + rightAttribute.value().toInt(),
|
||
|
YMARGIN + bottomAttribute.value().toInt());
|
||
|
|
||
|
soundNamesList = editableAreaElement.elementsByTagName("sound");
|
||
|
if (soundNamesList.count() != 1)
|
||
|
return false;
|
||
|
|
||
|
soundNameElement = (const QDomElement &) soundNamesList.item(0).toElement();
|
||
|
refAttribute = soundNameElement.attributeNode("ref");
|
||
|
|
||
|
editableSound = refAttribute.value();
|
||
|
|
||
|
categoriesList = playGroundElement.elementsByTagName("category");
|
||
|
texts = categoriesList.count();
|
||
|
if (texts < 1)
|
||
|
return false;
|
||
|
|
||
|
delete[] textsLayout;
|
||
|
textsLayout = new QRect[texts];
|
||
|
delete[] textsList;
|
||
|
textsList = new QString[texts];
|
||
|
|
||
|
for (int text = 0; text < texts; text++)
|
||
|
{
|
||
|
categoryElement = (const QDomElement &) categoriesList.item(text).toElement();
|
||
|
|
||
|
gameAreasList = categoryElement.elementsByTagName("position");
|
||
|
if (gameAreasList.count() != 1)
|
||
|
return false;
|
||
|
|
||
|
gameAreaElement = (const QDomElement &) gameAreasList.item(0).toElement();
|
||
|
leftAttribute = gameAreaElement.attributeNode("left");
|
||
|
topAttribute = gameAreaElement.attributeNode("top");
|
||
|
rightAttribute = gameAreaElement.attributeNode("right");
|
||
|
bottomAttribute = gameAreaElement.attributeNode("bottom");
|
||
|
|
||
|
textsLayout[text].setCoords
|
||
|
(leftAttribute.value().toInt(),
|
||
|
topAttribute.value().toInt(),
|
||
|
rightAttribute.value().toInt(),
|
||
|
bottomAttribute.value().toInt());
|
||
|
|
||
|
labelsList = categoryElement.elementsByTagName("label");
|
||
|
if (labelsList.count() != 1)
|
||
|
return false;
|
||
|
|
||
|
labelElement = (const QDomElement &) labelsList.item(0).toElement();
|
||
|
|
||
|
textsList[text] = labelElement.text();
|
||
|
}
|
||
|
|
||
|
objectsList = playGroundElement.elementsByTagName("object");
|
||
|
decorations = objectsList.count();
|
||
|
if (decorations < 1)
|
||
|
return false;
|
||
|
|
||
|
delete[] objectsLayout;
|
||
|
objectsLayout = new QRect[decorations];
|
||
|
delete[] soundsList;
|
||
|
soundsList = new QString[decorations];
|
||
|
|
||
|
for (int decoration = 0; decoration < decorations; decoration++)
|
||
|
{
|
||
|
objectElement = (const QDomElement &) objectsList.item(decoration).toElement();
|
||
|
|
||
|
gameAreasList = objectElement.elementsByTagName("position");
|
||
|
if (gameAreasList.count() != 1)
|
||
|
return false;
|
||
|
|
||
|
gameAreaElement = (const QDomElement &) gameAreasList.item(0).toElement();
|
||
|
leftAttribute = gameAreaElement.attributeNode("left");
|
||
|
topAttribute = gameAreaElement.attributeNode("top");
|
||
|
rightAttribute = gameAreaElement.attributeNode("right");
|
||
|
bottomAttribute = gameAreaElement.attributeNode("bottom");
|
||
|
|
||
|
objectsLayout[decoration].setCoords
|
||
|
(leftAttribute.value().toInt(),
|
||
|
topAttribute.value().toInt(),
|
||
|
rightAttribute.value().toInt(),
|
||
|
bottomAttribute.value().toInt());
|
||
|
|
||
|
soundNamesList = objectElement.elementsByTagName("sound");
|
||
|
if (soundNamesList.count() != 1)
|
||
|
return false;
|
||
|
|
||
|
soundNameElement = (const QDomElement &) soundNamesList.item(0).toElement();
|
||
|
|
||
|
refAttribute = soundNameElement.attributeNode("ref");
|
||
|
|
||
|
soundsList[decoration] = refAttribute.value();
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Report a load failure
|
||
|
void PlayGround::loadFailure()
|
||
|
{
|
||
|
KMessageBox::error(topLevel, i18n("Fatal error:\n"
|
||
|
"Unable to load the pictures, aborting."));
|
||
|
exit(-1);
|
||
|
}
|
||
|
|
||
|
// Set up play ground's geometry
|
||
|
void PlayGround::setupGeometry()
|
||
|
{
|
||
|
int width = gameboard.width() + 2 * XMARGIN,
|
||
|
height = gameboard.height() + 2 * YMARGIN;
|
||
|
setFixedWidth(width);
|
||
|
setFixedHeight(height);
|
||
|
}
|
||
|
|
||
|
// In which decorative object are we?
|
||
|
// On return, the position is the location of the cursor's hot spot
|
||
|
// Returns false if we aren't in any zone
|
||
|
bool PlayGround::zone(QPoint &position)
|
||
|
{
|
||
|
// Scan all available decorative objects on right side because we may be adding one
|
||
|
int draggedNumber;
|
||
|
for (draggedNumber = 0;
|
||
|
draggedNumber < decorations;
|
||
|
draggedNumber++) if (objectsLayout[draggedNumber].contains(position))
|
||
|
{
|
||
|
position.setX(position.x() - objectsLayout[draggedNumber].x());
|
||
|
position.setY(position.y() - objectsLayout[draggedNumber].y());
|
||
|
|
||
|
draggedObject.setNumber(draggedNumber);
|
||
|
draggedZOrder = -1;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Scan all decorative objects already layed down on editable are because we may be moving or removing one
|
||
|
const ToDraw *currentObject;
|
||
|
|
||
|
for (draggedZOrder = toDraw.count()-1; draggedZOrder >= 0; draggedZOrder--)
|
||
|
{
|
||
|
currentObject = toDraw.at(draggedZOrder);
|
||
|
if (!currentObject->getPosition().contains(position)) continue;
|
||
|
|
||
|
QRect toUpdate(currentObject->getPosition());
|
||
|
draggedObject = *currentObject;
|
||
|
draggedNumber = draggedObject.getNumber();
|
||
|
|
||
|
QBitmap shape(objectsLayout[draggedNumber].size());
|
||
|
QPoint relative(position.x() - toUpdate.x(),
|
||
|
position.y() - toUpdate.y());
|
||
|
bitBlt(&shape, QPoint(0, 0), &masks, objectsLayout[draggedNumber], Qt::CopyROP);
|
||
|
if (!shape.convertToImage().pixelIndex(relative.x(), relative.y())) continue;
|
||
|
|
||
|
toDraw.remove(draggedZOrder);
|
||
|
toUpdate.moveBy(XMARGIN, YMARGIN);
|
||
|
repaint(toUpdate, false);
|
||
|
|
||
|
position = relative;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// If we are on the gameboard itself, then play "tuberling" sound
|
||
|
if (editableArea.contains(position))
|
||
|
topLevel->playSound(editableSound);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Load objects and lay them down on the editable area
|
||
|
bool PlayGround::loadFrom(const QString &name)
|
||
|
{
|
||
|
FILE *fp;
|
||
|
bool eof = false;
|
||
|
ToDraw readObject, *newObject;
|
||
|
Action *newAction;
|
||
|
|
||
|
if (!(fp = fopen(QFile::encodeName(name), "r"))) return false;
|
||
|
|
||
|
uint newGameboard;
|
||
|
int nitems = fscanf(fp, "%u\n", &newGameboard);
|
||
|
if (nitems == EOF)
|
||
|
{
|
||
|
fclose(fp);
|
||
|
return false;
|
||
|
}
|
||
|
topLevel->changeGameboard(newGameboard);
|
||
|
|
||
|
for (;;)
|
||
|
{
|
||
|
if (!readObject.load(fp, decorations, eof))
|
||
|
{
|
||
|
fclose(fp);
|
||
|
return false;
|
||
|
}
|
||
|
if (eof)
|
||
|
{
|
||
|
return !fclose(fp);
|
||
|
}
|
||
|
newObject = new ToDraw(readObject);
|
||
|
toDraw.append(newObject);
|
||
|
newAction = new Action(0, -1, newObject, toDraw.count()-1);
|
||
|
history.append(newAction);
|
||
|
currentAction++;
|
||
|
|
||
|
}
|
||
|
}
|