RetroShare/plugins/qsolocards_plugin/CardStack.h

239 lines
10 KiB
C
Raw Normal View History

/*
QSoloCards is a collection of Solitaire card games written using Qt
Copyright (C) 2009 Steve Moore
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CARDSTACK_H
#define CARDSTACK_H
#include <QtCore/QObject>
#include <QtGui/QGraphicsPixmapItem>
#include "CardMoveRecord.h"
#include "FlipAnimation.h"
#include "DragCardStack.h"
#include <map>
#include <string>
class CardStack;
typedef std::map<std::string,CardStack *> CardStackMap;
class CardStack: public QObject,public QGraphicsPixmapItem
{
Q_OBJECT
public:
enum ProcessCardMoveRecordType
{
UndoMove=0,
RedoMove=1
};
enum
{
HintHighlightNoCards=-2
};
CardStack();
virtual ~CardStack();
inline const std::string stackName()const{return m_stackName.toStdString();}
inline bool isFlipAniRunning()const {return m_flipAni.isAniRunning();}
bool allCardsFaceUp()const;
// top is in this case the last card in the stack. bottom is index 0
bool cardsAscendingTopToBottom()const;
bool cardsDecendingTopToBottom()const;
void setTopCardUp(bool faceUp=true);
bool flipCard(int index,bool aniIfEnabled=true);
bool flipCard(int index,CardMoveRecord & moveRecord,bool aniIfEnabled=true);
inline void setAutoTopCardUp(bool autoFaceUp=true){this->m_autoFaceUp=autoFaceUp;}
inline bool isAutoTopCardUp()const {return m_autoFaceUp;}
inline bool isHighlighted() const {return m_highlighted;}
inline void setHighlighted(bool state=true){m_highlighted=state;}
inline int hintHighlightIndex() const {return m_hintHighlightIndex;}
inline bool showRedealCircle(){return m_showRedealCircle;}
inline void setShowRedealCircle(bool state=true){m_showRedealCircle=state;}
void addCard(const PlayingCard & newCard);
void addCards(const PlayingCardVector & cardVector);
void addCard(const PlayingCard & newCard,CardMoveRecord & moveRecord,bool justUpdateRec=false);
void addCards(const PlayingCardVector & cardVector,CardMoveRecord & moveRecord,bool justUpdateRec=false);
// pull the top card off of the stack
PlayingCard removeTopCard();
PlayingCard removeTopCard(CardMoveRecord & moveRecord);
// the cardVector contains the cards that were removed if the index is valid.
bool removeCardsStartingAt(unsigned int index,PlayingCardVector & removedCards);
bool removeCardsStartingAt(unsigned int index,PlayingCardVector & removedCards,
CardMoveRecord & moveRecord,bool justUpdateRec=false);
void removeAllCards();
inline bool isEmpty() const {return m_cardVector.empty();}
const PlayingCardVector & getCardVector()const{return m_cardVector;}
virtual bool canAddCards(const PlayingCardVector &){return false;}
// this function will return the cards at the end of the stack that can be moved.
// the function canMoveCards that can be overridden by subclasses controls the
// cards that can be moved. This function can also be overridden if something other
// than the default of just cards at the end of the stack is desired.
//
// the cards that can be moved will be added to the end of the card vector passed in
// the start index of the cards is also set if the function returns true
// the function returns true if it has cards that can be moved or false if it has none.
// this function has been added to aid in creating hints for moving cards
virtual bool getMovableCards(PlayingCardVector &, unsigned int & index) const;
// this function gets the point in the scene that a card would be added to this stack.
inline virtual QPointF getGlobalCardAddPt() const {return mapToScene(QPointF(0,0));};
inline virtual QPointF getGlobalLastCardPt() const {return mapToScene(QPointF(0,0));};
inline virtual QPointF getGlobalCardPt(int index) const {Q_UNUSED(index);return mapToScene(QPointF(0,0));};
// this function will update the bounding rectangle for the cards. And update the
// pixmap for the stack. The default implementation implementation just calls
// getStackPixmap. Subclasses may want to override this version to record bounding
// rectangles for cards and then call the base class.
virtual void updateStack();
// this function returns a pointer to a pixmap of the stack. The pixmap is the responsiblity
// of the caller to free. This function can be overridden in subclasses to create
// different look for the stack when drawn or cards from it are dragged to a different
// stack.
virtual QPixmap * getStackPixmap(const PlayingCardVector & cardVector,
bool highlighted=false,
int hintHighlightIndex=-1);
// override in subclasses for scoring per stack if desired.
virtual int score() const{return 0;}
///////////////////////////////////////////////////////////////////////////////
// public static functions
///////////////////////////////////////////////////////////////////////////////
static void updateAllStacks();
static void clearAllStacks();
static inline void lockUserInteration(bool lock=true){m_lockUserInteraction=lock;}
static inline bool isUserInteractionLocked() {return m_lockUserInteraction;}
static CardStack * getStackByName(const std::string & stackName);
static bool isCardStack(QGraphicsItem *);
static void processCardMoveRecord(ProcessCardMoveRecordType type,
CardMoveRecord moveRecord);
// this is a helper function that will show a move hint by highlighting the src widget starting with the
// srcCardIndex in the stack for one second. And then highlighting the last card in the dest stack for
// one second.
static void showHint(CardStack * pSrcWidget,unsigned int srcCardIndex,CardStack * pDstWidget);
public slots:
// the slotDelayedHintHighlight() allows you to call slotHintHighlight() for the src stack
// and slotDelayedHintHighlight() for the destination stack at the same time.
void slotDelayedHintHighlight(); // show a hint highlight delayed
void slotHintHighlight(int index=-1); // show the highlight hint immediately it will timeout in one second
void slotHintHighlightComplete();
void slotFlipComplete(CardStack * pSrc);
void slotDragCardsMoved(const CardMoveRecord & moveRecord);
signals:
// when a card is clicked this signal is emitted
void cardClicked(CardStack * pCardStackWidget,unsigned int index);
// This signal is emitted when there are no cards
// in the stack and the pad area where the first card would be is clicked
void padClicked(CardStack * pCardStackWidget);
// this signal indicates that cards where clicked, but they are also movable
// and it includes a move record of what would happen if the card was moved. This
// can be used to make the move by calling processCardMoveRecord. If the move is accepted
// the add move can be added to the move record. And then processCardMoveRecord can be
// called to perform the move. The index is the index of the card that was clicked.
void movableCardsClicked(CardStack * pCardStack,
const PlayingCardVector & cardVector,
const CardMoveRecord &);
// the card record will contain all changes made by the drag and
// drop. The remove from one stack. The flip of the card if in
// autoCardUp mode and the card under the remove cards was face
// down. And then the add of the cards to the other stack.
// The signal will be emitted by the stack that started the drag
// operation.
void cardsMovedByDragDrop(const CardMoveRecord &);
protected:
int m_hintHighlightIndex;
// subclasses should reimplement canMoveCard and canAddCards
// for the rules of whatever game they are implementing.
virtual bool canMoveCard(unsigned int index) const{Q_UNUSED(index); return false;}
virtual bool getCardIndex(const QPointF & pos,unsigned int & index);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
virtual void hoverMoveEvent ( QGraphicsSceneHoverEvent * event );
private:
QString m_stackName;
PlayingCardVector m_cardVector;
bool m_highlighted;
bool m_showRedealCircle;
bool m_autoFaceUp;
bool m_mouseMoved; // set to true if the mouse is moved while the button is down
// using this to determine a mouse click on the CardStack. The
// mouse should not move.
QPointF m_dragStartPos; // used to figure out when the mouse has been moved enough to
// start a drag operation
FlipAnimation m_flipAni;
DragCardStack m_dragStack;
///////////////////////////////////////////////////////////////////////////////
// static variables
///////////////////////////////////////////////////////////////////////////////
static CardStackMap m_cardStackMap; // this is a map that contains all of the current instances
// of CardStack. They are mapped by a unique name to a
// pointer to the instance.
static bool m_lockUserInteraction;
};
#endif