mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-07 05:53:59 -07:00
feat(game): add drag selection counter overlay
Display count of selected cards inside the lasso during drag selection. Count appears near cursor, repositioning to stay within selection bounds. Includes SelectionRubberBand subclass to allow label to appear above band. QRubberBand calls raise() in showEvent/changeEvent to stay on top - this subclass suppresses that behavior so dragCountLabel can be visible. Adds user setting to enable/disable the drag count overlay.
This commit is contained in:
parent
2b2a6db081
commit
8b20fa0425
9 changed files with 117 additions and 11 deletions
|
|
@ -284,6 +284,8 @@ SettingsCache::SettingsCache()
|
|||
closeEmptyCardView = settings->value("interface/closeEmptyCardView", true).toBool();
|
||||
focusCardViewSearchBar = settings->value("interface/focusCardViewSearchBar", true).toBool();
|
||||
|
||||
showDragSelectionCount = settings->value("interface/showlassoselectioncount", true).toBool();
|
||||
|
||||
showShortcuts = settings->value("menu/showshortcuts", true).toBool();
|
||||
showGameSelectorFilterToolbar = settings->value("menu/showgameselectorfiltertoolbar", true).toBool();
|
||||
displayCardNames = settings->value("cards/displaycardnames", true).toBool();
|
||||
|
|
@ -1308,6 +1310,12 @@ void SettingsCache::setRoundCardCorners(bool _roundCardCorners)
|
|||
emit roundCardCornersChanged(roundCardCorners);
|
||||
}
|
||||
|
||||
void SettingsCache::setShowDragSelectionCount(QT_STATE_CHANGED_T _showDragSelectionCount)
|
||||
{
|
||||
showDragSelectionCount = static_cast<bool>(_showDragSelectionCount);
|
||||
settings->setValue("interface/showlassoselectioncount", showDragSelectionCount);
|
||||
}
|
||||
|
||||
void SettingsCache::loadPaths()
|
||||
{
|
||||
QString dataPath = getDataPath();
|
||||
|
|
|
|||
|
|
@ -340,6 +340,7 @@ private:
|
|||
bool isPortableBuild;
|
||||
bool roundCardCorners;
|
||||
bool showStatusBar;
|
||||
bool showDragSelectionCount;
|
||||
|
||||
public:
|
||||
SettingsCache();
|
||||
|
|
@ -455,6 +456,10 @@ public:
|
|||
{
|
||||
return showStatusBar;
|
||||
}
|
||||
[[nodiscard]] bool getShowDragSelectionCount() const
|
||||
{
|
||||
return showDragSelectionCount;
|
||||
}
|
||||
[[nodiscard]] bool getNotificationsEnabled() const
|
||||
{
|
||||
return notificationsEnabled;
|
||||
|
|
@ -1120,5 +1125,6 @@ public slots:
|
|||
void setUpdateReleaseChannelIndex(int value);
|
||||
void setMaxFontSize(int _max);
|
||||
void setRoundCardCorners(bool _roundCardCorners);
|
||||
void setShowDragSelectionCount(QT_STATE_CHANGED_T _showDragSelectionCount);
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -521,9 +521,9 @@ void GameScene::startRubberBand(const QPointF &selectionOrigin)
|
|||
emit sigStartRubberBand(selectionOrigin);
|
||||
}
|
||||
|
||||
void GameScene::resizeRubberBand(const QPointF &cursorPoint)
|
||||
void GameScene::resizeRubberBand(const QPointF &cursorPoint, int selectedCount)
|
||||
{
|
||||
emit sigResizeRubberBand(cursorPoint);
|
||||
emit sigResizeRubberBand(cursorPoint, selectedCount);
|
||||
}
|
||||
|
||||
void GameScene::stopRubberBand()
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ public:
|
|||
/** Unregisters a card from animation updates. */
|
||||
void unregisterAnimationItem(AbstractCardItem *card);
|
||||
void startRubberBand(const QPointF &selectionOrigin);
|
||||
void resizeRubberBand(const QPointF &cursorPoint);
|
||||
void resizeRubberBand(const QPointF &cursorPoint, int selectedCount);
|
||||
void stopRubberBand();
|
||||
|
||||
public slots:
|
||||
|
|
@ -196,7 +196,7 @@ protected:
|
|||
|
||||
signals:
|
||||
void sigStartRubberBand(const QPointF &selectionOrigin);
|
||||
void sigResizeRubberBand(const QPointF &cursorPoint);
|
||||
void sigResizeRubberBand(const QPointF &cursorPoint, int selectedCount);
|
||||
void sigStopRubberBand();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,32 @@
|
|||
#include "game_scene.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QLabel>
|
||||
#include <QResizeEvent>
|
||||
#include <QRubberBand>
|
||||
|
||||
// QRubberBand calls raise() in showEvent() and changeEvent() to stay on top of siblings.
|
||||
// This subclass disables that behavior so dragCountLabel can appear above it.
|
||||
class SelectionRubberBand : public QRubberBand
|
||||
{
|
||||
public:
|
||||
using QRubberBand::QRubberBand;
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *event) override
|
||||
{
|
||||
QWidget::showEvent(event); // Skip QRubberBand's raise()
|
||||
}
|
||||
|
||||
void changeEvent(QEvent *event) override
|
||||
{
|
||||
if (event->type() == QEvent::ZOrderChange) {
|
||||
return; // Skip QRubberBand's raise() on z-order changes
|
||||
}
|
||||
QRubberBand::changeEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
GameView::GameView(GameScene *scene, QWidget *parent) : QGraphicsView(scene, parent), rubberBand(0)
|
||||
{
|
||||
setBackgroundBrush(QBrush(QColor(0, 0, 0)));
|
||||
|
|
@ -27,7 +50,19 @@ GameView::GameView(GameScene *scene, QWidget *parent) : QGraphicsView(scene, par
|
|||
connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this,
|
||||
&GameView::refreshShortcuts);
|
||||
refreshShortcuts();
|
||||
rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
|
||||
rubberBand = new SelectionRubberBand(QRubberBand::Rectangle, this);
|
||||
|
||||
const QString countLabelStyle = "color: white; "
|
||||
"font-size: 14px; "
|
||||
"font-weight: bold; "
|
||||
"background-color: rgba(0, 0, 0, 160); "
|
||||
"border-radius: 3px; "
|
||||
"padding: 1px 2px;";
|
||||
|
||||
dragCountLabel = new QLabel(this);
|
||||
dragCountLabel->setStyleSheet(countLabelStyle);
|
||||
dragCountLabel->hide();
|
||||
dragCountLabel->raise();
|
||||
}
|
||||
|
||||
void GameView::resizeEvent(QResizeEvent *event)
|
||||
|
|
@ -48,20 +83,67 @@ void GameView::updateSceneRect(const QRectF &rect)
|
|||
|
||||
void GameView::startRubberBand(const QPointF &_selectionOrigin)
|
||||
{
|
||||
if (!rubberBand)
|
||||
return;
|
||||
|
||||
selectionOrigin = _selectionOrigin;
|
||||
rubberBand->setGeometry(QRect(mapFromScene(selectionOrigin), QSize(0, 0)));
|
||||
rubberBand->show();
|
||||
}
|
||||
|
||||
void GameView::resizeRubberBand(const QPointF &cursorPoint)
|
||||
void GameView::resizeRubberBand(const QPointF &cursorPoint, int selectedCount)
|
||||
{
|
||||
if (rubberBand)
|
||||
rubberBand->setGeometry(QRect(mapFromScene(selectionOrigin), cursorPoint.toPoint()).normalized());
|
||||
if (!rubberBand)
|
||||
return;
|
||||
|
||||
constexpr int kLabelPaddingInPixels = 4;
|
||||
|
||||
QPoint cursor = cursorPoint.toPoint();
|
||||
QRect rect = QRect(mapFromScene(selectionOrigin), cursor).normalized();
|
||||
rubberBand->setGeometry(rect);
|
||||
|
||||
if (!SettingsCache::instance().getShowDragSelectionCount()) {
|
||||
dragCountLabel->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedCount > 0) {
|
||||
dragCountLabel->setText(QString::number(selectedCount));
|
||||
dragCountLabel->adjustSize();
|
||||
QSize labelSize = dragCountLabel->size();
|
||||
|
||||
if (rect.width() < labelSize.width() + 2 * kLabelPaddingInPixels ||
|
||||
rect.height() < labelSize.height() + 2 * kLabelPaddingInPixels) {
|
||||
dragCountLabel->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
const int minX = rect.left() + kLabelPaddingInPixels;
|
||||
const int minY = rect.top() + kLabelPaddingInPixels;
|
||||
|
||||
int x = qMax(minX, cursor.x() - labelSize.width() - kLabelPaddingInPixels);
|
||||
int y = qMax(minY, cursor.y() - labelSize.height() - kLabelPaddingInPixels);
|
||||
|
||||
bool isAtTopLeftCorner = (x == minX) && (y == minY);
|
||||
if (isAtTopLeftCorner) {
|
||||
constexpr int kCursorClearanceInPixels = 16;
|
||||
x = qMin(cursor.x() + kCursorClearanceInPixels, rect.right() - labelSize.width() - kLabelPaddingInPixels);
|
||||
}
|
||||
|
||||
dragCountLabel->move(x, y);
|
||||
dragCountLabel->show();
|
||||
} else {
|
||||
dragCountLabel->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void GameView::stopRubberBand()
|
||||
{
|
||||
if (!rubberBand)
|
||||
return;
|
||||
|
||||
rubberBand->hide();
|
||||
dragCountLabel->hide();
|
||||
}
|
||||
|
||||
void GameView::refreshShortcuts()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <QGraphicsView>
|
||||
|
||||
class GameScene;
|
||||
class QLabel;
|
||||
class QRubberBand;
|
||||
|
||||
class GameView : public QGraphicsView
|
||||
|
|
@ -18,13 +19,14 @@ class GameView : public QGraphicsView
|
|||
private:
|
||||
QAction *aCloseMostRecentZoneView;
|
||||
QRubberBand *rubberBand;
|
||||
QLabel *dragCountLabel;
|
||||
QPointF selectionOrigin;
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
private slots:
|
||||
void startRubberBand(const QPointF &selectionOrigin);
|
||||
void resizeRubberBand(const QPointF &cursorPoint);
|
||||
void resizeRubberBand(const QPointF &cursorPoint, int selectedCount);
|
||||
void stopRubberBand();
|
||||
void refreshShortcuts();
|
||||
public slots:
|
||||
|
|
|
|||
|
|
@ -68,7 +68,8 @@ void SelectZone::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||
}
|
||||
}
|
||||
static_cast<GameScene *>(scene())->resizeRubberBand(
|
||||
deviceTransform(static_cast<GameScene *>(scene())->getViewportTransform()).map(pos));
|
||||
deviceTransform(static_cast<GameScene *>(scene())->getViewportTransform()).map(pos),
|
||||
cardsInSelectionRect.size());
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -821,6 +821,10 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage()
|
|||
connect(&annotateTokensCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setAnnotateTokens);
|
||||
|
||||
showDragSelectionCountCheckBox.setChecked(SettingsCache::instance().getShowDragSelectionCount());
|
||||
connect(&showDragSelectionCountCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setShowDragSelectionCount);
|
||||
|
||||
useTearOffMenusCheckBox.setChecked(SettingsCache::instance().getUseTearOffMenus());
|
||||
connect(&useTearOffMenusCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
[](const QT_STATE_CHANGED_T state) { SettingsCache::instance().setUseTearOffMenus(state == Qt::Checked); });
|
||||
|
|
@ -833,7 +837,8 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage()
|
|||
generalGrid->addWidget(&closeEmptyCardViewCheckBox, 4, 0);
|
||||
generalGrid->addWidget(&focusCardViewSearchBarCheckBox, 5, 0);
|
||||
generalGrid->addWidget(&annotateTokensCheckBox, 6, 0);
|
||||
generalGrid->addWidget(&useTearOffMenusCheckBox, 7, 0);
|
||||
generalGrid->addWidget(&showDragSelectionCountCheckBox, 7, 0);
|
||||
generalGrid->addWidget(&useTearOffMenusCheckBox, 8, 0);
|
||||
|
||||
generalGroupBox = new QGroupBox;
|
||||
generalGroupBox->setLayout(generalGrid);
|
||||
|
|
@ -955,6 +960,7 @@ void UserInterfaceSettingsPage::retranslateUi()
|
|||
closeEmptyCardViewCheckBox.setText(tr("Close card view window when last card is removed"));
|
||||
focusCardViewSearchBarCheckBox.setText(tr("Auto focus search bar when card view window is opened"));
|
||||
annotateTokensCheckBox.setText(tr("Annotate card text on tokens"));
|
||||
showDragSelectionCountCheckBox.setText(tr("Show selection counter during drag selection"));
|
||||
useTearOffMenusCheckBox.setText(tr("Use tear-off menus, allowing right click menus to persist on screen"));
|
||||
notificationsGroupBox->setTitle(tr("Notifications settings"));
|
||||
notificationsEnabledCheckBox.setText(tr("Enable notifications in taskbar"));
|
||||
|
|
|
|||
|
|
@ -171,6 +171,7 @@ private:
|
|||
QCheckBox closeEmptyCardViewCheckBox;
|
||||
QCheckBox focusCardViewSearchBarCheckBox;
|
||||
QCheckBox annotateTokensCheckBox;
|
||||
QCheckBox showDragSelectionCountCheckBox;
|
||||
QCheckBox useTearOffMenusCheckBox;
|
||||
QCheckBox tapAnimationCheckBox;
|
||||
QCheckBox openDeckInNewTabCheckBox;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue