mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-04-27 07:48:01 -07:00
* feat(z-values): add centralized Z-value constants infrastructure Magic numbers scattered across the codebase make Z-value layering hard to understand and maintain. Centralizing them provides: - Self-documenting layer hierarchy - Validation utilities for development - Single source of truth for Z-value ranges Two-tier header design: - z_value_layer_manager.h: Foundation with constants and validation - z_values.h: User-facing namespace with semantic constants * refactor(z-values): replace magic Z-value numbers with ZValues constants Magic numbers like 2000000007 are impossible to understand without context. Named constants (ZValues::DRAG_ITEM) are self-documenting. This intentionally renumbers overlay Z-values to use a cleaner offset sequence. The relative stacking order is preserved, which is what matters for correct rendering. Each consumer now includes z_values.h and uses semantic constants instead of magic numbers. * refactor(z-values): removed redundant inline with contexpr, Updated doc, magic numbers removed from TableZone.
577 lines
No EOL
21 KiB
C++
577 lines
No EOL
21 KiB
C++
#include "view_zone_widget.h"
|
|
|
|
#include "../../client/settings/cache_settings.h"
|
|
#include "../../filters/syntax_help.h"
|
|
#include "../../interface/pixel_map_generator.h"
|
|
#include "../board/card_item.h"
|
|
#include "../game_scene.h"
|
|
#include "../player/player.h"
|
|
#include "../player/player_actions.h"
|
|
#include "../z_values.h"
|
|
#include "view_zone.h"
|
|
|
|
#include <QCheckBox>
|
|
#include <QGraphicsLinearLayout>
|
|
#include <QGraphicsProxyWidget>
|
|
#include <QGraphicsSceneMouseEvent>
|
|
#include <QGraphicsView>
|
|
#include <QLabel>
|
|
#include <QPainter>
|
|
#include <QScrollBar>
|
|
#include <QStyle>
|
|
#include <QStyleOption>
|
|
#include <libcockatrice/protocol/pb/command_shuffle.pb.h>
|
|
|
|
namespace
|
|
{
|
|
constexpr qreal kTitleBarHeight = 24.0;
|
|
constexpr qreal kMinVisibleWidth = 100.0;
|
|
} // namespace
|
|
|
|
/**
|
|
* @param _player the player the cards were revealed to.
|
|
* @param _origZone the zone the cards were revealed from.
|
|
* @param numberCards num of cards to reveal from the zone. Ex: scry the top 3 cards.
|
|
* Pass in a negative number to reveal the entire zone.
|
|
* -1 specifically will give the option to shuffle the zone upon closing the window.
|
|
* @param _revealZone if false, the cards will be face down.
|
|
* @param _writeableRevealZone whether the player can interact with the revealed cards.
|
|
*/
|
|
ZoneViewWidget::ZoneViewWidget(Player *_player,
|
|
CardZoneLogic *_origZone,
|
|
int numberCards,
|
|
bool _revealZone,
|
|
bool _writeableRevealZone,
|
|
const QList<const ServerInfo_Card *> &cardList,
|
|
bool _isReversed)
|
|
: QGraphicsWidget(0, Qt::Window), canBeShuffled(_origZone->getIsShufflable()), player(_player)
|
|
{
|
|
setAcceptHoverEvents(true);
|
|
setAttribute(Qt::WA_DeleteOnClose);
|
|
setZValue(ZValues::ZONE_VIEW_WIDGET);
|
|
setFlag(ItemIgnoresTransformations);
|
|
|
|
QGraphicsLinearLayout *vbox = new QGraphicsLinearLayout(Qt::Vertical);
|
|
vbox->setSpacing(2);
|
|
|
|
// If the number is < 0, then it means that we can give the option to make the area sorted
|
|
if (numberCards < 0) {
|
|
// search edit
|
|
searchEdit.setFocusPolicy(Qt::ClickFocus);
|
|
searchEdit.setPlaceholderText(tr("Search by card name (or search expressions)"));
|
|
searchEdit.setClearButtonEnabled(true);
|
|
searchEdit.addAction(loadColorAdjustedPixmap("theme:icons/search"), QLineEdit::LeadingPosition);
|
|
auto help = searchEdit.addAction(QPixmap("theme:icons/info"), QLineEdit::TrailingPosition);
|
|
|
|
connect(help, &QAction::triggered, this, [this] { createSearchSyntaxHelpWindow(&searchEdit); });
|
|
|
|
if (SettingsCache::instance().getFocusCardViewSearchBar()) {
|
|
this->setActive(true);
|
|
searchEdit.setFocus();
|
|
}
|
|
|
|
QGraphicsProxyWidget *searchEditProxy = new QGraphicsProxyWidget;
|
|
searchEditProxy->setWidget(&searchEdit);
|
|
searchEditProxy->setZValue(ZValues::DRAG_ITEM);
|
|
vbox->addItem(searchEditProxy);
|
|
|
|
// top row
|
|
QGraphicsLinearLayout *hTopRow = new QGraphicsLinearLayout(Qt::Horizontal);
|
|
|
|
// groupBy options
|
|
QGraphicsProxyWidget *groupBySelectorProxy = new QGraphicsProxyWidget;
|
|
groupBySelectorProxy->setWidget(&groupBySelector);
|
|
groupBySelectorProxy->setZValue(ZValues::TOP_UI);
|
|
hTopRow->addItem(groupBySelectorProxy);
|
|
|
|
// sortBy options
|
|
QGraphicsProxyWidget *sortBySelectorProxy = new QGraphicsProxyWidget;
|
|
sortBySelectorProxy->setWidget(&sortBySelector);
|
|
sortBySelectorProxy->setZValue(ZValues::DRAG_ITEM);
|
|
hTopRow->addItem(sortBySelectorProxy);
|
|
|
|
vbox->addItem(hTopRow);
|
|
|
|
// line
|
|
QGraphicsProxyWidget *lineProxy = new QGraphicsProxyWidget;
|
|
QFrame *line = new QFrame;
|
|
line->setFrameShape(QFrame::HLine);
|
|
line->setFrameShadow(QFrame::Sunken);
|
|
lineProxy->setWidget(line);
|
|
vbox->addItem(lineProxy);
|
|
|
|
// bottom row
|
|
QGraphicsLinearLayout *hBottomRow = new QGraphicsLinearLayout(Qt::Horizontal);
|
|
|
|
// pile view options
|
|
QGraphicsProxyWidget *pileViewProxy = new QGraphicsProxyWidget;
|
|
pileViewProxy->setWidget(&pileViewCheckBox);
|
|
hBottomRow->addItem(pileViewProxy);
|
|
|
|
// shuffle options
|
|
if (_origZone->getIsShufflable() && numberCards == -1) {
|
|
shuffleCheckBox.setChecked(true);
|
|
QGraphicsProxyWidget *shuffleProxy = new QGraphicsProxyWidget;
|
|
shuffleProxy->setWidget(&shuffleCheckBox);
|
|
hBottomRow->addItem(shuffleProxy);
|
|
}
|
|
|
|
vbox->addItem(hBottomRow);
|
|
}
|
|
|
|
extraHeight = vbox->sizeHint(Qt::PreferredSize).height();
|
|
|
|
QGraphicsLinearLayout *zoneHBox = new QGraphicsLinearLayout(Qt::Horizontal);
|
|
|
|
zoneContainer = new QGraphicsWidget(this);
|
|
zoneContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
zoneContainer->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
|
|
zoneHBox->addItem(zoneContainer);
|
|
|
|
scrollBar = new QScrollBar(Qt::Vertical);
|
|
scrollBar->setMinimum(0);
|
|
scrollBar->setSingleStep(20);
|
|
scrollBar->setPageStep(200);
|
|
connect(scrollBar, &QScrollBar::valueChanged, this, &ZoneViewWidget::handleScrollBarChange);
|
|
scrollBarProxy = new ScrollableGraphicsProxyWidget;
|
|
scrollBarProxy->setWidget(scrollBar);
|
|
zoneHBox->addItem(scrollBarProxy);
|
|
|
|
vbox->addItem(zoneHBox);
|
|
|
|
zone = new ZoneViewZone(new ZoneViewZoneLogic(player, _origZone, numberCards, _revealZone, _writeableRevealZone,
|
|
_isReversed, zoneContainer),
|
|
zoneContainer);
|
|
connect(zone, &ZoneViewZone::wheelEventReceived, scrollBarProxy, &ScrollableGraphicsProxyWidget::recieveWheelEvent);
|
|
|
|
retranslateUi();
|
|
|
|
// only wire up sort options after creating ZoneViewZone, since it segfaults otherwise.
|
|
if (numberCards < 0) {
|
|
connect(&groupBySelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
|
|
&ZoneViewWidget::processGroupBy);
|
|
connect(&sortBySelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
|
|
&ZoneViewWidget::processSortBy);
|
|
connect(&pileViewCheckBox, &QCheckBox::QT_STATE_CHANGED, this, &ZoneViewWidget::processSetPileView);
|
|
groupBySelector.setCurrentIndex(SettingsCache::instance().getZoneViewGroupByIndex());
|
|
sortBySelector.setCurrentIndex(SettingsCache::instance().getZoneViewSortByIndex());
|
|
pileViewCheckBox.setChecked(SettingsCache::instance().getZoneViewPileView());
|
|
|
|
if (CardList::NoSort == static_cast<CardList::SortOption>(groupBySelector.currentData().toInt())) {
|
|
pileViewCheckBox.setEnabled(false);
|
|
}
|
|
|
|
connect(&searchEdit, &QLineEdit::textChanged, zone, &ZoneViewZone::setFilterString);
|
|
}
|
|
|
|
setLayout(vbox);
|
|
|
|
connect(zone, &ZoneViewZone::optimumRectChanged, this, [this] { resizeToZoneContents(); });
|
|
connect(zone, &ZoneViewZone::closed, this, &ZoneViewWidget::zoneDeleted);
|
|
zone->initializeCards(cardList);
|
|
|
|
// QLabel sizes aren't taken into account until the widget is rendered.
|
|
// Force refresh after 1ms to fix glitchy rendering with long QLabels.
|
|
auto *lastResizeBeforeVisibleTimer = new QTimer(this);
|
|
connect(lastResizeBeforeVisibleTimer, &QTimer::timeout, this, [=, this] {
|
|
resizeToZoneContents();
|
|
disconnect(lastResizeBeforeVisibleTimer);
|
|
lastResizeBeforeVisibleTimer->deleteLater();
|
|
});
|
|
lastResizeBeforeVisibleTimer->setSingleShot(true);
|
|
lastResizeBeforeVisibleTimer->start(1);
|
|
}
|
|
|
|
void ZoneViewWidget::processGroupBy(int index)
|
|
{
|
|
auto option = static_cast<CardList::SortOption>(groupBySelector.itemData(index).toInt());
|
|
SettingsCache::instance().setZoneViewGroupByIndex(index);
|
|
zone->setGroupBy(option);
|
|
|
|
// disable pile view checkbox if we're not grouping by anything
|
|
pileViewCheckBox.setEnabled(option != CardList::NoSort);
|
|
|
|
// reset sortBy if it has the same value as groupBy
|
|
if (option != CardList::NoSort &&
|
|
option == static_cast<CardList::SortOption>(sortBySelector.currentData().toInt())) {
|
|
sortBySelector.setCurrentIndex(1); // set to SortByName
|
|
}
|
|
}
|
|
|
|
void ZoneViewWidget::processSortBy(int index)
|
|
{
|
|
auto option = static_cast<CardList::SortOption>(sortBySelector.itemData(index).toInt());
|
|
|
|
// set to SortByName instead if it has the same value as groupBy
|
|
if (option != CardList::NoSort &&
|
|
option == static_cast<CardList::SortOption>(groupBySelector.currentData().toInt())) {
|
|
sortBySelector.setCurrentIndex(1); // set to SortByName
|
|
return;
|
|
}
|
|
|
|
SettingsCache::instance().setZoneViewSortByIndex(index);
|
|
zone->setSortBy(option);
|
|
}
|
|
|
|
void ZoneViewWidget::processSetPileView(QT_STATE_CHANGED_T value)
|
|
{
|
|
SettingsCache::instance().setZoneViewPileView(value);
|
|
zone->setPileView(value);
|
|
}
|
|
|
|
void ZoneViewWidget::retranslateUi()
|
|
{
|
|
setWindowTitle(zone->getLogic()->getTranslatedName(false, CaseNominative));
|
|
|
|
{ // We can't change the strings after they're put into the QComboBox, so this is our workaround
|
|
int oldIndex = groupBySelector.currentIndex();
|
|
groupBySelector.clear();
|
|
groupBySelector.addItem(tr("Ungrouped"), CardList::NoSort);
|
|
groupBySelector.addItem(tr("Group by Type"), CardList::SortByMainType);
|
|
groupBySelector.addItem(tr("Group by Mana Value"), CardList::SortByManaValue);
|
|
groupBySelector.addItem(tr("Group by Color"), CardList::SortByColorGrouping);
|
|
groupBySelector.setCurrentIndex(oldIndex);
|
|
}
|
|
|
|
{
|
|
int oldIndex = sortBySelector.currentIndex();
|
|
sortBySelector.clear();
|
|
sortBySelector.addItem(tr("Unsorted"), CardList::NoSort);
|
|
sortBySelector.addItem(tr("Sort by Name"), CardList::SortByName);
|
|
sortBySelector.addItem(tr("Sort by Type"), CardList::SortByType);
|
|
sortBySelector.addItem(tr("Sort by Mana Cost"), CardList::SortByManaCost);
|
|
sortBySelector.addItem(tr("Sort by Colors"), CardList::SortByColors);
|
|
sortBySelector.addItem(tr("Sort by P/T"), CardList::SortByPt);
|
|
sortBySelector.addItem(tr("Sort by Set"), CardList::SortBySet);
|
|
sortBySelector.setCurrentIndex(oldIndex);
|
|
}
|
|
|
|
shuffleCheckBox.setText(tr("shuffle when closing"));
|
|
pileViewCheckBox.setText(tr("pile view"));
|
|
}
|
|
|
|
void ZoneViewWidget::stopWindowDrag()
|
|
{
|
|
if (!draggingWindow)
|
|
return;
|
|
|
|
draggingWindow = false;
|
|
ungrabMouse();
|
|
}
|
|
|
|
void ZoneViewWidget::startWindowDrag(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
draggingWindow = true;
|
|
dragStartItemPos = pos();
|
|
dragStartScreenPos = event->screenPos();
|
|
dragView = findDragView(event->widget());
|
|
|
|
// need to grab mouse to receive events and not miss initial movement
|
|
grabMouse();
|
|
}
|
|
|
|
QRectF ZoneViewWidget::closeButtonRect(QWidget *styleWidget) const
|
|
{
|
|
const QRectF frameRectF = windowFrameRect();
|
|
|
|
// query the style for the close button position (handles macOS top-left placement)
|
|
// Title bar rect MUST be local (0,0-based) for QStyle
|
|
const QRect titleBarRect(0, 0, static_cast<int>(frameRectF.width()), static_cast<int>(kTitleBarHeight));
|
|
|
|
if (styleWidget) {
|
|
QStyleOptionTitleBar opt;
|
|
opt.initFrom(styleWidget);
|
|
opt.rect = titleBarRect;
|
|
opt.text = windowTitle();
|
|
opt.icon = styleWidget->windowIcon();
|
|
opt.titleBarFlags = Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
|
|
|
|
opt.subControls = QStyle::SC_TitleBarCloseButton;
|
|
opt.activeSubControls = QStyle::SC_TitleBarCloseButton;
|
|
opt.titleBarState = styleWidget->isActiveWindow() ? Qt::WindowActive : Qt::WindowNoState;
|
|
|
|
if (styleWidget->isActiveWindow()) {
|
|
opt.state |= QStyle::State_Active;
|
|
}
|
|
|
|
QRect r = styleWidget->style()->subControlRect(QStyle::CC_TitleBar, &opt, QStyle::SC_TitleBarCloseButton,
|
|
styleWidget);
|
|
|
|
if (r.isValid() && !r.isEmpty()) {
|
|
// Translate from local-titlebar coords → frame coords
|
|
r.translate(frameRectF.topLeft().toPoint());
|
|
return QRectF(r);
|
|
}
|
|
}
|
|
|
|
// Fallback: frame-relative top-right
|
|
return QRectF(frameRectF.right() - kTitleBarHeight, frameRectF.top(), kTitleBarHeight, kTitleBarHeight);
|
|
}
|
|
|
|
QGraphicsView *ZoneViewWidget::findDragView(QWidget *eventWidget) const
|
|
{
|
|
QWidget *current = eventWidget;
|
|
while (current) {
|
|
if (auto *view = qobject_cast<QGraphicsView *>(current))
|
|
return view;
|
|
current = current->parentWidget();
|
|
}
|
|
|
|
if (scene() && !scene()->views().isEmpty())
|
|
return scene()->views().constFirst();
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
QPointF ZoneViewWidget::calcDraggedWindowPos(const QPoint &screenPos,
|
|
const QPointF &scenePos,
|
|
const QPointF &buttonDownScenePos) const
|
|
{
|
|
if (dragView && dragView->viewport()) {
|
|
const QPoint vpStart = dragView->viewport()->mapFromGlobal(dragStartScreenPos);
|
|
const QPoint vpNow = dragView->viewport()->mapFromGlobal(screenPos);
|
|
const QPointF sceneStart = dragView->mapToScene(vpStart);
|
|
const QPointF sceneNow = dragView->mapToScene(vpNow);
|
|
return dragStartItemPos + (sceneNow - sceneStart);
|
|
}
|
|
|
|
return dragStartItemPos + (scenePos - buttonDownScenePos);
|
|
}
|
|
|
|
bool ZoneViewWidget::windowFrameEvent(QEvent *event)
|
|
{
|
|
if (event->type() == QEvent::UngrabMouse) {
|
|
stopWindowDrag();
|
|
return QGraphicsWidget::windowFrameEvent(event);
|
|
}
|
|
|
|
auto *me = dynamic_cast<QGraphicsSceneMouseEvent *>(event);
|
|
if (!me)
|
|
return QGraphicsWidget::windowFrameEvent(event);
|
|
|
|
switch (event->type()) {
|
|
case QEvent::GraphicsSceneMousePress:
|
|
if (me->button() == Qt::LeftButton && windowFrameSectionAt(me->pos()) == Qt::TitleBarArea) {
|
|
// avoid drag on close button
|
|
if (closeButtonRect(me->widget()).contains(me->pos())) {
|
|
me->accept();
|
|
close();
|
|
return true;
|
|
}
|
|
|
|
startWindowDrag(me);
|
|
me->accept();
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
case QEvent::GraphicsSceneMouseMove:
|
|
if (draggingWindow) {
|
|
if (!(me->buttons() & Qt::LeftButton)) {
|
|
stopWindowDrag();
|
|
} else {
|
|
setPos(
|
|
calcDraggedWindowPos(me->screenPos(), me->scenePos(), me->buttonDownScenePos(Qt::LeftButton)));
|
|
}
|
|
me->accept();
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
case QEvent::GraphicsSceneMouseRelease:
|
|
if (draggingWindow && me->button() == Qt::LeftButton) {
|
|
stopWindowDrag();
|
|
me->accept();
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return QGraphicsWidget::windowFrameEvent(event);
|
|
}
|
|
|
|
void ZoneViewWidget::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
// move if the scene routes moves while dragging
|
|
if (draggingWindow && (event->buttons() & Qt::LeftButton)) {
|
|
setPos(calcDraggedWindowPos(event->screenPos(), event->scenePos(), event->buttonDownScenePos(Qt::LeftButton)));
|
|
event->accept();
|
|
return;
|
|
}
|
|
|
|
QGraphicsWidget::mouseMoveEvent(event);
|
|
}
|
|
|
|
void ZoneViewWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
if (draggingWindow && event->button() == Qt::LeftButton) {
|
|
stopWindowDrag();
|
|
event->accept();
|
|
return;
|
|
}
|
|
|
|
QGraphicsWidget::mouseReleaseEvent(event);
|
|
}
|
|
|
|
QVariant ZoneViewWidget::itemChange(GraphicsItemChange change, const QVariant &value)
|
|
{
|
|
if (change == QGraphicsItem::ItemPositionChange && scene()) {
|
|
// Keep grab area in main view
|
|
const QRectF sceneRect = scene()->sceneRect();
|
|
const QPointF requestedPos = value.toPointF();
|
|
QPointF desiredPos = requestedPos;
|
|
|
|
const qreal minX = sceneRect.left();
|
|
const qreal maxX = qMax(minX, sceneRect.right() - kMinVisibleWidth);
|
|
const qreal minY = sceneRect.top() + kTitleBarHeight;
|
|
const qreal maxY = qMax(minY, sceneRect.bottom() - kTitleBarHeight);
|
|
|
|
desiredPos.setX(qBound(minX, desiredPos.x(), maxX));
|
|
desiredPos.setY(qBound(minY, desiredPos.y(), maxY));
|
|
return desiredPos;
|
|
}
|
|
|
|
return QGraphicsWidget::itemChange(change, value);
|
|
}
|
|
|
|
void ZoneViewWidget::resizeEvent(QGraphicsSceneResizeEvent *event)
|
|
{
|
|
// We need to manually resize the scroll bar whenever the window gets resized
|
|
resizeScrollbar(event->newSize().height() - extraHeight - 10);
|
|
}
|
|
|
|
void ZoneViewWidget::resizeScrollbar(const qreal newZoneHeight)
|
|
{
|
|
qreal totalZoneHeight = zone->getOptimumRect().height();
|
|
qreal newMax = qMax(totalZoneHeight - newZoneHeight, 0.0);
|
|
scrollBar->setMaximum(newMax);
|
|
}
|
|
|
|
/**
|
|
* Maps a height that is given as number of rows of cards to the actual height, given in pixels.
|
|
*
|
|
* @param rows Rows of cards
|
|
* @return The height in pixels
|
|
*/
|
|
static qreal rowsToHeight(int rows)
|
|
{
|
|
const qreal cardsHeight = (rows + 1) * (CARD_HEIGHT / 3);
|
|
return cardsHeight + 5; // +5 padding to make the cutoff look nicer
|
|
}
|
|
|
|
/**
|
|
* Calculates the max initial height from the settings.
|
|
* The max initial height setting is given as number of rows, so we need to map it to a height.
|
|
**/
|
|
static qreal calcMaxInitialHeight()
|
|
{
|
|
return rowsToHeight(SettingsCache::instance().getCardViewInitialRowsMax());
|
|
}
|
|
|
|
/**
|
|
* @brief Handles edge cases in determining the next default zone height. We want the height to snap when the number of
|
|
* rows changes, but not if the player has already expanded the window.
|
|
*/
|
|
static qreal determineNewZoneHeight(qreal oldZoneHeight)
|
|
{
|
|
// don't snap if window is taller than max initial height
|
|
if (oldZoneHeight > calcMaxInitialHeight()) {
|
|
return oldZoneHeight;
|
|
}
|
|
|
|
return calcMaxInitialHeight();
|
|
}
|
|
|
|
void ZoneViewWidget::resizeToZoneContents(bool forceInitialHeight)
|
|
{
|
|
QRectF zoneRect = zone->getOptimumRect();
|
|
qreal totalZoneHeight = zoneRect.height();
|
|
|
|
qreal width = qMax(QGraphicsWidget::layout()->effectiveSizeHint(Qt::MinimumSize, QSizeF()).width(),
|
|
zoneRect.width() + scrollBar->width() + 10);
|
|
|
|
QSizeF maxSize(width, zoneRect.height() + extraHeight + 10);
|
|
|
|
qreal currentZoneHeight = rect().height() - extraHeight - 10;
|
|
qreal newZoneHeight = forceInitialHeight ? calcMaxInitialHeight() : determineNewZoneHeight(currentZoneHeight);
|
|
|
|
QSizeF initialSize(width, newZoneHeight + extraHeight + 10);
|
|
|
|
setMaximumSize(maxSize);
|
|
resize(initialSize);
|
|
resizeScrollbar(newZoneHeight);
|
|
|
|
zone->setGeometry(QRectF(0, -scrollBar->value(), zoneContainer->size().width(), totalZoneHeight));
|
|
|
|
if (layout())
|
|
layout()->invalidate();
|
|
}
|
|
|
|
void ZoneViewWidget::handleScrollBarChange(int value)
|
|
{
|
|
zone->setY(-value);
|
|
}
|
|
|
|
void ZoneViewWidget::closeEvent(QCloseEvent *event)
|
|
{
|
|
stopWindowDrag();
|
|
disconnect(zone, &ZoneViewZone::closed, this, 0);
|
|
// manually call zone->close in order to remove it from the origZones views
|
|
zone->close();
|
|
if (shuffleCheckBox.isChecked())
|
|
player->getPlayerActions()->sendGameCommand(Command_Shuffle());
|
|
zoneDeleted();
|
|
event->accept();
|
|
}
|
|
|
|
void ZoneViewWidget::zoneDeleted()
|
|
{
|
|
emit closePressed(this);
|
|
deleteLater();
|
|
}
|
|
|
|
void ZoneViewWidget::initStyleOption(QStyleOption *option) const
|
|
{
|
|
QStyleOptionTitleBar *titleBar = qstyleoption_cast<QStyleOptionTitleBar *>(option);
|
|
if (titleBar)
|
|
titleBar->icon = QPixmap("theme:cockatrice");
|
|
}
|
|
|
|
/**
|
|
* Expands/shrinks the window, depending on the current height as well as the configured initial and expanded max
|
|
* heights.
|
|
*/
|
|
void ZoneViewWidget::expandWindow()
|
|
{
|
|
qreal maxInitialHeight = calcMaxInitialHeight();
|
|
qreal maxExpandedHeight = rowsToHeight(SettingsCache::instance().getCardViewExpandedRowsMax());
|
|
qreal height = rect().height() - extraHeight - 10;
|
|
qreal maxHeight = maximumHeight() - extraHeight - 10;
|
|
|
|
// reset window to initial max height if...
|
|
bool doResetSize =
|
|
// current height is less than that
|
|
(height < maxInitialHeight) ||
|
|
// current height is at expanded max height
|
|
(height == maxExpandedHeight) ||
|
|
// current height is at actual max height, and actual max height is less than expanded max height
|
|
(height == maxHeight && height > maxInitialHeight && height < maxExpandedHeight);
|
|
|
|
if (doResetSize) {
|
|
resizeToZoneContents(true);
|
|
} else {
|
|
// expand/shrink window to expanded max height if current height is anywhere at or between initial max height
|
|
// and actual max height
|
|
resize(maximumSize().boundedTo({maximumWidth(), maxExpandedHeight + extraHeight + 10}));
|
|
}
|
|
}
|
|
|
|
void ZoneViewWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
if (event->pos().y() <= 0) {
|
|
expandWindow();
|
|
}
|
|
} |