File indexing completed on 2025-01-26 03:49:00
0001 /* 0002 * Copyright (C) 1995 Paul Olav Tvete <paul@troll.no> 0003 * Copyright (C) 2000-2009 Stephan Kulow <coolo@kde.org> 0004 * Copyright (C) 2010 Parker Coates <coates@kde.org> 0005 * 0006 * License of original code: 0007 * ------------------------------------------------------------------------- 0008 * Permission to use, copy, modify, and distribute this software and its 0009 * documentation for any purpose and without fee is hereby granted, 0010 * provided that the above copyright notice appear in all copies and that 0011 * both that copyright notice and this permission notice appear in 0012 * supporting documentation. 0013 * 0014 * This file is provided AS IS with no warranties of any kind. The author 0015 * shall have no liability with respect to the infringement of copyrights, 0016 * trade secrets or any patents by this file or any part thereof. In no 0017 * event will the author be liable for any lost revenue or profits or 0018 * other special, indirect and consequential damages. 0019 * ------------------------------------------------------------------------- 0020 * 0021 * License of modifications/additions made after 2009-01-01: 0022 * ------------------------------------------------------------------------- 0023 * This program is free software; you can redistribute it and/or 0024 * modify it under the terms of the GNU General Public License as 0025 * published by the Free Software Foundation; either version 2 of 0026 * the License, or (at your option) any later version. 0027 * 0028 * This program is distributed in the hope that it will be useful, 0029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0031 * GNU General Public License for more details. 0032 * 0033 * You should have received a copy of the GNU General Public License 0034 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0035 * ------------------------------------------------------------------------- 0036 */ 0037 0038 #include "kcardpile.h" 0039 0040 // own 0041 #include "kabstractcarddeck.h" 0042 #include "kcardscene.h" 0043 // Qt 0044 #include <QPainter> 0045 #include <QPropertyAnimation> 0046 // Std 0047 #include <cmath> 0048 0049 class KCardPilePrivate : public QObject 0050 { 0051 Q_OBJECT 0052 0053 Q_PROPERTY(qreal highlightedness READ highlightedness WRITE setHighlightedness) 0054 0055 public: 0056 KCardPilePrivate(KCardPile *q); 0057 0058 void setHighlightedness(qreal highlightedness); 0059 qreal highlightedness() const; 0060 0061 KCardPile *q; 0062 0063 QList<KCard *> cards; 0064 0065 bool autoTurnTop; 0066 bool highlighted; 0067 0068 QSize graphicSize; 0069 QPointF layoutPos; 0070 QPointF spread; 0071 0072 qreal topPadding; 0073 qreal rightPadding; 0074 qreal bottomPadding; 0075 qreal leftPadding; 0076 0077 KCardPile::WidthPolicy widthPolicy; 0078 KCardPile::HeightPolicy heightPolicy; 0079 0080 KCardPile::KeyboardFocusHint selectHint; 0081 KCardPile::KeyboardFocusHint dropHint; 0082 0083 qreal highlightValue; 0084 0085 QPropertyAnimation *fadeAnimation; 0086 }; 0087 0088 KCardPilePrivate::KCardPilePrivate(KCardPile *q) 0089 : QObject(q) 0090 , q(q) 0091 { 0092 } 0093 0094 void KCardPilePrivate::setHighlightedness(qreal highlightedness) 0095 { 0096 highlightValue = highlightedness; 0097 q->update(); 0098 } 0099 0100 qreal KCardPilePrivate::highlightedness() const 0101 { 0102 return highlightValue; 0103 } 0104 0105 KCardPile::KCardPile(KCardScene *cardScene) 0106 : QGraphicsObject() 0107 , d(new KCardPilePrivate(this)) 0108 { 0109 d->autoTurnTop = false; 0110 d->highlighted = false; 0111 d->highlightValue = 0; 0112 d->spread = QPointF(0, 0); 0113 0114 d->topPadding = 0; 0115 d->rightPadding = 0; 0116 d->bottomPadding = 0; 0117 d->leftPadding = 0; 0118 0119 d->widthPolicy = FixedWidth; 0120 d->heightPolicy = FixedHeight; 0121 0122 d->fadeAnimation = new QPropertyAnimation(d, "highlightedness", d); 0123 d->fadeAnimation->setDuration(150); 0124 d->fadeAnimation->setKeyValueAt(0, 0); 0125 d->fadeAnimation->setKeyValueAt(1, 1); 0126 0127 setZValue(0); 0128 QGraphicsItem::setVisible(true); 0129 0130 if (cardScene) 0131 cardScene->addPile(this); 0132 } 0133 0134 KCardPile::~KCardPile() 0135 { 0136 for (KCard *c : std::as_const(d->cards)) 0137 c->setPile(nullptr); 0138 0139 KCardScene *cardScene = dynamic_cast<KCardScene *>(scene()); 0140 if (cardScene) 0141 cardScene->removePile(this); 0142 } 0143 0144 int KCardPile::type() const 0145 { 0146 return KCardPile::Type; 0147 } 0148 0149 QRectF KCardPile::boundingRect() const 0150 { 0151 return QRectF(QPointF(0, 0), d->graphicSize); 0152 } 0153 0154 void KCardPile::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) 0155 { 0156 Q_UNUSED(option); 0157 Q_UNUSED(widget); 0158 0159 paintGraphic(painter, d->highlightValue); 0160 } 0161 0162 QList<KCard *> KCardPile::cards() const 0163 { 0164 return d->cards; 0165 } 0166 0167 int KCardPile::count() const 0168 { 0169 return d->cards.count(); 0170 } 0171 0172 bool KCardPile::isEmpty() const 0173 { 0174 return d->cards.isEmpty(); 0175 } 0176 0177 int KCardPile::indexOf(const KCard *card) const 0178 { 0179 return d->cards.indexOf(const_cast<KCard *>(card)); 0180 } 0181 0182 KCard *KCardPile::at(int index) const 0183 { 0184 if (index < 0 || index >= d->cards.size()) 0185 return nullptr; 0186 return d->cards.at(index); 0187 } 0188 0189 KCard *KCardPile::topCard() const 0190 { 0191 if (d->cards.isEmpty()) 0192 return nullptr; 0193 0194 return d->cards.last(); 0195 } 0196 0197 QList<KCard *> KCardPile::topCards(int depth) const 0198 { 0199 if (depth <= 0) 0200 return QList<KCard *>(); 0201 0202 if (depth > count()) 0203 return d->cards; 0204 0205 return d->cards.mid(count() - depth); 0206 } 0207 0208 QList<KCard *> KCardPile::topCardsDownTo(const KCard *card) const 0209 { 0210 int index = d->cards.indexOf(const_cast<KCard *>(card)); 0211 if (index == -1) 0212 return QList<KCard *>(); 0213 return d->cards.mid(index); 0214 } 0215 0216 void KCardPile::setLayoutPos(QPointF pos) 0217 { 0218 d->layoutPos = pos; 0219 } 0220 0221 void KCardPile::setLayoutPos(qreal x, qreal y) 0222 { 0223 setLayoutPos(QPointF(x, y)); 0224 } 0225 0226 QPointF KCardPile::layoutPos() const 0227 { 0228 return d->layoutPos; 0229 } 0230 0231 void KCardPile::setWidthPolicy(WidthPolicy policy) 0232 { 0233 d->widthPolicy = policy; 0234 } 0235 0236 KCardPile::WidthPolicy KCardPile::widthPolicy() const 0237 { 0238 return d->widthPolicy; 0239 } 0240 0241 void KCardPile::setHeightPolicy(HeightPolicy policy) 0242 { 0243 d->heightPolicy = policy; 0244 } 0245 0246 KCardPile::HeightPolicy KCardPile::heightPolicy() const 0247 { 0248 return d->heightPolicy; 0249 } 0250 0251 void KCardPile::setPadding(qreal topPadding, qreal rightPadding, qreal bottomPadding, qreal leftPadding) 0252 { 0253 setTopPadding(topPadding); 0254 setRightPadding(rightPadding); 0255 setBottomPadding(bottomPadding); 0256 setLeftPadding(leftPadding); 0257 } 0258 0259 void KCardPile::setTopPadding(qreal padding) 0260 { 0261 d->topPadding = padding; 0262 } 0263 0264 qreal KCardPile::topPadding() const 0265 { 0266 return d->topPadding; 0267 } 0268 0269 void KCardPile::setRightPadding(qreal padding) 0270 { 0271 d->rightPadding = padding; 0272 } 0273 0274 qreal KCardPile::rightPadding() const 0275 { 0276 return d->rightPadding; 0277 } 0278 0279 void KCardPile::setBottomPadding(qreal padding) 0280 { 0281 d->bottomPadding = padding; 0282 } 0283 0284 qreal KCardPile::bottomPadding() const 0285 { 0286 return d->bottomPadding; 0287 } 0288 0289 void KCardPile::setLeftPadding(qreal padding) 0290 { 0291 d->leftPadding = padding; 0292 } 0293 0294 qreal KCardPile::leftPadding() const 0295 { 0296 return d->leftPadding; 0297 } 0298 0299 void KCardPile::setSpread(QPointF spread) 0300 { 0301 d->spread = spread; 0302 } 0303 0304 void KCardPile::setSpread(qreal width, qreal height) 0305 { 0306 setSpread(QPointF(width, height)); 0307 } 0308 0309 QPointF KCardPile::spread() const 0310 { 0311 return d->spread; 0312 } 0313 0314 void KCardPile::setAutoTurnTop(bool autoTurnTop) 0315 { 0316 d->autoTurnTop = autoTurnTop; 0317 } 0318 0319 bool KCardPile::autoTurnTop() const 0320 { 0321 return d->autoTurnTop; 0322 } 0323 0324 void KCardPile::setKeyboardSelectHint(KeyboardFocusHint hint) 0325 { 0326 d->selectHint = hint; 0327 } 0328 0329 KCardPile::KeyboardFocusHint KCardPile::keyboardSelectHint() const 0330 { 0331 return d->selectHint; 0332 } 0333 0334 void KCardPile::setKeyboardDropHint(KeyboardFocusHint hint) 0335 { 0336 d->dropHint = hint; 0337 } 0338 0339 KCardPile::KeyboardFocusHint KCardPile::keyboardDropHint() const 0340 { 0341 return d->dropHint; 0342 } 0343 0344 void KCardPile::setVisible(bool visible) 0345 { 0346 if (visible != isVisible()) { 0347 QGraphicsItem::setVisible(visible); 0348 for (KCard *c : std::as_const(d->cards)) 0349 c->setVisible(visible); 0350 } 0351 } 0352 0353 void KCardPile::setHighlighted(bool highlighted) 0354 { 0355 if (highlighted != d->highlighted) { 0356 d->highlighted = highlighted; 0357 d->fadeAnimation->setDirection(highlighted ? QAbstractAnimation::Forward : QAbstractAnimation::Backward); 0358 if (d->fadeAnimation->state() != QAbstractAnimation::Running) 0359 d->fadeAnimation->start(); 0360 } 0361 } 0362 0363 bool KCardPile::isHighlighted() const 0364 { 0365 return d->highlighted; 0366 } 0367 0368 void KCardPile::add(KCard *card) 0369 { 0370 insert(d->cards.size(), card); 0371 } 0372 0373 void KCardPile::insert(int index, KCard *card) 0374 { 0375 if (card->scene() != scene()) 0376 scene()->addItem(card); 0377 0378 if (card->pile()) 0379 card->pile()->remove(card); 0380 0381 card->setPile(this); 0382 card->setVisible(isVisible()); 0383 0384 d->cards.insert(index, card); 0385 } 0386 0387 void KCardPile::remove(KCard *card) 0388 { 0389 Q_ASSERT(d->cards.contains(card)); 0390 d->cards.removeAll(card); 0391 card->setPile(nullptr); 0392 } 0393 0394 void KCardPile::clear() 0395 { 0396 const auto currentCards = d->cards; 0397 for (KCard *card : currentCards) 0398 remove(card); 0399 Q_ASSERT(d->cards.isEmpty()); 0400 } 0401 0402 void KCardPile::swapCards(int index1, int index2) 0403 { 0404 if (index1 == index2) 0405 return; 0406 0407 KCard *temp = d->cards.at(index1); 0408 d->cards[index1] = d->cards.at(index2); 0409 d->cards[index2] = temp; 0410 } 0411 0412 void KCardPile::paintGraphic(QPainter *painter, qreal highlightedness) 0413 { 0414 int penWidth = boundingRect().width() / 40; 0415 int topLeft = penWidth / 2; 0416 int bottomRight = topLeft - penWidth; 0417 painter->setPen(QPen(Qt::black, penWidth)); 0418 painter->setBrush(QColor(0, 0, 0, 64 * highlightedness)); 0419 painter->drawRect(boundingRect().adjusted(topLeft, topLeft, bottomRight, bottomRight)); 0420 } 0421 0422 QList<QPointF> KCardPile::cardPositions() const 0423 { 0424 QList<QPointF> positions; 0425 for (int i = 0; i < count(); ++i) 0426 positions << i * spread(); 0427 return positions; 0428 } 0429 0430 void KCardPile::setGraphicSize(QSize size) 0431 { 0432 if (size != d->graphicSize) { 0433 prepareGeometryChange(); 0434 d->graphicSize = size; 0435 update(); 0436 } 0437 } 0438 0439 #include "kcardpile.moc" 0440 #include "moc_kcardpile.cpp"