Commit d888fe00 authored by Stefan Majewsky's avatar Stefan Majewsky

Update the internal state of the MovePieceInteractor when pieces are merged.

This fixes the only known (and indeed quite annoying) crash in Palapeli.

svn path=/trunk/KDE/kdegames/palapeli/; revision=1119155
parent 9b4083f1
......@@ -47,7 +47,6 @@ static QGraphicsItem* findSelectableItemAt(const QPointF& scenePos, QGraphicsSce
void Palapeli::MovePieceInteractor::determineSelectedItems(QGraphicsItem* clickedItem, Palapeli::Piece* clickedPiece)
const QList<QGraphicsItem*> selectedItems = clickedItem->scene()->selectedItems();
if (clickedItem->isSelected())
......@@ -57,10 +56,7 @@ void Palapeli::MovePieceInteractor::determineSelectedItems(QGraphicsItem* clicke
Palapeli::Piece* selectedPiece = Palapeli::Piece::fromSelectedItem(selectedItem);
if (selectedPiece)
m_currentItems << selectedItem;
m_currentPieces << selectedPiece;
//NOTE: clickedItem is in the list selectedItems, so it need not be handled separately.
......@@ -70,7 +66,6 @@ void Palapeli::MovePieceInteractor::determineSelectedItems(QGraphicsItem* clicke
foreach (QGraphicsItem* selectedItem, selectedItems)
m_currentItems << clickedItem;
m_currentPieces << clickedPiece;
......@@ -88,10 +83,12 @@ bool Palapeli::MovePieceInteractor::startInteraction(const Palapeli::MouseEvent&
//start moving this piece
determineSelectedItems(selectableItemUnderMouse, piece);
m_baseScenePosition = event.scenePos;
m_currentOffset = QPointF();
foreach(Palapeli::Piece* piece, m_currentPieces)
m_basePositions << piece->pos();
connect(piece, SIGNAL(replacedBy(Palapeli::Piece*)), SLOT(pieceReplacedBy(Palapeli::Piece*)), Qt::DirectConnection);
return true;
......@@ -99,19 +96,37 @@ bool Palapeli::MovePieceInteractor::startInteraction(const Palapeli::MouseEvent&
void Palapeli::MovePieceInteractor::continueInteraction(const Palapeli::MouseEvent& event)
m_currentOffset = event.scenePos - m_baseScenePosition;
for (int i = 0; i < m_currentPieces.count(); ++i)
m_currentPieces[i]->setPos(m_basePositions[i] + event.scenePos - m_baseScenePosition);
m_currentPieces[i]->setPos(m_basePositions[i] + m_currentOffset);
void Palapeli::MovePieceInteractor::pieceReplacedBy(Palapeli::Piece* replacement)
//This slot is triggered when a MergeGroup replaces one of the m_currentPieces by a new piece.
//remove old piece from data structures
int index = m_currentPieces.indexOf(reinterpret_cast<Palapeli::Piece*>(sender()));
//add new piece (might not always be necessary, if the new piece replaces more than one of the selected pieces)
if (!m_currentPieces.contains(replacement))
m_currentPieces << replacement;
m_basePositions << replacement->pos() - m_currentOffset;
void Palapeli::MovePieceInteractor::stopInteraction(const Palapeli::MouseEvent& event)
foreach(Palapeli::Piece* piece, m_currentPieces)
disconnect(piece, 0, this, 0);
......@@ -334,3 +349,5 @@ bool Palapeli::ToggleConstraintInteractor::startInteraction(const Palapeli::Mous
//END Palapeli::ToggleConstraintInteractor
#include "interactors.moc"
......@@ -30,21 +30,23 @@ namespace Palapeli
//This interactor is assigned to LeftButton;NoModifier by default.
//1. When you click on and drag a selected piece, all selected pieces are moved.
//2. When you click on and drag an unselected piece, all other pieces are deselected, the clicked piece is selected and moved.
class MovePieceInteractor : public Palapeli::Interactor
class MovePieceInteractor : public QObject, public Palapeli::Interactor
MovePieceInteractor(QGraphicsView* view);
virtual bool startInteraction(const Palapeli::MouseEvent& event);
virtual void continueInteraction(const Palapeli::MouseEvent& event);
virtual void stopInteraction(const Palapeli::MouseEvent& event);
protected Q_SLOTS:
void pieceReplacedBy(Palapeli::Piece* replacement);
Palapeli::Piece* findPieceForItem(QGraphicsItem* mouseInteractingItem) const;
void determineSelectedItems(QGraphicsItem* clickedItem, Palapeli::Piece* clickedPiece);
QList<QGraphicsItem*> m_currentItems; //the item which accepts the events
QList<Palapeli::Piece*> m_currentPieces; //the piece for this item
QPointF m_baseScenePosition;
QList<Palapeli::Piece*> m_currentPieces;
QPointF m_baseScenePosition, m_currentOffset;
QList<QPointF> m_basePositions;
......@@ -151,7 +151,7 @@ void Palapeli::MergeGroup::createMergedPiece()
if (piece->isSelected())
m_mergedPiece->setZValue(qMax(m_mergedPiece->zValue(), piece->zValue()));
delete piece;
piece->announceReplaced(m_mergedPiece); //make sure that interactors know about the change, and delete the piece
m_mergedPiece->rewriteLogicalNeighbors(m_pieces, 0); //0 = these neighbors should be dropped
foreach (Palapeli::Piece* logicalNeighbor, m_mergedPiece->logicalNeighbors())
......@@ -165,6 +165,12 @@ void Palapeli::Piece::rewriteLogicalNeighbors(const QList<Palapeli::Piece*>& old
m_logicalNeighbors += newPiece;
void Palapeli::Piece::announceReplaced(Palapeli::Piece* replacement)
emit replacedBy(replacement);
delete this;
void Palapeli::Piece::addAtomicSize(const QSize& size)
m_atomicSize = m_atomicSize.expandedTo(size);
......@@ -63,8 +63,11 @@ namespace Palapeli
///When piece instances have been replaced by other piece instances, this method can be used to update the internal data structures of their logical neighbors.
void rewriteLogicalNeighbors(const QList<Palapeli::Piece*>& oldPieces, Palapeli::Piece* newPiece);
///Call this when this piece instance has been replaced by another piece instance. This will also delete this instance.
void announceReplaced(Palapeli::Piece* replacement);
void moved();
void replacedBy(Palapeli::Piece* newPiece);
friend class MovePieceInteractor;
void beginMove();
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment