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 ...@@ -47,7 +47,6 @@ static QGraphicsItem* findSelectableItemAt(const QPointF& scenePos, QGraphicsSce
void Palapeli::MovePieceInteractor::determineSelectedItems(QGraphicsItem* clickedItem, Palapeli::Piece* clickedPiece) void Palapeli::MovePieceInteractor::determineSelectedItems(QGraphicsItem* clickedItem, Palapeli::Piece* clickedPiece)
{ {
m_currentItems.clear();
m_currentPieces.clear(); m_currentPieces.clear();
const QList<QGraphicsItem*> selectedItems = clickedItem->scene()->selectedItems(); const QList<QGraphicsItem*> selectedItems = clickedItem->scene()->selectedItems();
if (clickedItem->isSelected()) if (clickedItem->isSelected())
...@@ -57,10 +56,7 @@ void Palapeli::MovePieceInteractor::determineSelectedItems(QGraphicsItem* clicke ...@@ -57,10 +56,7 @@ void Palapeli::MovePieceInteractor::determineSelectedItems(QGraphicsItem* clicke
{ {
Palapeli::Piece* selectedPiece = Palapeli::Piece::fromSelectedItem(selectedItem); Palapeli::Piece* selectedPiece = Palapeli::Piece::fromSelectedItem(selectedItem);
if (selectedPiece) if (selectedPiece)
{
m_currentItems << selectedItem;
m_currentPieces << selectedPiece; m_currentPieces << selectedPiece;
}
} }
//NOTE: clickedItem is in the list selectedItems, so it need not be handled separately. //NOTE: clickedItem is in the list selectedItems, so it need not be handled separately.
} }
...@@ -70,7 +66,6 @@ void Palapeli::MovePieceInteractor::determineSelectedItems(QGraphicsItem* clicke ...@@ -70,7 +66,6 @@ void Palapeli::MovePieceInteractor::determineSelectedItems(QGraphicsItem* clicke
foreach (QGraphicsItem* selectedItem, selectedItems) foreach (QGraphicsItem* selectedItem, selectedItems)
selectedItem->setSelected(false); selectedItem->setSelected(false);
clickedItem->setSelected(true); clickedItem->setSelected(true);
m_currentItems << clickedItem;
m_currentPieces << clickedPiece; m_currentPieces << clickedPiece;
} }
} }
...@@ -88,10 +83,12 @@ bool Palapeli::MovePieceInteractor::startInteraction(const Palapeli::MouseEvent& ...@@ -88,10 +83,12 @@ bool Palapeli::MovePieceInteractor::startInteraction(const Palapeli::MouseEvent&
//start moving this piece //start moving this piece
determineSelectedItems(selectableItemUnderMouse, piece); determineSelectedItems(selectableItemUnderMouse, piece);
m_baseScenePosition = event.scenePos; m_baseScenePosition = event.scenePos;
m_currentOffset = QPointF();
m_basePositions.clear(); m_basePositions.clear();
foreach(Palapeli::Piece* piece, m_currentPieces) foreach(Palapeli::Piece* piece, m_currentPieces)
{ {
m_basePositions << piece->pos(); m_basePositions << piece->pos();
connect(piece, SIGNAL(replacedBy(Palapeli::Piece*)), SLOT(pieceReplacedBy(Palapeli::Piece*)), Qt::DirectConnection);
piece->beginMove(); piece->beginMove();
} }
return true; return true;
...@@ -99,19 +96,37 @@ bool Palapeli::MovePieceInteractor::startInteraction(const Palapeli::MouseEvent& ...@@ -99,19 +96,37 @@ bool Palapeli::MovePieceInteractor::startInteraction(const Palapeli::MouseEvent&
void Palapeli::MovePieceInteractor::continueInteraction(const Palapeli::MouseEvent& event) void Palapeli::MovePieceInteractor::continueInteraction(const Palapeli::MouseEvent& event)
{ {
m_currentOffset = event.scenePos - m_baseScenePosition;
for (int i = 0; i < m_currentPieces.count(); ++i) 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);
m_currentPieces[i]->doMove(); m_currentPieces[i]->doMove();
} }
} }
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()));
m_currentPieces.removeAt(index);
m_basePositions.removeAt(index);
//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) void Palapeli::MovePieceInteractor::stopInteraction(const Palapeli::MouseEvent& event)
{ {
Q_UNUSED(event) Q_UNUSED(event)
foreach(Palapeli::Piece* piece, m_currentPieces) foreach(Palapeli::Piece* piece, m_currentPieces)
{
disconnect(piece, 0, this, 0);
piece->endMove(); piece->endMove();
m_currentItems.clear(); }
m_currentPieces.clear(); m_currentPieces.clear();
} }
...@@ -334,3 +349,5 @@ bool Palapeli::ToggleConstraintInteractor::startInteraction(const Palapeli::Mous ...@@ -334,3 +349,5 @@ bool Palapeli::ToggleConstraintInteractor::startInteraction(const Palapeli::Mous
} }
//END Palapeli::ToggleConstraintInteractor //END Palapeli::ToggleConstraintInteractor
#include "interactors.moc"
...@@ -30,21 +30,23 @@ namespace Palapeli ...@@ -30,21 +30,23 @@ namespace Palapeli
//This interactor is assigned to LeftButton;NoModifier by default. //This interactor is assigned to LeftButton;NoModifier by default.
//1. When you click on and drag a selected piece, all selected pieces are moved. //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. //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
{ {
Q_OBJECT
public: public:
MovePieceInteractor(QGraphicsView* view); MovePieceInteractor(QGraphicsView* view);
protected: protected:
virtual bool startInteraction(const Palapeli::MouseEvent& event); virtual bool startInteraction(const Palapeli::MouseEvent& event);
virtual void continueInteraction(const Palapeli::MouseEvent& event); virtual void continueInteraction(const Palapeli::MouseEvent& event);
virtual void stopInteraction(const Palapeli::MouseEvent& event); virtual void stopInteraction(const Palapeli::MouseEvent& event);
protected Q_SLOTS:
void pieceReplacedBy(Palapeli::Piece* replacement);
private: private:
Palapeli::Piece* findPieceForItem(QGraphicsItem* mouseInteractingItem) const; Palapeli::Piece* findPieceForItem(QGraphicsItem* mouseInteractingItem) const;
void determineSelectedItems(QGraphicsItem* clickedItem, Palapeli::Piece* clickedPiece); void determineSelectedItems(QGraphicsItem* clickedItem, Palapeli::Piece* clickedPiece);
QList<QGraphicsItem*> m_currentItems; //the item which accepts the events QList<Palapeli::Piece*> m_currentPieces;
QList<Palapeli::Piece*> m_currentPieces; //the piece for this item QPointF m_baseScenePosition, m_currentOffset;
QPointF m_baseScenePosition;
QList<QPointF> m_basePositions; QList<QPointF> m_basePositions;
}; };
......
...@@ -151,7 +151,7 @@ void Palapeli::MergeGroup::createMergedPiece() ...@@ -151,7 +151,7 @@ void Palapeli::MergeGroup::createMergedPiece()
if (piece->isSelected()) if (piece->isSelected())
m_mergedPiece->setSelected(true); m_mergedPiece->setSelected(true);
m_mergedPiece->setZValue(qMax(m_mergedPiece->zValue(), piece->zValue())); 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 m_mergedPiece->rewriteLogicalNeighbors(m_pieces, 0); //0 = these neighbors should be dropped
foreach (Palapeli::Piece* logicalNeighbor, m_mergedPiece->logicalNeighbors()) foreach (Palapeli::Piece* logicalNeighbor, m_mergedPiece->logicalNeighbors())
......
...@@ -165,6 +165,12 @@ void Palapeli::Piece::rewriteLogicalNeighbors(const QList<Palapeli::Piece*>& old ...@@ -165,6 +165,12 @@ void Palapeli::Piece::rewriteLogicalNeighbors(const QList<Palapeli::Piece*>& old
m_logicalNeighbors += newPiece; m_logicalNeighbors += newPiece;
} }
void Palapeli::Piece::announceReplaced(Palapeli::Piece* replacement)
{
emit replacedBy(replacement);
delete this;
}
void Palapeli::Piece::addAtomicSize(const QSize& size) void Palapeli::Piece::addAtomicSize(const QSize& size)
{ {
m_atomicSize = m_atomicSize.expandedTo(size); m_atomicSize = m_atomicSize.expandedTo(size);
......
...@@ -63,8 +63,11 @@ namespace Palapeli ...@@ -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. ///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); 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);
Q_SIGNALS: Q_SIGNALS:
void moved(); void moved();
void replacedBy(Palapeli::Piece* newPiece);
protected: protected:
friend class MovePieceInteractor; friend class MovePieceInteractor;
void beginMove(); 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