1 #include "zoneviewzone.h"
2 
3 #include "carddatabase.h"
4 #include "carddragitem.h"
5 #include "carditem.h"
6 #include "pb/command_dump_zone.pb.h"
7 #include "pb/command_move_card.pb.h"
8 #include "pb/response_dump_zone.pb.h"
9 #include "pb/serverinfo_card.pb.h"
10 #include "pending_command.h"
11 #include "player.h"
12 
13 #include <QBrush>
14 #include <QDebug>
15 #include <QGraphicsSceneWheelEvent>
16 #include <QPainter>
17 #include <math.h>
18 
ZoneViewZone(Player * _p,CardZone * _origZone,int _numberCards,bool _revealZone,bool _writeableRevealZone,QGraphicsItem * parent)19 ZoneViewZone::ZoneViewZone(Player *_p,
20                            CardZone *_origZone,
21                            int _numberCards,
22                            bool _revealZone,
23                            bool _writeableRevealZone,
24                            QGraphicsItem *parent)
25     : SelectZone(_p, _origZone->getName(), false, false, true, parent, true), bRect(QRectF()), minRows(0),
26       numberCards(_numberCards), origZone(_origZone), revealZone(_revealZone),
27       writeableRevealZone(_writeableRevealZone), sortByName(false), sortByType(false)
28 {
29     if (!(revealZone && !writeableRevealZone))
30         origZone->setView(this);
31 }
32 
~ZoneViewZone()33 ZoneViewZone::~ZoneViewZone()
34 {
35     emit beingDeleted();
36     qDebug("ZoneViewZone destructor");
37     if (!(revealZone && !writeableRevealZone))
38         origZone->setView(NULL);
39 }
40 
boundingRect() const41 QRectF ZoneViewZone::boundingRect() const
42 {
43     return bRect;
44 }
45 
paint(QPainter * painter,const QStyleOptionGraphicsItem *,QWidget *)46 void ZoneViewZone::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
47 {
48     QBrush windowBrush(QColor(240, 240, 240));
49     windowBrush.setColor(windowBrush.color().darker(150));
50     painter->fillRect(boundingRect(), windowBrush);
51 }
52 
initializeCards(const QList<const ServerInfo_Card * > & cardList)53 void ZoneViewZone::initializeCards(const QList<const ServerInfo_Card *> &cardList)
54 {
55     if (!cardList.isEmpty()) {
56         for (int i = 0; i < cardList.size(); ++i)
57             addCard(
58                 new CardItem(player, QString::fromStdString(cardList[i]->name()), cardList[i]->id(), revealZone, this),
59                 false, i);
60         reorganizeCards();
61     } else if (!origZone->contentsKnown()) {
62         Command_DumpZone cmd;
63         cmd.set_player_id(player->getId());
64         cmd.set_zone_name(name.toStdString());
65         cmd.set_number_cards(numberCards);
66 
67         PendingCommand *pend = player->prepareGameCommand(cmd);
68         connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
69                 SLOT(zoneDumpReceived(const Response &)));
70         player->sendGameCommand(pend);
71     } else {
72         const CardList &c = origZone->getCards();
73         int number = numberCards == -1 ? c.size() : (numberCards < c.size() ? numberCards : c.size());
74         for (int i = 0; i < number; i++) {
75             CardItem *card = c.at(i);
76             addCard(new CardItem(player, card->getName(), card->getId(), revealZone, this), false, i);
77         }
78         reorganizeCards();
79     }
80 }
81 
zoneDumpReceived(const Response & r)82 void ZoneViewZone::zoneDumpReceived(const Response &r)
83 {
84     const Response_DumpZone &resp = r.GetExtension(Response_DumpZone::ext);
85     const int respCardListSize = resp.zone_info().card_list_size();
86     for (int i = 0; i < respCardListSize; ++i) {
87         const ServerInfo_Card &cardInfo = resp.zone_info().card_list(i);
88         CardItem *card = new CardItem(player, QString::fromStdString(cardInfo.name()), cardInfo.id(), revealZone, this);
89         addCard(card, false, i);
90     }
91 
92     reorganizeCards();
93 }
94 
95 // Because of boundingRect(), this function must not be called before the zone was added to a scene.
reorganizeCards()96 void ZoneViewZone::reorganizeCards()
97 {
98     int cardCount = cards.size();
99     if (!origZone->contentsKnown())
100         for (int i = 0; i < cardCount; ++i)
101             cards[i]->setId(i);
102 
103     int cols = floor(sqrt((double)cardCount / 2));
104     if (cols > 7)
105         cols = 7;
106     int rows = ceil((double)cardCount / cols);
107     if (rows < 1)
108         rows = 1;
109     if (minRows == 0)
110         minRows = rows;
111     else if (rows < minRows) {
112         rows = minRows;
113         cols = ceil((double)cardCount / minRows);
114     }
115     if (cols < 2)
116         cols = 2;
117 
118     qDebug() << "reorganizeCards: rows=" << rows << "cols=" << cols;
119 
120     CardList cardsToDisplay(cards);
121     if (sortByName || sortByType)
122         cardsToDisplay.sort((sortByName ? CardList::SortByName : 0) | (sortByType ? CardList::SortByType : 0));
123 
124     int typeColumn = 0;
125     int longestRow = 0;
126     if (pileView && sortByType) { // we need sort by type enabled for the feature to work
127         int typeRow = 0;
128         QString lastCardType;
129         for (int i = 0; i < cardCount; i++) {
130             CardItem *c = cardsToDisplay.at(i);
131             QString cardType = c->getInfo() ? c->getInfo()->getMainCardType() : "";
132 
133             if (i) { // if not the first card
134                 if (cardType == lastCardType)
135                     typeRow++; // add below current card
136                 else {         // if no match then move card to next column
137                     typeColumn++;
138                     typeRow = 0;
139                 }
140             }
141 
142             lastCardType = cardType;
143             qreal x = 7 + (typeColumn * CARD_WIDTH);
144             qreal y = typeRow * CARD_HEIGHT / 3;
145             c->setPos(x + 5, y + 5);
146             c->setRealZValue(i);
147             longestRow = qMax(typeRow, longestRow);
148         }
149     } else {
150         for (int i = 0; i < cardCount; i++) {
151             CardItem *c = cardsToDisplay.at(i);
152             qreal x = 7 + ((i / rows) * CARD_WIDTH);
153             qreal y = (i % rows) * CARD_HEIGHT / 3;
154             c->setPos(x + 5, y + 5);
155             c->setRealZValue(i);
156         }
157     }
158 
159     qreal aleft = 0;
160     qreal atop = 0;
161     qreal awidth = (pileView && sortByType) ? qMax(typeColumn + 1, 3) * CARD_WIDTH + (CARD_WIDTH / 2)
162                                             : qMax(cols, 1) * CARD_WIDTH + (CARD_WIDTH / 2);
163     qreal aheight = (pileView && sortByType) ? (longestRow * CARD_HEIGHT) / 3 + CARD_HEIGHT * 1.3
164                                              : (rows * CARD_HEIGHT) / 3 + CARD_HEIGHT * 1.3;
165     optimumRect = QRectF(aleft, atop, awidth, aheight);
166 
167     updateGeometry();
168     emit optimumRectChanged();
169 }
170 
setSortByName(int _sortByName)171 void ZoneViewZone::setSortByName(int _sortByName)
172 {
173     sortByName = _sortByName;
174     reorganizeCards();
175 }
176 
setSortByType(int _sortByType)177 void ZoneViewZone::setSortByType(int _sortByType)
178 {
179     sortByType = _sortByType;
180     if (!sortByType)
181         pileView = false;
182     reorganizeCards();
183 }
184 
setPileView(int _pileView)185 void ZoneViewZone::setPileView(int _pileView)
186 {
187     pileView = _pileView;
188     reorganizeCards();
189 }
190 
addCardImpl(CardItem * card,int x,int)191 void ZoneViewZone::addCardImpl(CardItem *card, int x, int /*y*/)
192 {
193     cards.insert(x, card);
194     card->setParentItem(this);
195     card->update();
196     reorganizeCards();
197 }
198 
handleDropEvent(const QList<CardDragItem * > & dragItems,CardZone * startZone,const QPoint &)199 void ZoneViewZone::handleDropEvent(const QList<CardDragItem *> &dragItems,
200                                    CardZone *startZone,
201                                    const QPoint & /*dropPoint*/)
202 {
203     Command_MoveCard cmd;
204     cmd.set_start_player_id(startZone->getPlayer()->getId());
205     cmd.set_start_zone(startZone->getName().toStdString());
206     cmd.set_target_player_id(player->getId());
207     cmd.set_target_zone(getName().toStdString());
208     cmd.set_x(0);
209     cmd.set_y(0);
210 
211     for (int i = 0; i < dragItems.size(); ++i)
212         cmd.mutable_cards_to_move()->add_card()->set_card_id(dragItems[i]->getId());
213 
214     player->sendGameCommand(cmd);
215 }
216 
removeCard(int position)217 void ZoneViewZone::removeCard(int position)
218 {
219     if (position >= cards.size())
220         return;
221 
222     CardItem *card = cards.takeAt(position);
223     card->deleteLater();
224     reorganizeCards();
225 }
226 
setGeometry(const QRectF & rect)227 void ZoneViewZone::setGeometry(const QRectF &rect)
228 {
229     prepareGeometryChange();
230     setPos(rect.x(), rect.y());
231     bRect = QRectF(0, 0, rect.width(), rect.height());
232 }
233 
sizeHint(Qt::SizeHint,const QSizeF &) const234 QSizeF ZoneViewZone::sizeHint(Qt::SizeHint /*which*/, const QSizeF & /*constraint*/) const
235 {
236     return optimumRect.size();
237 }
238 
setWriteableRevealZone(bool _writeableRevealZone)239 void ZoneViewZone::setWriteableRevealZone(bool _writeableRevealZone)
240 {
241     if (writeableRevealZone && !_writeableRevealZone)
242         origZone->setView(this);
243     else if (!writeableRevealZone && _writeableRevealZone)
244         origZone->setView(NULL);
245 
246     writeableRevealZone = _writeableRevealZone;
247 }
248 
wheelEvent(QGraphicsSceneWheelEvent * event)249 void ZoneViewZone::wheelEvent(QGraphicsSceneWheelEvent *event)
250 {
251     emit wheelEventReceived(event);
252 }
253