Merge branch 'master' into disabledisabledartcrops

This commit is contained in:
ebbit1q 2026-03-04 00:18:51 +01:00 committed by GitHub
commit ceeedd32b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 156 additions and 79 deletions

View file

@ -1,9 +1,12 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: 💬 Discord Community (Get help with server issues, e.g. Login) - name: 💬 Discord Community (Get help with server issues, e.g. Login)
url: https://discord.gg/3Z9yzmA url: https://discord.com/invite/3Z9yzmA
about: Need help with using the client? Want to find some games? Try the Discord server! about: Need help with using the client? Want to find some games? Try the Discord server!
- name: 🌐 Translations (Help improve the localization of the app) - name: 🌐 Translations (Help improve the localization of the app)
url: https://explore.transifex.com/cockatrice/cockatrice/ url: https://explore.transifex.com/cockatrice/cockatrice/
# it is not possible to add a link to the wiki to this description # it is not possible to add a link to the wiki to this description
about: For more information and guidance check our Translation FAQ on our wiki! about: For more information and guidance check our Translation FAQ on our wiki!
- name: 📖 Code Documentation
url: https://cockatrice.github.io/docs/
about:

View file

@ -212,7 +212,7 @@ jobs:
- name: Upload artifact - name: Upload artifact
id: upload_artifact id: upload_artifact
if: matrix.package != 'skip' if: matrix.package != 'skip'
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v7
with: with:
name: ${{matrix.distro}}${{matrix.version}}-package name: ${{matrix.distro}}${{matrix.version}}-package
path: ${{steps.build.outputs.path}} path: ${{steps.build.outputs.path}}
@ -232,7 +232,7 @@ jobs:
- name: Attest binary provenance - name: Attest binary provenance
id: attestation id: attestation
if: steps.upload_release.outcome == 'success' if: steps.upload_release.outcome == 'success'
uses: actions/attest-build-provenance@v3 uses: actions/attest-build-provenance@v4
with: with:
subject-name: ${{steps.build.outputs.name}} subject-name: ${{steps.build.outputs.name}}
subject-path: ${{steps.build.outputs.path}} subject-path: ${{steps.build.outputs.path}}
@ -499,7 +499,7 @@ jobs:
- name: Upload artifact - name: Upload artifact
id: upload_artifact id: upload_artifact
if: matrix.make_package if: matrix.make_package
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v7
with: with:
name: ${{matrix.artifact_name}} name: ${{matrix.artifact_name}}
path: ${{steps.build.outputs.path}} path: ${{steps.build.outputs.path}}
@ -507,7 +507,7 @@ jobs:
- name: Upload PDBs (Program Databases) - name: Upload PDBs (Program Databases)
if: matrix.os == 'Windows' if: matrix.os == 'Windows'
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v7
with: with:
name: Windows${{matrix.target}}-PDBs name: Windows${{matrix.target}}-PDBs
path: | path: |
@ -530,7 +530,7 @@ jobs:
- name: Attest binary provenance - name: Attest binary provenance
id: attestation id: attestation
if: steps.upload_release.outcome == 'success' if: steps.upload_release.outcome == 'success'
uses: actions/attest-build-provenance@v3 uses: actions/attest-build-provenance@v4
with: with:
subject-name: ${{steps.build.outputs.name}} subject-name: ${{steps.build.outputs.name}}
subject-path: ${{steps.build.outputs.path}} subject-path: ${{steps.build.outputs.path}}

View file

@ -13,9 +13,10 @@
CardDragItem::CardDragItem(CardItem *_item, CardDragItem::CardDragItem(CardItem *_item,
int _id, int _id,
const QPointF &_hotSpot, const QPointF &_hotSpot,
bool _faceDown, bool _forceFaceDown,
AbstractCardDragItem *parentDrag) AbstractCardDragItem *parentDrag)
: AbstractCardDragItem(_item, _hotSpot, parentDrag), id(_id), faceDown(_faceDown), occupied(false), currentZone(0) : AbstractCardDragItem(_item, _hotSpot, parentDrag), id(_id), forceFaceDown(_forceFaceDown), occupied(false),
currentZone(0)
{ {
} }

View file

@ -16,7 +16,7 @@ class CardDragItem : public AbstractCardDragItem
Q_OBJECT Q_OBJECT
private: private:
int id; int id;
bool faceDown; bool forceFaceDown;
bool occupied; bool occupied;
CardZone *currentZone; CardZone *currentZone;
@ -24,15 +24,15 @@ public:
CardDragItem(CardItem *_item, CardDragItem(CardItem *_item,
int _id, int _id,
const QPointF &_hotSpot, const QPointF &_hotSpot,
bool _faceDown, bool _forceFaceDown,
AbstractCardDragItem *parentDrag = 0); AbstractCardDragItem *parentDrag = 0);
int getId() const int getId() const
{ {
return id; return id;
} }
bool getFaceDown() const bool isForceFaceDown() const
{ {
return faceDown; return forceFaceDown;
} }
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void updatePosition(const QPointF &cursorScenePos) override; void updatePosition(const QPointF &cursorScenePos) override;

View file

@ -212,10 +212,12 @@ void CardItem::setAttachedTo(CardItem *_attachedTo)
} }
} }
/**
* @brief Resets the fields that should be reset after a zone transition
*/
void CardItem::resetState(bool keepAnnotations) void CardItem::resetState(bool keepAnnotations)
{ {
attacking = false; attacking = false;
facedown = false;
counters.clear(); counters.clear();
pt.clear(); pt.clear();
if (!keepAnnotations) { if (!keepAnnotations) {
@ -251,10 +253,10 @@ void CardItem::processCardInfo(const ServerInfo_Card &_info)
setDoesntUntap(_info.doesnt_untap()); setDoesntUntap(_info.doesnt_untap());
} }
CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown) CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool forceFaceDown)
{ {
deleteDragItem(); deleteDragItem();
dragItem = new CardDragItem(this, _id, _pos, faceDown); dragItem = new CardDragItem(this, _id, _pos, forceFaceDown);
dragItem->setVisible(false); dragItem->setVisible(false);
scene()->addItem(dragItem); scene()->addItem(dragItem);
dragItem->updatePosition(_scenePos); dragItem->updatePosition(_scenePos);
@ -352,7 +354,7 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
// Use the buttonDownPos to align the hot spot with the position when // Use the buttonDownPos to align the hot spot with the position when
// the user originally clicked // the user originally clicked
createDragItem(id, event->buttonDownPos(Qt::LeftButton), event->scenePos(), facedown || forceFaceDown); createDragItem(id, event->buttonDownPos(Qt::LeftButton), event->scenePos(), forceFaceDown);
dragItem->grabMouse(); dragItem->grabMouse();
int childIndex = 0; int childIndex = 0;
@ -366,8 +368,7 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
childPos = card->pos() - pos(); childPos = card->pos() - pos();
else else
childPos = QPointF(childIndex * CARD_WIDTH / 2, 0); childPos = QPointF(childIndex * CARD_WIDTH / 2, 0);
CardDragItem *drag = CardDragItem *drag = new CardDragItem(card, card->getId(), childPos, forceFaceDown, dragItem);
new CardDragItem(card, card->getId(), childPos, card->getFaceDown() || forceFaceDown, dragItem);
drag->setPos(dragItem->pos() + childPos); drag->setPos(dragItem->pos() + childPos);
scene()->addItem(drag); scene()->addItem(drag);
} }

View file

@ -142,7 +142,7 @@ public:
void processCardInfo(const ServerInfo_Card &_info); void processCardInfo(const ServerInfo_Card &_info);
bool animationEvent(); bool animationEvent();
CardDragItem *createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown); CardDragItem *createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool forceFaceDown);
void deleteDragItem(); void deleteDragItem();
void drawArrow(const QColor &arrowColor); void drawArrow(const QColor &arrowColor);
void drawAttachArrow(); void drawAttachArrow();

View file

@ -314,9 +314,17 @@ void MessageLogWidget::logMoveCard(Player *player,
finalStr = tr("%1 puts %2 into play%3."); finalStr = tr("%1 puts %2 into play%3.");
} }
} else if (targetZoneName == GRAVE_ZONE_NAME) { } else if (targetZoneName == GRAVE_ZONE_NAME) {
finalStr = tr("%1 puts %2%3 into their graveyard."); if (card->getFaceDown()) {
finalStr = tr("%1 puts %2%3 into their graveyard face down.");
} else {
finalStr = tr("%1 puts %2%3 into their graveyard.");
}
} else if (targetZoneName == EXILE_ZONE_NAME) { } else if (targetZoneName == EXILE_ZONE_NAME) {
finalStr = tr("%1 exiles %2%3."); if (card->getFaceDown()) {
finalStr = tr("%1 exiles %2%3 face down.");
} else {
finalStr = tr("%1 exiles %2%3.");
}
} else if (targetZoneName == HAND_ZONE_NAME) { } else if (targetZoneName == HAND_ZONE_NAME) {
finalStr = tr("%1 moves %2%3 to their hand."); finalStr = tr("%1 moves %2%3 to their hand.");
} else if (targetZoneName == DECK_ZONE_NAME) { } else if (targetZoneName == DECK_ZONE_NAME) {
@ -335,10 +343,18 @@ void MessageLogWidget::logMoveCard(Player *player,
finalStr = tr("%1 moves %2%3 to sideboard."); finalStr = tr("%1 moves %2%3 to sideboard.");
} else if (targetZoneName == STACK_ZONE_NAME) { } else if (targetZoneName == STACK_ZONE_NAME) {
soundEngine->playSound("play_card"); soundEngine->playSound("play_card");
finalStr = tr("%1 plays %2%3."); if (card->getFaceDown()) {
finalStr = tr("%1 plays %2%3 face down.");
} else {
finalStr = tr("%1 plays %2%3.");
}
} else { } else {
fourthArg = targetZoneName; fourthArg = targetZoneName;
finalStr = tr("%1 moves %2%3 to custom zone '%4'."); if (card->getFaceDown()) {
finalStr = tr("%1 moves %2%3 to custom zone '%4' face down.");
} else {
finalStr = tr("%1 moves %2%3 to custom zone '%4'.");
}
} }
QString message = finalStr.arg(sanitizeHtml(player->getPlayerInfo()->getName()), cardStr, nameFrom.second); QString message = finalStr.arg(sanitizeHtml(player->getPlayerInfo()->getName()), cardStr, nameFrom.second);

View file

@ -43,8 +43,10 @@ void CardZoneLogic::addCard(CardItem *card, const bool reorganize, const int x,
for (auto *view : views) { for (auto *view : views) {
if (qobject_cast<ZoneViewZoneLogic *>(view->getLogic())->prepareAddCard(x)) { if (qobject_cast<ZoneViewZoneLogic *>(view->getLogic())->prepareAddCard(x)) {
view->getLogic()->addCard(new CardItem(player, nullptr, card->getCardRef(), card->getId()), reorganize, x, auto copy = new CardItem(player, nullptr, card->getCardRef(), card->getId());
y); copy->setFaceDown(card->getFaceDown());
view->getLogic()->addCard(copy, reorganize, x, y);
} }
} }

View file

@ -68,8 +68,13 @@ void PileZone::handleDropEvent(const QList<CardDragItem *> &dragItems, CardZoneL
cmd.set_x(0); cmd.set_x(0);
cmd.set_y(0); cmd.set_y(0);
for (int i = 0; i < dragItems.size(); ++i) for (int i = 0; i < dragItems.size(); ++i) {
cmd.mutable_cards_to_move()->add_card()->set_card_id(dragItems[i]->getId()); auto cardToMove = cmd.mutable_cards_to_move()->add_card();
cardToMove->set_card_id(dragItems[i]->getId());
if (dragItems[i]->isForceFaceDown()) {
cardToMove->set_face_down(true);
}
}
getLogic()->getPlayer()->getPlayerActions()->sendGameCommand(cmd); getLogic()->getPlayer()->getPlayerActions()->sendGameCommand(cmd);
} }
@ -101,12 +106,12 @@ void PileZone::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
if (getLogic()->getCards().isEmpty()) if (getLogic()->getCards().isEmpty())
return; return;
bool faceDown = event->modifiers().testFlag(Qt::ShiftModifier); bool forceFaceDown = event->modifiers().testFlag(Qt::ShiftModifier);
bool bottomCard = event->modifiers().testFlag(Qt::ControlModifier); bool bottomCard = event->modifiers().testFlag(Qt::ControlModifier);
CardItem *card = bottomCard ? getLogic()->getCards().last() : getLogic()->getCards().first(); CardItem *card = bottomCard ? getLogic()->getCards().last() : getLogic()->getCards().first();
const int cardid = const int cardid =
getLogic()->contentsKnown() ? card->getId() : (bottomCard ? getLogic()->getCards().size() - 1 : 0); getLogic()->contentsKnown() ? card->getId() : (bottomCard ? getLogic()->getCards().size() - 1 : 0);
CardDragItem *drag = card->createDragItem(cardid, event->pos(), event->scenePos(), faceDown); CardDragItem *drag = card->createDragItem(cardid, event->pos(), event->scenePos(), forceFaceDown);
drag->grabMouse(); drag->grabMouse();
setCursor(Qt::OpenHandCursor); setCursor(Qt::OpenHandCursor);
} }

View file

@ -78,7 +78,11 @@ void StackZone::handleDropEvent(const QList<CardDragItem *> &dragItems,
for (CardDragItem *item : dragItems) { for (CardDragItem *item : dragItems) {
if (item) { if (item) {
cmd.mutable_cards_to_move()->add_card()->set_card_id(item->getId()); auto cardToMove = cmd.mutable_cards_to_move()->add_card();
cardToMove->set_card_id(item->getId());
if (item->isForceFaceDown()) {
cardToMove->set_face_down(true);
}
} }
} }

View file

@ -134,8 +134,10 @@ void TableZone::handleDropEventByGrid(const QList<CardDragItem *> &dragItems,
for (const auto &item : dragItems) { for (const auto &item : dragItems) {
CardToMove *ctm = cmd.mutable_cards_to_move()->add_card(); CardToMove *ctm = cmd.mutable_cards_to_move()->add_card();
ctm->set_card_id(item->getId()); ctm->set_card_id(item->getId());
ctm->set_face_down(item->getFaceDown()); if (item->isForceFaceDown()) {
if (startZone->getName() != getLogic()->getName() && !item->getFaceDown()) { ctm->set_face_down(true);
}
if (startZone->getName() != getLogic()->getName() && !item->isForceFaceDown()) {
const auto &card = item->getItem()->getCard(); const auto &card = item->getItem()->getCard();
if (card) { if (card) {
ctm->set_pt(card.getInfo().getPowTough().toStdString()); ctm->set_pt(card.getInfo().getPowTough().toStdString());

View file

@ -73,7 +73,10 @@ void ZoneViewZone::initializeCards(const QList<const ServerInfo_Card *> &cardLis
for (int i = 0; i < cardList.size(); ++i) { for (int i = 0; i < cardList.size(); ++i) {
auto card = cardList[i]; auto card = cardList[i];
CardRef cardRef = {QString::fromStdString(card->name()), QString::fromStdString(card->provider_id())}; CardRef cardRef = {QString::fromStdString(card->name()), QString::fromStdString(card->provider_id())};
getLogic()->addCard(new CardItem(getLogic()->getPlayer(), this, cardRef, card->id()), false, i); auto copy = new CardItem(getLogic()->getPlayer(), this, cardRef, card->id());
copy->setFaceDown(card->face_down());
getLogic()->addCard(copy, false, i);
} }
reorganizeCards(); reorganizeCards();
} else if (!qobject_cast<ZoneViewZoneLogic *>(getLogic())->getOriginalZone()->contentsKnown()) { } else if (!qobject_cast<ZoneViewZoneLogic *>(getLogic())->getOriginalZone()->contentsKnown()) {
@ -91,8 +94,10 @@ void ZoneViewZone::initializeCards(const QList<const ServerInfo_Card *> &cardLis
int number = numberCards == -1 ? c.size() : (numberCards < c.size() ? numberCards : c.size()); int number = numberCards == -1 ? c.size() : (numberCards < c.size() ? numberCards : c.size());
for (int i = 0; i < number; i++) { for (int i = 0; i < number; i++) {
CardItem *card = c.at(i); CardItem *card = c.at(i);
getLogic()->addCard(new CardItem(getLogic()->getPlayer(), this, card->getCardRef(), card->getId()), false, auto copy = new CardItem(getLogic()->getPlayer(), this, card->getCardRef(), card->getId());
i); copy->setFaceDown(card->getFaceDown());
getLogic()->addCard(copy, false, i);
} }
reorganizeCards(); reorganizeCards();
} }
@ -107,6 +112,7 @@ void ZoneViewZone::zoneDumpReceived(const Response &r)
auto cardName = QString::fromStdString(cardInfo.name()); auto cardName = QString::fromStdString(cardInfo.name());
auto cardProviderId = QString::fromStdString(cardInfo.provider_id()); auto cardProviderId = QString::fromStdString(cardInfo.provider_id());
auto card = new CardItem(getLogic()->getPlayer(), this, {cardName, cardProviderId}, cardInfo.id(), getLogic()); auto card = new CardItem(getLogic()->getPlayer(), this, {cardName, cardProviderId}, cardInfo.id(), getLogic());
card->setFaceDown(cardInfo.face_down());
getLogic()->rawInsertCard(card, i); getLogic()->rawInsertCard(card, i);
} }
@ -279,8 +285,13 @@ void ZoneViewZone::handleDropEvent(const QList<CardDragItem *> &dragItems,
cmd.set_y(0); cmd.set_y(0);
cmd.set_is_reversed(qobject_cast<ZoneViewZoneLogic *>(getLogic())->getIsReversed()); cmd.set_is_reversed(qobject_cast<ZoneViewZoneLogic *>(getLogic())->getIsReversed());
for (int i = 0; i < dragItems.size(); ++i) for (int i = 0; i < dragItems.size(); ++i) {
cmd.mutable_cards_to_move()->add_card()->set_card_id(dragItems[i]->getId()); auto cardToMove = cmd.mutable_cards_to_move()->add_card();
cardToMove->set_card_id(dragItems[i]->getId());
if (dragItems[i]->isForceFaceDown()) {
cardToMove->set_face_down(true);
}
}
getLogic()->getPlayer()->getPlayerActions()->sendGameCommand(cmd); getLogic()->getPlayer()->getPlayerActions()->sendGameCommand(cmd);
} }

View file

@ -8,7 +8,7 @@ CardInfoPictureArtCropWidget::CardInfoPictureArtCropWidget(QWidget *parent)
hide(); hide();
} }
QPixmap CardInfoPictureArtCropWidget::getProcessedBackground(const QSize &targetSize) QPixmap CardInfoPictureArtCropWidget::getBackground()
{ {
// Load the full-resolution card image, not a pre-scaled one // Load the full-resolution card image, not a pre-scaled one
QPixmap fullResPixmap; QPixmap fullResPixmap;
@ -17,10 +17,8 @@ QPixmap CardInfoPictureArtCropWidget::getProcessedBackground(const QSize &target
} else { } else {
CardPictureLoader::getCardBackPixmap(fullResPixmap, QSize(745, 1040)); CardPictureLoader::getCardBackPixmap(fullResPixmap, QSize(745, 1040));
} }
// Fail-safe if loading failed
if (fullResPixmap.isNull()) { if (fullResPixmap.isNull()) {
return QPixmap(targetSize); return QPixmap(); // return null qpixmap
} }
const QSize sz = fullResPixmap.size(); const QSize sz = fullResPixmap.size();
@ -33,9 +31,7 @@ QPixmap CardInfoPictureArtCropWidget::getProcessedBackground(const QSize &target
foilRect = foilRect.intersected(fullResPixmap.rect()); // always clamp to source bounds foilRect = foilRect.intersected(fullResPixmap.rect()); // always clamp to source bounds
// Crop first, then scale for best quality // return full resolution image crop
QPixmap cropped = fullResPixmap.copy(foilRect); QPixmap cropped = fullResPixmap.copy(foilRect);
QPixmap scaled = cropped.scaled(targetSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); return cropped;
return scaled;
} }

View file

@ -16,8 +16,8 @@ class CardInfoPictureArtCropWidget : public CardInfoPictureWidget
public: public:
explicit CardInfoPictureArtCropWidget(QWidget *parent = nullptr); explicit CardInfoPictureArtCropWidget(QWidget *parent = nullptr);
// Returns a processed (cropped & scaled) version of the pixmap // Returns a cropped version of the pixmap
QPixmap getProcessedBackground(const QSize &targetSize); QPixmap getBackground();
}; };
#endif // CARD_INFO_PICTURE_ART_CROP_WIDGET_H #endif // CARD_INFO_PICTURE_ART_CROP_WIDGET_H

View file

@ -20,8 +20,6 @@
#include <libcockatrice/card/database/card_database_manager.h> #include <libcockatrice/card/database/card_database_manager.h>
#include <libcockatrice/models/database/card_set/card_sets_model.h> #include <libcockatrice/models/database/card_set/card_sets_model.h>
#define SORT_RESET -1
WndSets::WndSets(QWidget *parent) : QMainWindow(parent) WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
{ {
setOrderIsSorted = false; setOrderIsSorted = false;
@ -97,7 +95,6 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
view->setDropIndicatorShown(true); view->setDropIndicatorShown(true);
view->setDragDropMode(QAbstractItemView::InternalMove); view->setDragDropMode(QAbstractItemView::InternalMove);
view->sortByColumn(SetsModel::SortKeyCol, Qt::AscendingOrder);
view->setColumnHidden(SetsModel::SortKeyCol, true); view->setColumnHidden(SetsModel::SortKeyCol, true);
view->setColumnHidden(SetsModel::IsKnownCol, true); view->setColumnHidden(SetsModel::IsKnownCol, true);
view->setColumnHidden(SetsModel::PriorityCol, true); view->setColumnHidden(SetsModel::PriorityCol, true);
@ -196,10 +193,10 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
auto headerState = SettingsCache::instance().layouts().getSetsDialogHeaderState(); auto headerState = SettingsCache::instance().layouts().getSetsDialogHeaderState();
if (!headerState.isEmpty()) { if (!headerState.isEmpty()) {
view->header()->restoreState(headerState); view->header()->restoreState(headerState);
view->header()->setSortIndicator(SORT_RESET, Qt::DescendingOrder);
} else { } else {
view->header()->resizeSections(QHeaderView::ResizeToContents); view->header()->resizeSections(QHeaderView::ResizeToContents);
} }
resetSort();
connect(view->header(), &QHeaderView::geometriesChanged, this, &WndSets::saveHeaderState); connect(view->header(), &QHeaderView::geometriesChanged, this, &WndSets::saveHeaderState);
} }
@ -239,6 +236,13 @@ void WndSets::rebuildMainLayout(int actionToTake)
} }
} }
void WndSets::resetSort()
{
view->sortByColumn(SetsModel::SortKeyCol, Qt::AscendingOrder);
sortIndex = -1;
sortWarning->setVisible(false);
}
void WndSets::includeRebalancedCardsChanged(bool _includeRebalancedCards) void WndSets::includeRebalancedCardsChanged(bool _includeRebalancedCards)
{ {
includeRebalancedCards = _includeRebalancedCards; includeRebalancedCards = _includeRebalancedCards;
@ -260,9 +264,9 @@ void WndSets::actRestore()
void WndSets::actRestoreOriginalOrder() void WndSets::actRestoreOriginalOrder()
{ {
view->header()->setSortIndicator(SORT_RESET, Qt::DescendingOrder);
model->restoreOriginalOrder(); model->restoreOriginalOrder();
sortWarning->setVisible(false); view->selectionModel()->reset();
resetSort();
} }
void WndSets::actDisableResetButton(const QString &filterString) void WndSets::actDisableResetButton(const QString &filterString)
@ -288,11 +292,12 @@ void WndSets::actSort(int index)
sortIndex = index; sortIndex = index;
sortWarning->setVisible(true); sortWarning->setVisible(true);
} else { } else {
view->header()->setSortIndicator(SORT_RESET, Qt::DescendingOrder); resetSort();
sortIndex = -1;
sortWarning->setVisible(false);
} }
} }
if (!view->selectionModel()->selection().empty()) {
view->scrollTo(view->selectionModel()->selectedRows().first());
}
} }
void WndSets::actIgnoreWarning() void WndSets::actIgnoreWarning()
@ -301,23 +306,18 @@ void WndSets::actIgnoreWarning()
return; return;
} }
model->sort(sortIndex, sortOrder); model->sort(sortIndex, sortOrder);
view->header()->setSortIndicator(SORT_RESET, Qt::DescendingOrder); resetSort();
sortIndex = -1;
sortWarning->setVisible(false);
} }
void WndSets::actDisableSortButtons(int index) void WndSets::actDisableSortButtons(int index)
{ {
if (index != SORT_RESET) { if (index != SetsModel::SortKeyCol) {
view->setDragEnabled(false); view->setDragEnabled(false);
setOrderIsSorted = true; setOrderIsSorted = true;
} else { } else {
setOrderIsSorted = false; setOrderIsSorted = false;
view->setDragEnabled(true); view->setDragEnabled(true);
} }
if (!view->selectionModel()->selection().empty()) {
view->scrollTo(view->selectionModel()->selectedRows().first());
}
actToggleButtons(view->selectionModel()->selection(), QItemSelection()); actToggleButtons(view->selectionModel()->selection(), QItemSelection());
} }

View file

@ -45,9 +45,6 @@ private:
QHBoxLayout *filterBox; QHBoxLayout *filterBox;
int sortIndex; int sortIndex;
Qt::SortOrder sortOrder; Qt::SortOrder sortOrder;
void closeEvent(QCloseEvent *ev) override;
void saveHeaderState();
void rebuildMainLayout(int actionToTake);
bool setOrderIsSorted; bool setOrderIsSorted;
bool includeRebalancedCards; bool includeRebalancedCards;
enum enum
@ -56,6 +53,11 @@ private:
SOME_SETS_SELECTED SOME_SETS_SELECTED
}; };
void closeEvent(QCloseEvent *ev) override;
void saveHeaderState();
void rebuildMainLayout(int actionToTake);
void resetSort();
public: public:
explicit WndSets(QWidget *parent = nullptr); explicit WndSets(QWidget *parent = nullptr);
~WndSets() override; ~WndSets() override;

View file

@ -63,6 +63,7 @@ void HomeWidget::initializeBackgroundFromSource()
cardChangeTimer->stop(); cardChangeTimer->stop();
background = QPixmap("theme:backgrounds/home"); background = QPixmap("theme:backgrounds/home");
backgroundSourceDeck = DeckList(); backgroundSourceDeck = DeckList();
backgroundSourceCard->setCard(ExactCard());
updateButtonsToBackgroundColor(); updateButtonsToBackgroundColor();
update(); update();
break; break;
@ -138,7 +139,7 @@ void HomeWidget::updateRandomCard()
connect(newCard.getCardPtr().data(), &CardInfo::pixmapUpdated, this, &HomeWidget::updateBackgroundProperties); connect(newCard.getCardPtr().data(), &CardInfo::pixmapUpdated, this, &HomeWidget::updateBackgroundProperties);
backgroundSourceCard->setCard(newCard); backgroundSourceCard->setCard(newCard);
background = backgroundSourceCard->getProcessedBackground(size()); background = backgroundSourceCard->getBackground(size());
} }
void HomeWidget::onBackgroundShuffleFrequencyChanged() void HomeWidget::onBackgroundShuffleFrequencyChanged()
@ -151,7 +152,7 @@ void HomeWidget::onBackgroundShuffleFrequencyChanged()
void HomeWidget::updateBackgroundProperties() void HomeWidget::updateBackgroundProperties()
{ {
background = backgroundSourceCard->getProcessedBackground(size()); background = backgroundSourceCard->getBackground();
updateButtonsToBackgroundColor(); updateButtonsToBackgroundColor();
update(); // Triggers repaint update(); // Triggers repaint
} }
@ -309,14 +310,17 @@ void HomeWidget::paintEvent(QPaintEvent *event)
QPainter painter(this); QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::Antialiasing);
background = background.scaled(size(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); if (!background.isNull()) {
QSize widgetSize = size() * devicePixelRatio();
QPixmap toDraw = background.scaled(widgetSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
// Draw already-scaled background centered // Draw scaled background centered
QSize widgetSize = size(); QSize bgSize = toDraw.size();
QSize bgSize = background.size(); QPoint topLeft((widgetSize.width() - bgSize.width()) / (devicePixelRatio() * 2), // undo scaling for painter
QPoint topLeft((widgetSize.width() - bgSize.width()) / 2, (widgetSize.height() - bgSize.height()) / 2); (widgetSize.height() - bgSize.height()) / (devicePixelRatio() * 2));
painter.drawPixmap(topLeft, background); painter.drawPixmap(topLeft, toDraw);
}
// Draw translucent black overlay with rounded corners // Draw translucent black overlay with rounded corners
QRectF overlayRect(5, 5, width() - 10, height() - 10); QRectF overlayRect(5, 5, width() - 10, height() - 10);

View file

@ -45,7 +45,7 @@ QVariant SetsModel::data(const QModelIndex &index, int role) const
switch (index.column()) { switch (index.column()) {
case SortKeyCol: case SortKeyCol:
return QString("%1").arg(set->getSortKey(), 8, 10, QChar('0')); return QString("%1").arg(index.row(), 8, 10, QChar('0'));
case IsKnownCol: case IsKnownCol:
return set->getIsKnown(); return set->getIsKnown();
case SetTypeCol: case SetTypeCol:

View file

@ -198,6 +198,35 @@ shouldDestroyOnMove(const Server_Card *card, const Server_CardZone *startZone, c
return true; return true;
} }
/**
* @brief Determines whether the moved card should be face-down
*/
static bool
shouldBeFaceDown(const MoveCardStruct &cardStruct, const Server_CardZone *startZone, const Server_CardZone *targetZone)
{
if (!targetZone) {
return false;
}
// being face-down only makes sense for public zones
if (targetZone->getType() != ServerInfo_Zone::PublicZone) {
return false;
}
// face-down property in proto takes precedence
if (cardStruct.cardToMove->has_face_down()) {
return cardStruct.cardToMove->face_down();
}
// Default to keep face-down the same if zone didn't change.
// Compare using zone names because face-down is maintained when changing controllers.
if (startZone && startZone->getName() == targetZone->getName()) {
return cardStruct.card->getFaceDown();
}
return false;
}
Response::ResponseCode Server_AbstractPlayer::moveCard(GameEventStorage &ges, Response::ResponseCode Server_AbstractPlayer::moveCard(GameEventStorage &ges,
Server_CardZone *startzone, Server_CardZone *startzone,
const QList<const CardToMove *> &_cards, const QList<const CardToMove *> &_cards,
@ -257,10 +286,7 @@ Response::ResponseCode Server_AbstractPlayer::moveCard(GameEventStorage &ges,
for (auto cardStruct : cardsToMove) { for (auto cardStruct : cardsToMove) {
Server_Card *card = cardStruct.card; Server_Card *card = cardStruct.card;
const CardToMove *thisCardProperties = cardStruct.cardToMove;
int originalPosition = cardStruct.position; int originalPosition = cardStruct.position;
bool faceDown = targetzone->hasCoords() &&
(thisCardProperties->has_face_down() ? thisCardProperties->face_down() : card->getFaceDown());
bool sourceBeingLookedAt; bool sourceBeingLookedAt;
int position = startzone->removeCard(card, sourceBeingLookedAt); int position = startzone->removeCard(card, sourceBeingLookedAt);
@ -315,6 +341,8 @@ Response::ResponseCode Server_AbstractPlayer::moveCard(GameEventStorage &ges,
++xIndex; ++xIndex;
int newX = isReversed ? targetzone->getCards().size() - xCoord + xIndex : xCoord + xIndex; int newX = isReversed ? targetzone->getCards().size() - xCoord + xIndex : xCoord + xIndex;
bool faceDown = shouldBeFaceDown(cardStruct, startzone, targetzone);
if (targetzone->hasCoords()) { if (targetzone->hasCoords()) {
newX = targetzone->getFreeGridColumn(newX, yCoord, card->getName(), faceDown); newX = targetzone->getFreeGridColumn(newX, yCoord, card->getName(), faceDown);
} else { } else {

View file

@ -6,7 +6,9 @@ message CardToMove {
// Id of the card in its current zone // Id of the card in its current zone
optional sint32 card_id = 1 [default = -1]; optional sint32 card_id = 1 [default = -1];
// Places the card face down, hiding its name // If true, places the card face down, hiding its name.
// If false, forcibly turns the card face up.
// If not set, defers the resulting face down state to the server.
optional bool face_down = 2; optional bool face_down = 2;
// When moving add this value to the power/toughness field of the card // When moving add this value to the power/toughness field of the card