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