Performance fixes, hide sets which can't offer any new cards, better dragging indicators.

This commit is contained in:
Lukas Brübach 2025-02-07 09:21:15 +01:00
parent b11d3e0c55
commit 669e9e42f6
2 changed files with 120 additions and 64 deletions

View file

@ -64,6 +64,8 @@ DlgSelectSetForCards::DlgSelectSetForCards(QWidget *parent, DeckListModel *_mode
splitter->addWidget(scrollArea); splitter->addWidget(scrollArea);
splitter->addWidget(bottomContainer); splitter->addWidget(bottomContainer);
cardsForSets = getCardsForSets();
sortSetsByCount(); sortSetsByCount();
updateCardLists(); updateCardLists();
@ -160,17 +162,13 @@ QMap<QString, int> DlgSelectSetForCards::getSetsForCards()
void DlgSelectSetForCards::updateCardLists() void DlgSelectSetForCards::updateCardLists()
{ {
QList<SetEntryWidget *> entry_widgets; updateLayoutOrder();
for (int i = 0; i < listLayout->count(); ++i) {
QWidget *widget = listLayout->itemAt(i)->widget();
if (auto entry = qobject_cast<SetEntryWidget *>(widget)) {
entry_widgets.append(entry);
}
}
for (SetEntryWidget *entryWidget : entry_widgets) { for (SetEntryWidget *entryWidget : entry_widgets) {
entryWidget->populateCardList();
if (entryWidget->expanded) { if (entryWidget->expanded) {
entryWidget->populateCardList(); entryWidget->updateCardDisplayWidgets();
} }
entryWidget->checkVisibility();
} }
uneditedCardsFlowWidget->clearLayout(); uneditedCardsFlowWidget->clearLayout();
@ -217,7 +215,10 @@ void DlgSelectSetForCards::updateCardLists()
void DlgSelectSetForCards::dragEnterEvent(QDragEnterEvent *event) void DlgSelectSetForCards::dragEnterEvent(QDragEnterEvent *event)
{ {
if (event->mimeData()->hasFormat("application/x-setentrywidget")) { if (event->mimeData()->hasFormat("application/x-setentrywidget")) {
// Highlight the drop target area
event->acceptProposedAction(); event->acceptProposedAction();
// Optionally, change cursor to indicate a valid drop area
setCursor(Qt::OpenHandCursor);
} }
} }
@ -236,7 +237,7 @@ void DlgSelectSetForCards::dropEvent(QDropEvent *event)
} }
if (dropIndex != -1) { if (dropIndex != -1) {
// Find the dragged widget // Find the dragged widget and move it to the new position
SetEntryWidget *draggedWidget = setEntries.value(draggedSetName, nullptr); SetEntryWidget *draggedWidget = setEntries.value(draggedSetName, nullptr);
if (draggedWidget) { if (draggedWidget) {
listLayout->removeWidget(draggedWidget); listLayout->removeWidget(draggedWidget);
@ -245,6 +246,8 @@ void DlgSelectSetForCards::dropEvent(QDropEvent *event)
} }
event->acceptProposedAction(); event->acceptProposedAction();
// Reset cursor after drop
unsetCursor();
} }
QMap<QString, QStringList> DlgSelectSetForCards::getCardsForSets() QMap<QString, QStringList> DlgSelectSetForCards::getCardsForSets()
@ -310,6 +313,17 @@ QMap<QString, QStringList> DlgSelectSetForCards::getModifiedCards()
return modifiedCards; return modifiedCards;
} }
void DlgSelectSetForCards::updateLayoutOrder()
{
entry_widgets.clear();
for (int i = 0; i < listLayout->count(); ++i) {
QWidget *widget = listLayout->itemAt(i)->widget();
if (auto entry = qobject_cast<SetEntryWidget *>(widget)) {
entry_widgets.append(entry);
}
}
}
SetEntryWidget::SetEntryWidget(DlgSelectSetForCards *_parent, const QString &_setName, int count) SetEntryWidget::SetEntryWidget(DlgSelectSetForCards *_parent, const QString &_setName, int count)
: QWidget(_parent), parent(_parent), setName(_setName), expanded(false) : QWidget(_parent), parent(_parent), setName(_setName), expanded(false)
{ {
@ -349,63 +363,86 @@ SetEntryWidget::SetEntryWidget(DlgSelectSetForCards *_parent, const QString &_se
layout->addWidget(alreadySelectedCardsLabel); layout->addWidget(alreadySelectedCardsLabel);
layout->addWidget(alreadySelectedCardListContainer); layout->addWidget(alreadySelectedCardListContainer);
setAttribute(Qt::WA_DeleteOnClose, false); setAttribute(Qt::WA_DeleteOnClose, false);
setAttribute(Qt::WA_StyledBackground, true);
} }
void SetEntryWidget::mousePressEvent(QMouseEvent *event) void SetEntryWidget::mousePressEvent(QMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) { if (event->button() == Qt::LeftButton) {
// Create a drag object and set up mime data
QDrag *drag = new QDrag(this); QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData; QMimeData *mimeData = new QMimeData;
// Set the mime data to store the dragged set's name
mimeData->setData("application/x-setentrywidget", setName.toUtf8()); mimeData->setData("application/x-setentrywidget", setName.toUtf8());
drag->setMimeData(mimeData); drag->setMimeData(mimeData);
// Create a drag preview (snapshot of the widget) // Create a "ghost" pixmap to represent the widget during dragging
QPixmap pixmap(size()); QPixmap pixmap = this->grab();
pixmap.fill(Qt::transparent); // Ensure transparency
QPainter painter(&pixmap); // Ensure pixmap has a transparent background
this->render(&painter); QImage image = pixmap.toImage();
painter.end(); for (int y = 0; y < image.height(); ++y) {
for (int x = 0; x < image.width(); ++x) {
if (image.pixel(x, y) == Qt::transparent) {
image.setPixel(x, y, QColor(0, 0, 0, 0).rgba()); // Set transparency where needed
}
}
}
pixmap = QPixmap::fromImage(image); // Convert back to pixmap after transparency manipulation
// Set the pixmap for the drag object
drag->setPixmap(pixmap); drag->setPixmap(pixmap);
drag->setHotSpot(event->position().toPoint()); // Keeps the cursor aligned
// Optionally adjust the pixmap position offset to align with the cursor
drag->setHotSpot(event->pos());
drag->exec(Qt::MoveAction); drag->exec(Qt::MoveAction);
} }
} }
void SetEntryWidget::mouseMoveEvent(QMouseEvent *event) void SetEntryWidget::enterEvent(QEnterEvent *event)
{ {
if (!(event->buttons() & Qt::LeftButton)) QWidget::enterEvent(event); // Call the base class handler
return; // Highlight the widget by changing the background color only for the widget itself
setStyleSheet("SetEntryWidget { background: gray; }");
// Start a drag operation // Change cursor to open hand
QDrag *drag = new QDrag(this); setCursor(Qt::OpenHandCursor);
QMimeData *mimeData = new QMimeData(); repaint();
mimeData->setText("SetEntryWidget Data"); // Customize with relevant data }
drag->setMimeData(mimeData);
// Create a drag preview of the widget void SetEntryWidget::leaveEvent(QEvent *event)
QPixmap pixmap(size()); {
pixmap.fill(Qt::transparent); QWidget::leaveEvent(event); // Call the base class handler
// Reset the background color only for the widget itself
setStyleSheet("SetEntryWidget { background: none; }");
// Render the widget onto the pixmap // Reset cursor to default
render(&pixmap); setCursor(Qt::ArrowCursor);
repaint();
}
// Optionally, apply transparency to make it look like a drag effect void SetEntryWidget::dragMoveEvent(QDragMoveEvent *event)
QPixmap transparentPixmap = pixmap; {
QPainter painter(&transparentPixmap); // Check if the mime data is of the correct type
painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); if (event->mimeData()->hasFormat("application/x-setentrywidget")) {
painter.fillRect(transparentPixmap.rect(), QColor(0, 0, 0, 128)); // Semi-transparent effect setCursor(Qt::ClosedHandCursor); // Hand cursor to indicate move
painter.end(); // Get the current position of the widget being dragged
// Set the drag pixmap // For now, we will just highlight the widget when dragged.
drag->setPixmap(transparentPixmap); QPainter painter(this);
drag->setHotSpot(event->pos()); // Ensure the drag starts from where the user clicked QColor highlightColor(255, 255, 255, 128); // Semi-transparent white
painter.setBrush(QBrush(highlightColor));
painter.setPen(Qt::NoPen);
painter.drawRect(this->rect()); // Highlight the widget area
// Start the drag operation // Allow the widget to be moved to the new position
drag->exec(Qt::MoveAction); event->acceptProposedAction();
} else {
event->ignore();
}
} }
bool SetEntryWidget::isChecked() const bool SetEntryWidget::isChecked() const
@ -422,13 +459,25 @@ void SetEntryWidget::toggleExpansion()
alreadySelectedCardListContainer->setVisible(expanded); alreadySelectedCardListContainer->setVisible(expanded);
expandButton->setText(expanded ? "-" : "+"); expandButton->setText(expanded ? "-" : "+");
populateCardList();
updateCardDisplayWidgets();
parent->updateCardLists(); parent->updateCardLists();
} }
void SetEntryWidget::checkVisibility()
{
if (possibleCards.empty()) {
setHidden(true);
} else {
setVisible(true);
}
}
QStringList SetEntryWidget::getAllCardsForSet() QStringList SetEntryWidget::getAllCardsForSet()
{ {
QStringList list; QStringList list;
QMap<QString, QStringList> setCards = parent->getCardsForSets(); QMap<QString, QStringList> setCards = parent->cardsForSets;
if (setCards.contains(setName)) { if (setCards.contains(setName)) {
for (const QString &cardName : setCards[setName]) { for (const QString &cardName : setCards[setName]) {
list << cardName; list << cardName;
@ -439,30 +488,31 @@ QStringList SetEntryWidget::getAllCardsForSet()
void SetEntryWidget::populateCardList() void SetEntryWidget::populateCardList()
{ {
cardListContainer->clearLayout(); possibleCards = getAllCardsForSet();
alreadySelectedCardListContainer->clearLayout();
QStringList possibleCards = getAllCardsForSet(); for (SetEntryWidget *entryWidget : parent->entry_widgets) {
QList<SetEntryWidget *> entry_widgets;
for (int i = 0; i < parent->listLayout->count(); ++i) {
QWidget *widget = parent->listLayout->itemAt(i)->widget();
if (auto entry = qobject_cast<SetEntryWidget *>(widget)) {
entry_widgets.append(entry);
}
}
for (SetEntryWidget *entryWidget : entry_widgets) {
if (entryWidget == this) { if (entryWidget == this) {
break; break;
} }
if (entryWidget->isChecked()) { if (entryWidget->isChecked()) {
QStringList alreadyDoneCards = entryWidget->getAllCardsForSet(); for (const QString &cardName : entryWidget->possibleCards) {
for (const QString &cardName : alreadyDoneCards) {
possibleCards.removeAll(cardName); possibleCards.removeAll(cardName);
} }
} }
} }
unusedCards = getAllCardsForSet();
for (const QString &cardName : possibleCards) {
unusedCards.removeAll(cardName);
}
checkVisibility();
}
void SetEntryWidget::updateCardDisplayWidgets()
{
cardListContainer->clearLayout();
alreadySelectedCardListContainer->clearLayout();
for (const QString &cardName : possibleCards) { for (const QString &cardName : possibleCards) {
CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(cardListContainer); CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(cardListContainer);
picture_widget->setCard(CardDatabaseManager::getInstance()->getCardByNameAndProviderId( picture_widget->setCard(CardDatabaseManager::getInstance()->getCardByNameAndProviderId(
@ -471,11 +521,6 @@ void SetEntryWidget::populateCardList()
cardListContainer->addWidget(picture_widget); cardListContainer->addWidget(picture_widget);
} }
QStringList unusedCards = getAllCardsForSet();
for (const QString &cardName : possibleCards) {
unusedCards.removeAll(cardName);
}
for (const QString &cardName : unusedCards) { for (const QString &cardName : unusedCards) {
CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(alreadySelectedCardListContainer); CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(alreadySelectedCardListContainer);
picture_widget->setCard(CardDatabaseManager::getInstance()->getCardByNameAndProviderId( picture_widget->setCard(CardDatabaseManager::getInstance()->getCardByNameAndProviderId(

View file

@ -4,6 +4,7 @@
#include "../client/ui/widgets/general/layout_containers/flow_widget.h" #include "../client/ui/widgets/general/layout_containers/flow_widget.h"
#include "../deck/deck_list_model.h" #include "../deck/deck_list_model.h"
#include <QCheckBox>
#include <QDialog> #include <QDialog>
#include <QLabel> #include <QLabel>
#include <QListWidget> #include <QListWidget>
@ -11,7 +12,6 @@
#include <QScrollArea> #include <QScrollArea>
#include <QVBoxLayout> #include <QVBoxLayout>
class QCheckBox;
class SetEntryWidget; // Forward declaration class SetEntryWidget; // Forward declaration
class DlgSelectSetForCards : public QDialog class DlgSelectSetForCards : public QDialog
@ -20,16 +20,19 @@ class DlgSelectSetForCards : public QDialog
public: public:
explicit DlgSelectSetForCards(QWidget *parent, DeckListModel *_model); explicit DlgSelectSetForCards(QWidget *parent, DeckListModel *_model);
void actOK();
void sortSetsByCount(); void sortSetsByCount();
QMap<QString, QStringList> getCardsForSets(); QMap<QString, QStringList> getCardsForSets();
QMap<QString, QStringList> getModifiedCards(); QMap<QString, QStringList> getModifiedCards();
void updateLayoutOrder();
QVBoxLayout *listLayout; QVBoxLayout *listLayout;
QList<SetEntryWidget *> entry_widgets;
QMap<QString, QStringList> cardsForSets;
public slots: public slots:
void updateCardLists(); void updateCardLists();
void dragEnterEvent(QDragEnterEvent *event) override; void dragEnterEvent(QDragEnterEvent *event) override;
void dropEvent(QDropEvent *event) override; void dropEvent(QDropEvent *event) override;
void actOK();
private: private:
QVBoxLayout *layout; QVBoxLayout *layout;
@ -52,17 +55,23 @@ class SetEntryWidget : public QWidget
public: public:
explicit SetEntryWidget(DlgSelectSetForCards *parent, const QString &setName, int count); explicit SetEntryWidget(DlgSelectSetForCards *parent, const QString &setName, int count);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void toggleExpansion(); void toggleExpansion();
void checkVisibility();
QStringList getAllCardsForSet(); QStringList getAllCardsForSet();
void populateCardList(); void populateCardList();
void updateCardDisplayWidgets();
void updateCardState(bool checked); void updateCardState(bool checked);
bool isChecked() const; bool isChecked() const;
DlgSelectSetForCards *parent; DlgSelectSetForCards *parent;
QString setName; QString setName;
bool expanded; bool expanded;
public slots:
void mousePressEvent(QMouseEvent *event) override;
void enterEvent(QEnterEvent *event) override;
void leaveEvent(QEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
private: private:
QVBoxLayout *layout; QVBoxLayout *layout;
QCheckBox *checkBox; QCheckBox *checkBox;
@ -73,6 +82,8 @@ private:
QLabel *alreadySelectedCardsLabel; QLabel *alreadySelectedCardsLabel;
FlowWidget *alreadySelectedCardListContainer; FlowWidget *alreadySelectedCardListContainer;
QVBoxLayout *cardListLayout; QVBoxLayout *cardListLayout;
QStringList possibleCards;
QStringList unusedCards;
}; };
#endif // DLG_SELECT_SET_FOR_CARDS_H #endif // DLG_SELECT_SET_FOR_CARDS_H