mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-10 20:13:24 -08:00
[Game] Dismiss the hover panel before opening a modal dialog
The hover panel is a Qt::ToolTip window, i.e. a popup: it is always on top and holds the input grab. Actions on the panel that open a modal dialog (Set power/toughness, Set annotation, Set counter value, token creation) therefore opened the dialog behind the panel, where it could not be seen or activated. Hide the panel synchronously and defer the action to the next event-loop turn, so the popup grab is released before the dialog's event loop starts. The panel asks the scene to dismiss it through a new dismissRequested signal, keeping hover timers and the covered-card fade on the scene's side. Reported from the P/T overlay SET button; the same path covers the counter tab and the token tab.
This commit is contained in:
parent
d073a007bb
commit
9162dcdede
3 changed files with 56 additions and 10 deletions
|
|
@ -1040,6 +1040,7 @@ void GameScene::showCardHoverPopup(CardItem *card)
|
|||
cardHoverWidget = new CardHoverWidget(viewport);
|
||||
connect(cardHoverWidget, &CardHoverWidget::hoverEntered, this, &GameScene::onHoverWidgetEntered);
|
||||
connect(cardHoverWidget, &CardHoverWidget::hoverLeft, this, &GameScene::onHoverWidgetLeft);
|
||||
connect(cardHoverWidget, &CardHoverWidget::dismissRequested, this, &GameScene::hideCardHoverPopup);
|
||||
|
||||
// Keep the popup anchored to its card while the view scrolls, zooms, or resizes
|
||||
if (!views().isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -407,10 +407,12 @@ void CardHoverWidget::createPTOverlay()
|
|||
a->actIncT(cardList());
|
||||
}
|
||||
});
|
||||
btnSetPT = createOverlayButton("SET", tr("Set power/toughness..."), [getActions, cardList]() {
|
||||
if (auto *a = getActions()) {
|
||||
a->actRequestSetPTDialog(cardList());
|
||||
}
|
||||
btnSetPT = createOverlayButton("SET", tr("Set power/toughness..."), [this, getActions, cardList]() {
|
||||
runModalAction([getActions, cardList]() {
|
||||
if (auto *a = getActions()) {
|
||||
a->actRequestSetPTDialog(cardList());
|
||||
}
|
||||
});
|
||||
});
|
||||
btnResetPT = createOverlayButton("RST", tr("Reset power/toughness"), [getActions, cardList]() {
|
||||
if (auto *a = getActions()) {
|
||||
|
|
@ -885,7 +887,10 @@ void CardHoverWidget::buildMainTab(const QList<CardState *> &cardList, const QSt
|
|||
mainPage));
|
||||
grid.addButton(createGridButton(
|
||||
tr("Set annotation..."), semanticActionIcon(QStringLiteral("icons/pencil"), AppColor::Marked),
|
||||
[actions, cardList]() { actions->actRequestSetAnnotationDialog(cardList); }, mainPage));
|
||||
[this, actions, cardList]() {
|
||||
runModalAction([actions, cardList]() { actions->actRequestSetAnnotationDialog(cardList); });
|
||||
},
|
||||
mainPage));
|
||||
grid.addButton(createGridButton(tr("Turn Over"),
|
||||
semanticActionIcon(QStringLiteral("icons/swap"), AppColor::Hidden),
|
||||
invoke(cmFlip), mainPage));
|
||||
|
|
@ -1041,7 +1046,10 @@ void CardHoverWidget::buildCounterTab(const QList<CardState *> &cardList, const
|
|||
|
||||
layout->addWidget(createSectionHeader(tr("Power / Toughness"), counterPage));
|
||||
layout->addWidget(createSmallButton(
|
||||
tr("Set power and toughness..."), [actions, cardList]() { actions->actRequestSetPTDialog(cardList); },
|
||||
tr("Set power and toughness..."),
|
||||
[this, actions, cardList]() {
|
||||
runModalAction([actions, cardList]() { actions->actRequestSetPTDialog(cardList); });
|
||||
},
|
||||
counterPage));
|
||||
layout->addWidget(createSmallButton(
|
||||
tr("Reset power and toughness"), [actions, cardList]() { actions->actResetPT(cardList); }, counterPage));
|
||||
|
|
@ -1065,7 +1073,10 @@ void CardHoverWidget::buildCounterTab(const QList<CardState *> &cardList, const
|
|||
tr("Remove"), [actions, cardList, i]() { actions->actRemoveCardCounter(cardList, i); }, counterPage));
|
||||
}
|
||||
row->addWidget(createSmallButton(
|
||||
tr("Set..."), [actions, cardList, i]() { actions->actRequestSetCardCounterDialog(cardList, i); },
|
||||
tr("Set..."),
|
||||
[this, actions, cardList, i]() {
|
||||
runModalAction([actions, cardList, i]() { actions->actRequestSetCardCounterDialog(cardList, i); });
|
||||
},
|
||||
counterPage));
|
||||
layout->addLayout(row);
|
||||
}
|
||||
|
|
@ -1108,14 +1119,19 @@ void CardHoverWidget::buildTokenTab(CardItem *card, bool canModify)
|
|||
CardItem *source = card;
|
||||
layout->addWidget(createSmallButton(
|
||||
tr("Token: ") + relatedName,
|
||||
[actions, source, captured]() {
|
||||
actions->actRequestCreateRelatedFromRelationDialog(source->getState(), captured);
|
||||
[this, actions, source, captured]() {
|
||||
runModalAction([actions, source, captured]() {
|
||||
actions->actRequestCreateRelatedFromRelationDialog(source->getState(), captured);
|
||||
});
|
||||
},
|
||||
tokenPage));
|
||||
}
|
||||
if (hasMulti && known > 0) {
|
||||
layout->addWidget(createSmallButton(
|
||||
tr("All tokens"), [actions, card]() { actions->actCreateAllRelatedCards(card->getState()); },
|
||||
tr("All tokens"),
|
||||
[this, actions, card]() {
|
||||
runModalAction([actions, card]() { actions->actCreateAllRelatedCards(card->getState()); });
|
||||
},
|
||||
tokenPage));
|
||||
}
|
||||
anyToken = known > 0;
|
||||
|
|
@ -1613,6 +1629,23 @@ bool CardHoverWidget::isClosing() const
|
|||
return fadeOut->state() == QAbstractAnimation::Running;
|
||||
}
|
||||
|
||||
void CardHoverWidget::runModalAction(const std::function<void()> &action)
|
||||
{
|
||||
// The panel is a Qt::ToolTip (Qt::Popup | Qt::Sheet): it is always on top and
|
||||
// holds an input grab. A modal dialog opened while it is still up lands behind
|
||||
// it and cannot be activated. Ask the scene to dismiss the panel so its hover
|
||||
// timers stop and the covered card fades back in, then drop the window
|
||||
// synchronously to release the grab.
|
||||
emit dismissRequested();
|
||||
fadeIn->stop();
|
||||
fadeOut->stop();
|
||||
hide();
|
||||
|
||||
// Defer the dialog to the next event-loop turn: the popup grab is not fully
|
||||
// released until after the current mouse event returns.
|
||||
QTimer::singleShot(0, this, action);
|
||||
}
|
||||
|
||||
// ---------- Event filter ----------
|
||||
|
||||
bool CardHoverWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ protected:
|
|||
signals:
|
||||
void hoverEntered();
|
||||
void hoverLeft();
|
||||
/** @brief Asks the scene to dismiss the panel before a modal dialog opens. */
|
||||
void dismissRequested();
|
||||
|
||||
private slots:
|
||||
void onCardChanged();
|
||||
|
|
@ -167,6 +169,16 @@ private:
|
|||
QWidget *makeStackPage(QVBoxLayout *&layout);
|
||||
void showPage(int index);
|
||||
|
||||
/**
|
||||
* @brief Dismisses the panel, then runs an action that opens a modal dialog.
|
||||
*
|
||||
* A Qt::ToolTip window is always on top and holds the input grab, so a modal
|
||||
* dialog opened from inside the panel lands behind it and cannot be
|
||||
* activated. Hide the panel synchronously, then defer the action so the grab
|
||||
* is released before the dialog's event loop starts.
|
||||
*/
|
||||
void runModalAction(const std::function<void()> &action);
|
||||
|
||||
QLabel *createSectionHeader(const QString &text, QWidget *parent);
|
||||
QLabel *createNoteLabel(const QString &text, QWidget *parent);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue