Determine where we will insert the card before actually inserting it in the model.

This commit is contained in:
Lukas Brübach 2025-06-13 04:06:41 +02:00
parent 249f4d9d01
commit dcd63e4a7f
14 changed files with 122 additions and 63 deletions

View file

@ -101,9 +101,9 @@ void TappedOutInterface::copyDeckSplitMainAndSide(DeckList &source, DeckList &ma
DecklistCardNode *addedCard;
if (node->getName() == DECK_ZONE_SIDE)
addedCard = sideboard.addCard(card->getName(), node->getName());
addedCard = sideboard.addCard(card->getName(), node->getName(), -1);
else
addedCard = mainboard.addCard(card->getName(), node->getName());
addedCard = mainboard.addCard(card->getName(), node->getName(), -1);
addedCard->setNumber(card->getNumber());
};

View file

@ -43,7 +43,6 @@ QWidget *CardGroupDisplayWidget::constructWidgetForIndex(int rowIndex)
}
auto cardName = deckListModel->data(index.sibling(index.row(), 1), Qt::EditRole).toString();
auto cardProviderId = deckListModel->data(index.sibling(index.row(), 4), Qt::EditRole).toString();
qInfo() << cardName;
auto widget = new CardInfoPictureWithTextOverlayWidget(getLayoutParent(), true);
widget->setScaleFactor(cardSizeWidget->getSlider()->value());
@ -59,9 +58,6 @@ QWidget *CardGroupDisplayWidget::constructWidgetForIndex(int rowIndex)
void CardGroupDisplayWidget::updateCardDisplays()
{
qInfo() << "Constructing Card Display Widgets for Card Group Display widget";
qInfo() << deckListModel->data(trackedIndex.sibling(trackedIndex.row(), 1), Qt::EditRole).toString() << " has "
<< deckListModel->rowCount(trackedIndex.sibling(trackedIndex.row(), 0)) << " entries.";
for (int i = 0; i < deckListModel->rowCount(trackedIndex); ++i) {
addToLayout(constructWidgetForIndex(i));
}

View file

@ -40,8 +40,8 @@ public slots:
void onHover(CardInfoPtr card);
virtual QWidget* constructWidgetForIndex(int rowIndex);
virtual void updateCardDisplays();
void onCardAddition(const QModelIndex &parent, int first, int last);
void onCardRemoval(const QModelIndex &parent, int first, int last);
virtual void onCardAddition(const QModelIndex &parent, int first, int last);
virtual void onCardRemoval(const QModelIndex &parent, int first, int last);
void resizeEvent(QResizeEvent *event) override;
signals:
@ -65,7 +65,6 @@ protected:
virtual void insertIntoLayout(QWidget *toInsert, int insertAt)
{
qInfo() << "Default card group insert";
layout->insertWidget(insertAt, toInsert);
}

View file

@ -38,7 +38,6 @@ FlatCardGroupDisplayWidget::FlatCardGroupDisplayWidget(QWidget *parent,
indexToWidgetMap.remove(idx);
}
qInfo() << "Initialized a flat CardGroupDisplayWidget";
FlatCardGroupDisplayWidget::updateCardDisplays();
// connect(deckListModel, &DeckListModel::dataChanged, this, &FlatCardGroupDisplayWidget::updateCardDisplays);
disconnect(deckListModel, &QAbstractItemModel::rowsInserted, this, &CardGroupDisplayWidget::onCardAddition);
@ -48,6 +47,38 @@ FlatCardGroupDisplayWidget::FlatCardGroupDisplayWidget(QWidget *parent,
connect(deckListModel, &QAbstractItemModel::rowsRemoved, this, &FlatCardGroupDisplayWidget::onCardRemoval);
}
void FlatCardGroupDisplayWidget::onCardAddition(const QModelIndex &parent, int first, int last)
{
if (!trackedIndex.isValid()) {
emit cleanupRequested(this);
return;
}
if (parent == trackedIndex) {
for (int i = first; i <= last; i++) {
insertIntoLayout(constructWidgetForIndex(i), i);
}
}
}
void FlatCardGroupDisplayWidget::onCardRemoval(const QModelIndex &parent, int first, int last)
{
Q_UNUSED(parent);
Q_UNUSED(first);
Q_UNUSED(last);
if (parent == trackedIndex) {
for (const QPersistentModelIndex &idx : indexToWidgetMap.keys()) {
if (!idx.isValid()) {
removeFromLayout(indexToWidgetMap.value(idx));
indexToWidgetMap.value(idx)->deleteLater();
indexToWidgetMap.remove(idx);
}
}
if (!trackedIndex.isValid()) {
emit cleanupRequested(this);
}
}
}
QWidget *FlatCardGroupDisplayWidget::constructWidgetForIndex(int row)
{
QPersistentModelIndex index = QPersistentModelIndex(deckListModel->index(row, 0, trackedIndex));
@ -57,7 +88,6 @@ QWidget *FlatCardGroupDisplayWidget::constructWidgetForIndex(int row)
}
auto cardName = deckListModel->data(index.sibling(index.row(), 1), Qt::EditRole).toString();
auto cardProviderId = deckListModel->data(index.sibling(index.row(), 4), Qt::EditRole).toString();
qInfo() << cardName;
auto widget = new CardInfoPictureWithTextOverlayWidget(flowWidget, true);
widget->setScaleFactor(cardSizeWidget->getSlider()->value());

View file

@ -22,6 +22,8 @@ public:
public slots:
QWidget* constructWidgetForIndex(int row) override;
void resizeEvent(QResizeEvent *event) override;
void onCardAddition(const QModelIndex &parent, int first, int last) override;
void onCardRemoval(const QModelIndex &parent, int first, int last) override;
private:
FlowWidget *flowWidget;
@ -38,7 +40,6 @@ private:
void insertIntoLayout(QWidget *toInsert, int insertAt) override
{
qInfo() << "Flat card group insertion at " << insertAt;
flowWidget->insertWidgetAtIndex(toInsert, insertAt);
}

View file

@ -37,7 +37,6 @@ OverlappedCardGroupDisplayWidget::OverlappedCardGroupDisplayWidget(QWidget *pare
indexToWidgetMap.remove(idx);
}
qInfo() << "Initialized an overlap CardGroupDisplayWidget";
OverlappedCardGroupDisplayWidget::updateCardDisplays();
connect(cardSizeWidget->getSlider(), &QSlider::valueChanged, this,
@ -50,6 +49,38 @@ OverlappedCardGroupDisplayWidget::OverlappedCardGroupDisplayWidget(QWidget *pare
connect(deckListModel, &QAbstractItemModel::rowsRemoved, this, &OverlappedCardGroupDisplayWidget::onCardRemoval);
}
void OverlappedCardGroupDisplayWidget::onCardAddition(const QModelIndex &parent, int first, int last)
{
if (!trackedIndex.isValid()) {
emit cleanupRequested(this);
return;
}
if (parent == trackedIndex) {
for (int i = first; i <= last; i++) {
insertIntoLayout(constructWidgetForIndex(i), i);
}
}
}
void OverlappedCardGroupDisplayWidget::onCardRemoval(const QModelIndex &parent, int first, int last)
{
Q_UNUSED(parent);
Q_UNUSED(first);
Q_UNUSED(last);
if (parent == trackedIndex) {
for (const QPersistentModelIndex &idx : indexToWidgetMap.keys()) {
if (!idx.isValid()) {
removeFromLayout(indexToWidgetMap.value(idx));
indexToWidgetMap.value(idx)->deleteLater();
indexToWidgetMap.remove(idx);
}
}
if (!trackedIndex.isValid()) {
emit cleanupRequested(this);
}
}
}
void OverlappedCardGroupDisplayWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);

View file

@ -19,22 +19,31 @@ public:
int bannerOpacity,
CardSizeWidget *cardSizeWidget);
public slots:
void onCardAddition(const QModelIndex &parent, int first, int last) override;
void onCardRemoval(const QModelIndex &parent, int first, int last) override;
void resizeEvent(QResizeEvent *event) override;
private:
OverlapWidget *overlapWidget;
QWidget* getLayoutParent() override
QWidget *getLayoutParent() override
{
return overlapWidget;
}
void addToLayout(QWidget* toAdd) override
void addToLayout(QWidget *toAdd) override
{
overlapWidget->addWidget(toAdd);
}
void removeFromLayout(QWidget* toRemove) override
void insertIntoLayout(QWidget *toInsert, int insertAt) override
{
Q_UNUSED(insertAt);
overlapWidget->addWidget(toInsert);
}
void removeFromLayout(QWidget *toRemove) override
{
overlapWidget->removeWidget(toRemove);
}

View file

@ -43,29 +43,23 @@ DeckCardZoneDisplayWidget::DeckCardZoneDisplayWidget(QWidget *parent,
void DeckCardZoneDisplayWidget::cleanupInvalidCardGroup(CardGroupDisplayWidget *displayWidget)
{
qInfo() << "Cleaning up invalid card group " << displayWidget->cardGroupCategory << " from "
<< displayWidget->zoneName;
cardGroupLayout->removeWidget(displayWidget);
displayWidget->setParent(nullptr);
for (auto idx : indexToWidgetMap.keys()) {
if (!idx.isValid()) {
indexToWidgetMap.remove(idx);
}
}
displayWidget->deleteLater();
qInfo() << "Cleaned.";
delete displayWidget;
}
void DeckCardZoneDisplayWidget::constructAppropriateWidget(QPersistentModelIndex index)
{
auto categoryName = deckListModel->data(index.sibling(index.row(), 1), Qt::EditRole).toString();
if (indexToWidgetMap.contains(index)) {
qInfo() << categoryName << " is already contained in the index to widget map";
return;
} else {
qInfo() << categoryName << " needs a widget";
}
if (displayType == DisplayType::Overlap) {
qInfo() << "It's getting an overlap widget.";
auto *display_widget = new OverlappedCardGroupDisplayWidget(
cardGroupContainer, deckListModel, index, zoneName, categoryName, activeGroupCriteria, activeSortCriteria,
subBannerOpacity, cardSizeWidget);
@ -77,7 +71,6 @@ void DeckCardZoneDisplayWidget::constructAppropriateWidget(QPersistentModelIndex
cardGroupLayout->addWidget(display_widget);
indexToWidgetMap.insert(index, display_widget);
} else if (displayType == DisplayType::Flat) {
qInfo() << "Getting a flat widget for christmas";
auto *display_widget =
new FlatCardGroupDisplayWidget(cardGroupContainer, deckListModel, index, zoneName, categoryName,
activeGroupCriteria, activeSortCriteria, subBannerOpacity, cardSizeWidget);
@ -93,9 +86,6 @@ void DeckCardZoneDisplayWidget::constructAppropriateWidget(QPersistentModelIndex
void DeckCardZoneDisplayWidget::displayCards()
{
qInfo() << "Constructing Group Display Widgets for Zone Display widget";
qInfo() << deckListModel->data(trackedIndex.sibling(trackedIndex.row(), 1), Qt::EditRole).toString() << " has "
<< deckListModel->rowCount(trackedIndex.sibling(trackedIndex.row(), 0)) << " entries.";
for (int i = 0; i < deckListModel->rowCount(trackedIndex); ++i) {
QPersistentModelIndex index = QPersistentModelIndex(deckListModel->index(i, 0, trackedIndex));
constructAppropriateWidget(index);
@ -106,9 +96,9 @@ void DeckCardZoneDisplayWidget::onCategoryAddition(const QModelIndex &parent, in
{
if (!trackedIndex.isValid()) {
emit requestCleanup(this);
return;
}
if (parent == trackedIndex) {
qInfo() << deckListModel->data(trackedIndex.sibling(trackedIndex.row(), 1), Qt::EditRole).toString() << " zone thinks it has a new category";
for (int i = first; i <= last; i++) {
QPersistentModelIndex index = QPersistentModelIndex(deckListModel->index(i, 0, trackedIndex));

View file

@ -201,15 +201,13 @@ void VisualDeckEditorWidget::retranslateUi()
void VisualDeckEditorWidget::cleanupInvalidZones(DeckCardZoneDisplayWidget *displayWidget)
{
qInfo() << "Cleaning up invalid card zone " << displayWidget->zoneName;
zoneContainerLayout->removeWidget(displayWidget);
for (auto idx : indexToWidgetMap.keys()) {
if (!idx.isValid()) {
indexToWidgetMap.remove(idx);
}
}
displayWidget->deleteLater();
qInfo() << "Cleaned.";
delete displayWidget;
}
void VisualDeckEditorWidget::onCardAddition(const QModelIndex &parent, int first, int last)
@ -222,8 +220,6 @@ void VisualDeckEditorWidget::onCardAddition(const QModelIndex &parent, int first
continue;
}
qInfo() << "Created zone for " << deckListModel->data(index.sibling(index.row(), 1), Qt::EditRole).toString();
DeckCardZoneDisplayWidget *zoneDisplayWidget = new DeckCardZoneDisplayWidget(
zoneContainer, deckListModel, index, deckListModel->data(index.sibling(index.row(), 1), Qt::EditRole).toString(), activeGroupCriteria,
activeSortCriteria, currentDisplayType, 20, 10, cardSizeWidget);
@ -261,7 +257,6 @@ void VisualDeckEditorWidget::onCardRemoval(const QModelIndex &parent, int first,
void VisualDeckEditorWidget::constructZoneWidgetsFromDeckListModel()
{
qInfo() << "Constructing zone widgets";
for (int i = 0; i < deckListModel->rowCount(deckListModel->parent(QModelIndex())); i++) {
QPersistentModelIndex index = QPersistentModelIndex(deckListModel->index(i, 0, deckListModel->getRoot()));
@ -269,8 +264,6 @@ void VisualDeckEditorWidget::constructZoneWidgetsFromDeckListModel()
continue;
}
qInfo() << deckListModel->data(index.sibling(index.row(), 1), Qt::EditRole).toString();
DeckCardZoneDisplayWidget *zoneDisplayWidget = new DeckCardZoneDisplayWidget(
zoneContainer, deckListModel, index, deckListModel->data(index.sibling(index.row(), 1), Qt::EditRole).toString(), activeGroupCriteria,
activeSortCriteria, currentDisplayType, 20, 10, cardSizeWidget);

View file

@ -408,13 +408,14 @@ QModelIndex DeckListModel::addCard(const QString &cardName,
const auto cardSetName = cardInfoSet.getPtr().isNull() ? "" : cardInfoSet.getPtr()->getCorrectedShortName();
if (!cardNode) {
auto *decklistCard = deckList->addCard(cardInfo->getName(), zoneName, cardSetName,
cardInfoSet.getProperty("num"), cardInfoSet.getProperty("uuid"));
// Determine the correct index
int insertRow = findSortedInsertRow(cardTypeNode, cardNode);
int insertRow = findSortedInsertRow(cardTypeNode, cardInfo);
auto *decklistCard = deckList->addCard(cardInfo->getName(), zoneName, insertRow, cardSetName,
cardInfoSet.getProperty("num"), cardInfoSet.getProperty("uuid"));
beginInsertRows(parentIndex, insertRow, insertRow);
cardNode = new DecklistModelCardNode(decklistCard, cardTypeNode);
cardNode = new DecklistModelCardNode(decklistCard, cardTypeNode, insertRow);
endInsertRows();
} else {
cardNode->setNumber(cardNode->getNumber() + 1);
@ -428,14 +429,14 @@ QModelIndex DeckListModel::addCard(const QString &cardName,
return nodeToIndex(cardNode);
}
int DeckListModel::findSortedInsertRow(InnerDecklistNode *parent, AbstractDecklistNode *newNode) const
int DeckListModel::findSortedInsertRow(InnerDecklistNode *parent, CardInfoPtr cardInfo) const
{
auto *newCard = dynamic_cast<const DecklistModelCardNode *>(newNode);
if (!newCard)
if (!cardInfo) {
return parent->size(); // fallback: append at end
}
for (int i = 0; i < parent->size(); ++i) {
auto *existingCard = dynamic_cast<const DecklistModelCardNode *>(parent->at(i));
auto *existingCard = dynamic_cast<DecklistModelCardNode *>(parent->at(i));
if (!existingCard)
continue;
@ -443,14 +444,14 @@ int DeckListModel::findSortedInsertRow(InnerDecklistNode *parent, AbstractDeckli
switch (lastKnownColumn) {
case 0: // ByNumber
lessThan = lastKnownOrder == Qt::AscendingOrder
? newCard->getCardCollectorNumber() < existingCard->getCardCollectorNumber()
: newCard->getCardCollectorNumber() > existingCard->getCardCollectorNumber();
? cardInfo->getProperty("collectorNumber") < existingCard->getCardCollectorNumber()
: cardInfo->getProperty("collectorNumber") > existingCard->getCardCollectorNumber();
break;
case 1: // ByName
default:
lessThan = lastKnownOrder == Qt::AscendingOrder
? newCard->getName().localeAwareCompare(existingCard->getName()) < 0
: newCard->getName().localeAwareCompare(existingCard->getName()) > 0;
? cardInfo->getName().localeAwareCompare(existingCard->getName()) < 0
: cardInfo->getName().localeAwareCompare(existingCard->getName()) > 0;
break;
}

View file

@ -25,8 +25,8 @@ private:
DecklistCardNode *dataNode;
public:
DecklistModelCardNode(DecklistCardNode *_dataNode, InnerDecklistNode *_parent)
: AbstractDecklistCardNode(_parent), dataNode(_dataNode)
DecklistModelCardNode(DecklistCardNode *_dataNode, InnerDecklistNode *_parent, int position = -1)
: AbstractDecklistCardNode(_parent, position), dataNode(_dataNode)
{
}
int getNumber() const override
@ -115,7 +115,7 @@ public:
const CardInfoPerSet &cardInfoSet,
const QString &zoneName,
bool abAddAnyway = false);
int findSortedInsertRow(InnerDecklistNode *parent, AbstractDecklistNode *newNode) const;
int findSortedInsertRow(InnerDecklistNode *parent, CardInfoPtr cardInfo) const;
void sort(int column, Qt::SortOrder order) override;
void cleanList();
DeckLoader *getDeckList() const

View file

@ -72,7 +72,7 @@ void DeckStatsInterface::copyDeckWithoutTokens(DeckList &source, DeckList &desti
auto copyIfNotAToken = [this, &destination](const auto node, const auto card) {
CardInfoPtr dbCard = cardDatabase.getCard(card->getName());
if (dbCard && !dbCard->getIsToken()) {
DecklistCardNode *addedCard = destination.addCard(card->getName(), node->getName());
DecklistCardNode *addedCard = destination.addCard(card->getName(), node->getName(), -1);
addedCard->setNumber(card->getNumber());
}
};

View file

@ -71,10 +71,15 @@ void SideboardPlan::write(QXmlStreamWriter *xml)
xml->writeEndElement();
}
AbstractDecklistNode::AbstractDecklistNode(InnerDecklistNode *_parent) : parent(_parent), sortMethod(Default)
AbstractDecklistNode::AbstractDecklistNode(InnerDecklistNode *_parent, int position)
: parent(_parent), sortMethod(Default)
{
if (parent) {
parent->append(this);
if (position == -1) {
parent->append(this);
} else {
parent->insert(position, this);
}
}
}
@ -274,7 +279,7 @@ bool InnerDecklistNode::readElement(QXmlStreamReader *xml)
} else if (childName == "card") {
DecklistCardNode *newCard = new DecklistCardNode(
xml->attributes().value("name").toString(), xml->attributes().value("number").toString().toInt(),
this, xml->attributes().value("setShortName").toString(),
this, -1, xml->attributes().value("setShortName").toString(),
xml->attributes().value("collectorNumber").toString(), xml->attributes().value("uuid").toString());
newCard->readElement(xml);
}
@ -725,7 +730,7 @@ bool DeckList::loadFromStream_Plain(QTextStream &in, bool preserveMetadata)
QString zoneName = getCardZoneFromName(cardName, sideboard ? DECK_ZONE_SIDE : DECK_ZONE_MAIN);
// make new entry in decklist
new DecklistCardNode(cardName, amount, getZoneObjFromName(zoneName), setCode, collectorNumber);
new DecklistCardNode(cardName, amount, getZoneObjFromName(zoneName), -1, setCode, collectorNumber);
}
refreshDeckHash();
@ -856,6 +861,7 @@ int DeckList::getSideboardSize() const
DecklistCardNode *DeckList::addCard(const QString &cardName,
const QString &zoneName,
const int position,
const QString &cardSetName,
const QString &cardSetCollectorNumber,
const QString &cardProviderId)
@ -865,7 +871,8 @@ DecklistCardNode *DeckList::addCard(const QString &cardName,
zoneNode = new InnerDecklistNode(zoneName, root);
}
auto *node = new DecklistCardNode(cardName, 1, zoneNode, cardSetName, cardSetCollectorNumber, cardProviderId);
auto *node =
new DecklistCardNode(cardName, 1, zoneNode, position, cardSetName, cardSetCollectorNumber, cardProviderId);
refreshDeckHash();
return node;

View file

@ -56,7 +56,7 @@ protected:
DeckSortMethod sortMethod;
public:
explicit AbstractDecklistNode(InnerDecklistNode *_parent = nullptr);
explicit AbstractDecklistNode(InnerDecklistNode *_parent = nullptr, int position = -1);
virtual ~AbstractDecklistNode() = default;
virtual void setSortMethod(DeckSortMethod method)
{
@ -88,8 +88,8 @@ class InnerDecklistNode : public AbstractDecklistNode, public QList<AbstractDeck
class compareFunctor;
public:
explicit InnerDecklistNode(QString _name = QString(), InnerDecklistNode *_parent = nullptr)
: AbstractDecklistNode(_parent), name(std::move(_name))
explicit InnerDecklistNode(QString _name = QString(), InnerDecklistNode *_parent = nullptr, int position = -1)
: AbstractDecklistNode(_parent, position), name(std::move(_name))
{
}
explicit InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent = nullptr);
@ -153,7 +153,7 @@ public:
class AbstractDecklistCardNode : public AbstractDecklistNode
{
public:
explicit AbstractDecklistCardNode(InnerDecklistNode *_parent = nullptr) : AbstractDecklistNode(_parent)
explicit AbstractDecklistCardNode(InnerDecklistNode *_parent = nullptr, int position = -1) : AbstractDecklistNode(_parent, position)
{
}
virtual int getNumber() const = 0;
@ -190,10 +190,11 @@ public:
explicit DecklistCardNode(QString _name = QString(),
int _number = 1,
InnerDecklistNode *_parent = nullptr,
int position = -1,
QString _cardSetShortName = QString(),
QString _cardSetNumber = QString(),
QString _cardProviderId = QString())
: AbstractDecklistCardNode(_parent), name(std::move(_name)), number(_number),
: AbstractDecklistCardNode(_parent, position), name(std::move(_name)), number(_number),
cardSetShortName(std::move(_cardSetShortName)), cardSetNumber(std::move(_cardSetNumber)),
cardProviderId(std::move(_cardProviderId))
{
@ -373,6 +374,7 @@ public:
}
DecklistCardNode *addCard(const QString &cardName,
const QString &zoneName,
int position,
const QString &cardSetName = QString(),
const QString &cardSetCollectorNumber = QString(),
const QString &cardProviderId = QString());