1 #include "cardzone.h"
2 
3 #include "carditem.h"
4 #include "pb/command_move_card.pb.h"
5 #include "pb/serverinfo_user.pb.h"
6 #include "player.h"
7 #include "zoneviewzone.h"
8 
9 #include <QAction>
10 #include <QDebug>
11 #include <QGraphicsSceneMouseEvent>
12 #include <QMenu>
13 
CardZone(Player * _p,const QString & _name,bool _hasCardAttr,bool _isShufflable,bool _contentsKnown,QGraphicsItem * parent,bool _isView)14 CardZone::CardZone(Player *_p,
15                    const QString &_name,
16                    bool _hasCardAttr,
17                    bool _isShufflable,
18                    bool _contentsKnown,
19                    QGraphicsItem *parent,
20                    bool _isView)
21     : AbstractGraphicsItem(parent), player(_p), name(_name), cards(_contentsKnown), view(NULL), menu(NULL),
22       doubleClickAction(0), hasCardAttr(_hasCardAttr), isShufflable(_isShufflable), isView(_isView)
23 {
24     if (!isView)
25         player->addZone(this);
26 }
27 
~CardZone()28 CardZone::~CardZone()
29 {
30     qDebug() << "CardZone destructor: " << name;
31     delete view;
32     clearContents();
33 }
34 
retranslateUi()35 void CardZone::retranslateUi()
36 {
37     for (int i = 0; i < cards.size(); ++i)
38         cards[i]->retranslateUi();
39 }
40 
clearContents()41 void CardZone::clearContents()
42 {
43     for (int i = 0; i < cards.size(); i++) {
44         // If an incorrectly implemented server doesn't return attached cards to whom they belong before dropping a
45         // player, we have to return them to avoid a crash.
46         const QList<CardItem *> &attachedCards = cards[i]->getAttachedCards();
47         for (auto attachedCard : attachedCards)
48             attachedCard->setParentItem(attachedCard->getZone());
49 
50         player->deleteCard(cards.at(i));
51     }
52     cards.clear();
53     emit cardCountChanged();
54 }
55 
getTranslatedName(bool theirOwn,GrammaticalCase gc) const56 QString CardZone::getTranslatedName(bool theirOwn, GrammaticalCase gc) const
57 {
58     QString ownerName = player->getName();
59     if (name == "hand")
60         return (theirOwn ? tr("their hand", "nominative") : tr("%1's hand", "nominative").arg(ownerName));
61     else if (name == "deck")
62         switch (gc) {
63             case CaseLookAtZone:
64                 return (theirOwn ? tr("their library", "look at zone")
65                                  : tr("%1's library", "look at zone").arg(ownerName));
66             case CaseTopCardsOfZone:
67                 return (theirOwn ? tr("of their library", "top cards of zone,")
68                                  : tr("of %1's library", "top cards of zone").arg(ownerName));
69             case CaseRevealZone:
70                 return (theirOwn ? tr("their library", "reveal zone")
71                                  : tr("%1's library", "reveal zone").arg(ownerName));
72             case CaseShuffleZone:
73                 return (theirOwn ? tr("their library", "shuffle") : tr("%1's library", "shuffle").arg(ownerName));
74             default:
75                 return (theirOwn ? tr("their library", "nominative") : tr("%1's library", "nominative").arg(ownerName));
76         }
77     else if (name == "grave")
78         return (theirOwn ? tr("their graveyard", "nominative") : tr("%1's graveyard", "nominative").arg(ownerName));
79     else if (name == "rfg")
80         return (theirOwn ? tr("their exile", "nominative") : tr("%1's exile", "nominative").arg(ownerName));
81     else if (name == "sb")
82         switch (gc) {
83             case CaseLookAtZone:
84                 return (theirOwn ? tr("their sideboard", "look at zone")
85                                  : tr("%1's sideboard", "look at zone").arg(ownerName));
86             case CaseNominative:
87                 return (theirOwn ? tr("their sideboard", "nominative")
88                                  : tr("%1's sideboard", "nominative").arg(ownerName));
89             default:
90                 break;
91         }
92     return QString();
93 }
94 
mouseDoubleClickEvent(QGraphicsSceneMouseEvent *)95 void CardZone::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * /*event*/)
96 {
97     if (doubleClickAction)
98         doubleClickAction->trigger();
99 }
100 
showContextMenu(const QPoint & screenPos)101 bool CardZone::showContextMenu(const QPoint &screenPos)
102 {
103     if (menu) {
104         menu->exec(screenPos);
105         return true;
106     }
107     return false;
108 }
109 
mousePressEvent(QGraphicsSceneMouseEvent * event)110 void CardZone::mousePressEvent(QGraphicsSceneMouseEvent *event)
111 {
112     if (event->button() == Qt::RightButton) {
113         if (showContextMenu(event->screenPos()))
114             event->accept();
115         else
116             event->ignore();
117     } else
118         event->ignore();
119 }
120 
addCard(CardItem * card,bool reorganize,int x,int y)121 void CardZone::addCard(CardItem *card, bool reorganize, int x, int y)
122 {
123     if (view)
124         if ((x <= view->getCards().size()) || (view->getNumberCards() == -1))
125             view->addCard(new CardItem(player, card->getName(), card->getId()), reorganize, x, y);
126 
127     card->setZone(this);
128     addCardImpl(card, x, y);
129 
130     if (reorganize)
131         reorganizeCards();
132 
133     emit cardCountChanged();
134 }
135 
getCard(int cardId,const QString & cardName)136 CardItem *CardZone::getCard(int cardId, const QString &cardName)
137 {
138     CardItem *c = cards.findCard(cardId, false);
139     if (!c) {
140         qDebug() << "CardZone::getCard: card id=" << cardId << "not found";
141         return 0;
142     }
143     // If the card's id is -1, this zone is invisible,
144     // so we need to give the card an id and a name as it comes out.
145     // It can be assumed that in an invisible zone, all cards are equal.
146     if ((c->getId() == -1) || (c->getName().isEmpty())) {
147         c->setId(cardId);
148         c->setName(cardName);
149     }
150     return c;
151 }
152 
takeCard(int position,int cardId,bool)153 CardItem *CardZone::takeCard(int position, int cardId, bool /*canResize*/)
154 {
155     if (position == -1) {
156         // position == -1 means either that the zone is indexed by card id
157         // or that it doesn't matter which card you take.
158         for (int i = 0; i < cards.size(); ++i)
159             if (cards[i]->getId() == cardId) {
160                 position = i;
161                 break;
162             }
163         if (position == -1)
164             position = 0;
165     }
166     if (position >= cards.size())
167         return 0;
168 
169     CardItem *c = cards.takeAt(position);
170 
171     if (view)
172         view->removeCard(position);
173 
174     c->setId(cardId);
175 
176     reorganizeCards();
177     emit cardCountChanged();
178     return c;
179 }
180 
removeCard(CardItem * card)181 void CardZone::removeCard(CardItem *card)
182 {
183     cards.removeAt(cards.indexOf(card));
184     reorganizeCards();
185     emit cardCountChanged();
186     player->deleteCard(card);
187 }
188 
moveAllToZone()189 void CardZone::moveAllToZone()
190 {
191     QList<QVariant> data = static_cast<QAction *>(sender())->data().toList();
192     QString targetZone = data[0].toString();
193     int targetX = data[1].toInt();
194 
195     Command_MoveCard cmd;
196     cmd.set_start_zone(getName().toStdString());
197     cmd.set_target_player_id(player->getId());
198     cmd.set_target_zone(targetZone.toStdString());
199     cmd.set_x(targetX);
200 
201     for (int i = 0; i < cards.size(); ++i)
202         cmd.mutable_cards_to_move()->add_card()->set_card_id(cards[i]->getId());
203 
204     player->sendGameCommand(cmd);
205 }
206 
closestGridPoint(const QPointF & point)207 QPointF CardZone::closestGridPoint(const QPointF &point)
208 {
209     return point;
210 }
211