mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-23 10:05:10 -07:00
[Models] Mirror custom deck zones in the deck list model
DeckListModel now surfaces the custom zones from the deck tree so views can render and edit them alongside criteria groups. - rebuildTree mirrors each custom zone as a DecklistModelSubZoneNode under its board zone, cards flat inside (no further grouping). - The freshly built shadow tree is sorted while the model reset is still open, so views never observe unsorted intermediate order and proxies cannot desync. - Custom zones always sort after criteria groups within a board, regardless of their names. sortHelper remaps persistent indexes through the pre-shift rows to keep selections valid. - addCard inserts flat into a custom zone by name and keeps grouping by active criteria for board zones. findCardNode resolves cards in both layouts, legacy top-level zones unchanged. - New IsCustomZoneRole lets views tell zones apart from groups. - Empty custom zones survive row removal. Zone rows themselves are only mutable through the deck tree API. Took 5 minutes Took 20 minutes
This commit is contained in:
parent
0a09884c78
commit
f796e2e419
2 changed files with 209 additions and 27 deletions
|
|
@ -68,6 +68,16 @@ void DeckListModel::rebuildTree()
|
||||||
|
|
||||||
//! \todo Better sanity checking.
|
//! \todo Better sanity checking.
|
||||||
if (currentCard == nullptr) {
|
if (currentCard == nullptr) {
|
||||||
|
// Custom zones nested under the board zone are mirrored as-is,
|
||||||
|
// with their cards as direct children (no further grouping).
|
||||||
|
if (auto *customZone = dynamic_cast<InnerDecklistNode *>(currentZone->at(j))) {
|
||||||
|
auto *shadowZone = new DecklistModelSubZoneNode(customZone->getName(), node);
|
||||||
|
for (int k = 0; k < customZone->size(); k++) {
|
||||||
|
if (auto *customCard = dynamic_cast<DecklistCardNode *>(customZone->at(k))) {
|
||||||
|
new DecklistModelCardNode(customCard, shadowZone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,6 +94,13 @@ void DeckListModel::rebuildTree()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The shadow tree was built in deck file order. Apply the active sort while
|
||||||
|
// the reset is still open so every consumer (tree view and visual editor)
|
||||||
|
// sees the canonical order from the start. sortShadowTree emits no signals,
|
||||||
|
// which is only valid before endResetModel closes the reset.
|
||||||
|
root->setSortMethod(lastKnownColumn == 0 ? DeckSortMethod::ByNumber : DeckSortMethod::ByName);
|
||||||
|
sortShadowTree(root, lastKnownOrder);
|
||||||
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
|
||||||
refreshCardFormatLegalities();
|
refreshCardFormatLegalities();
|
||||||
|
|
@ -154,6 +171,9 @@ QVariant DeckListModel::data(const QModelIndex &index, int role) const
|
||||||
case DeckRoles::IsLegalRole:
|
case DeckRoles::IsLegalRole:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case DeckRoles::IsCustomZoneRole:
|
||||||
|
return dynamic_cast<const DecklistModelSubZoneNode *>(group) != nullptr;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
@ -190,6 +210,10 @@ QVariant DeckListModel::data(const QModelIndex &index, int role) const
|
||||||
return card->getFormatLegality();
|
return card->getFormatLegality();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case DeckRoles::IsCustomZoneRole: {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
@ -327,6 +351,13 @@ bool DeckListModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Custom zone rows are managed through the deck tree, never removed as model rows.
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (dynamic_cast<DecklistModelSubZoneNode *>(node->at(row + i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
beginRemoveRows(parent, row, row + count - 1);
|
beginRemoveRows(parent, row, row + count - 1);
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
AbstractDecklistNode *toDelete = node->takeAt(row);
|
AbstractDecklistNode *toDelete = node->takeAt(row);
|
||||||
|
|
@ -337,7 +368,8 @@ bool DeckListModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||||
}
|
}
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
|
|
||||||
if (node->empty() && (node != root)) {
|
// Empty criteria groups get pruned, but custom zones stay until explicitly deleted.
|
||||||
|
if (node->empty() && (node != root) && !dynamic_cast<DecklistModelSubZoneNode *>(node)) {
|
||||||
removeRows(parent.row(), 1, parent.parent());
|
removeRows(parent.row(), 1, parent.parent());
|
||||||
} else {
|
} else {
|
||||||
emitRecursiveUpdates(parent);
|
emitRecursiveUpdates(parent);
|
||||||
|
|
@ -365,24 +397,41 @@ DecklistModelCardNode *DeckListModel::findCardNode(const QString &cardName,
|
||||||
const QString &providerId,
|
const QString &providerId,
|
||||||
const QString &cardNumber) const
|
const QString &cardNumber) const
|
||||||
{
|
{
|
||||||
InnerDecklistNode *zoneNode = dynamic_cast<InnerDecklistNode *>(root->findChild(zoneName));
|
|
||||||
if (!zoneNode) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(cardName);
|
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(cardName);
|
||||||
if (!info) {
|
if (!info) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString groupCriteria = extractGroupCriteriaValue(info, activeGroupCriteria);
|
// 1. Board zone lookup: search the criteria groups, then the custom zones
|
||||||
InnerDecklistNode *groupNode = dynamic_cast<InnerDecklistNode *>(zoneNode->findChild(groupCriteria));
|
// nested under the board.
|
||||||
if (!groupNode) {
|
if (auto *zoneNode = dynamic_cast<InnerDecklistNode *>(root->findChild(zoneName))) {
|
||||||
return nullptr;
|
QString groupCriteria = extractGroupCriteriaValue(info, activeGroupCriteria);
|
||||||
|
if (auto *groupNode = dynamic_cast<InnerDecklistNode *>(zoneNode->findChild(groupCriteria))) {
|
||||||
|
if (auto *card = dynamic_cast<DecklistModelCardNode *>(
|
||||||
|
groupNode->findCardChildByNameProviderIdAndNumber(cardName, providerId, cardNumber))) {
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto *child : *zoneNode) {
|
||||||
|
auto *customZone = dynamic_cast<DecklistModelSubZoneNode *>(child);
|
||||||
|
if (!customZone) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (auto *card = dynamic_cast<DecklistModelCardNode *>(
|
||||||
|
customZone->findCardChildByNameProviderIdAndNumber(cardName, providerId, cardNumber))) {
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dynamic_cast<DecklistModelCardNode *>(
|
// 2. Custom zone lookup by name (custom zone names are deck-unique).
|
||||||
groupNode->findCardChildByNameProviderIdAndNumber(cardName, providerId, cardNumber));
|
if (auto *customZone = findSubZoneNodeByName(zoneName)) {
|
||||||
|
return dynamic_cast<DecklistModelCardNode *>(
|
||||||
|
customZone->findCardChildByNameProviderIdAndNumber(cardName, providerId, cardNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex DeckListModel::findCard(const QString &cardName,
|
QModelIndex DeckListModel::findCard(const QString &cardName,
|
||||||
|
|
@ -398,6 +447,25 @@ QModelIndex DeckListModel::findCard(const QString &cardName,
|
||||||
return nodeToIndex(cardNode);
|
return nodeToIndex(cardNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DecklistModelSubZoneNode *DeckListModel::findSubZoneNodeByName(const QString &zoneName) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < root->size(); i++) {
|
||||||
|
auto *boardZone = dynamic_cast<InnerDecklistNode *>(root->at(i));
|
||||||
|
if (!boardZone) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < boardZone->size(); j++) {
|
||||||
|
auto *customZone = dynamic_cast<DecklistModelSubZoneNode *>(boardZone->at(j));
|
||||||
|
if (customZone && customZone->getName() == zoneName) {
|
||||||
|
return customZone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
QModelIndex DeckListModel::addPreferredPrintingCard(const QString &cardName, const QString &zoneName, bool abAddAnyway)
|
QModelIndex DeckListModel::addPreferredPrintingCard(const QString &cardName, const QString &zoneName, bool abAddAnyway)
|
||||||
{
|
{
|
||||||
ExactCard card = CardDatabaseManager::query()->getCard({cardName});
|
ExactCard card = CardDatabaseManager::query()->getCard({cardName});
|
||||||
|
|
@ -423,29 +491,43 @@ QModelIndex DeckListModel::addCard(const ExactCard &card, const QString &zoneNam
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
InnerDecklistNode *zoneNode = createNodeIfNeeded(zoneName, root);
|
|
||||||
|
|
||||||
CardInfoPtr cardInfo = card.getCardPtr();
|
CardInfoPtr cardInfo = card.getCardPtr();
|
||||||
PrintingInfo printingInfo = card.getPrinting();
|
PrintingInfo printingInfo = card.getPrinting();
|
||||||
|
|
||||||
QString groupCriteria = extractGroupCriteriaValue(cardInfo, activeGroupCriteria);
|
InnerDecklistNode *cardParent = nullptr;
|
||||||
InnerDecklistNode *groupNode = createNodeIfNeeded(groupCriteria, zoneNode);
|
|
||||||
|
|
||||||
const QModelIndex parentIndex = nodeToIndex(groupNode);
|
auto *boardNode = dynamic_cast<InnerDecklistNode *>(root->findChild(zoneName));
|
||||||
auto *cardNode = dynamic_cast<DecklistModelCardNode *>(groupNode->findCardChildByNameProviderIdAndNumber(
|
auto *customZoneNode = boardNode ? nullptr : findSubZoneNodeByName(zoneName);
|
||||||
|
|
||||||
|
if (boardNode) {
|
||||||
|
// Board zone: cards are grouped by the active criteria.
|
||||||
|
QString groupCriteria = extractGroupCriteriaValue(cardInfo, activeGroupCriteria);
|
||||||
|
cardParent = createNodeIfNeeded(groupCriteria, boardNode);
|
||||||
|
} else if (customZoneNode) {
|
||||||
|
// Custom zone: cards live flat inside the zone.
|
||||||
|
cardParent = customZoneNode;
|
||||||
|
} else {
|
||||||
|
// Unknown zone: create a top-level zone (legacy behavior).
|
||||||
|
QString groupCriteria = extractGroupCriteriaValue(cardInfo, activeGroupCriteria);
|
||||||
|
auto *newZone = createNodeIfNeeded(zoneName, root);
|
||||||
|
cardParent = createNodeIfNeeded(groupCriteria, newZone);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QModelIndex parentIndex = nodeToIndex(cardParent);
|
||||||
|
auto *cardNode = dynamic_cast<DecklistModelCardNode *>(cardParent->findCardChildByNameProviderIdAndNumber(
|
||||||
card.getName(), printingInfo.getUuid(), printingInfo.getProperty("num")));
|
card.getName(), printingInfo.getUuid(), printingInfo.getProperty("num")));
|
||||||
const auto cardSetName = printingInfo.getSet().isNull() ? "" : printingInfo.getSet()->getCorrectedShortName();
|
const auto cardSetName = printingInfo.getSet().isNull() ? "" : printingInfo.getSet()->getCorrectedShortName();
|
||||||
|
|
||||||
bool cardNodeAdded = false;
|
bool cardNodeAdded = false;
|
||||||
if (!cardNode) {
|
if (!cardNode) {
|
||||||
// Determine the correct index
|
// Determine the correct index
|
||||||
int insertRow = findSortedInsertRow(groupNode, cardInfo);
|
int insertRow = findSortedInsertRow(cardParent, cardInfo);
|
||||||
|
|
||||||
auto *decklistCard = deckList->addCard(cardInfo->getName(), zoneName, insertRow, cardSetName,
|
auto *decklistCard = deckList->addCard(cardInfo->getName(), zoneName, insertRow, cardSetName,
|
||||||
printingInfo.getProperty("num"), printingInfo.getProperty("uuid"));
|
printingInfo.getProperty("num"), printingInfo.getProperty("uuid"));
|
||||||
|
|
||||||
beginInsertRows(parentIndex, insertRow, insertRow);
|
beginInsertRows(parentIndex, insertRow, insertRow);
|
||||||
cardNode = new DecklistModelCardNode(decklistCard, groupNode, insertRow);
|
cardNode = new DecklistModelCardNode(decklistCard, cardParent, insertRow);
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
|
|
||||||
cardNodeAdded = true;
|
cardNodeAdded = true;
|
||||||
|
|
@ -576,21 +658,76 @@ QModelIndex DeckListModel::nodeToIndex(AbstractDecklistNode *node) const
|
||||||
return createIndex(node->getParent()->indexOf(node), 0, node);
|
return createIndex(node->getParent()->indexOf(node), 0, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Moves custom zones of a board zone after the criteria groups, stably.
|
||||||
|
*
|
||||||
|
* Sorting would interleave custom zones with criteria groups by name; custom
|
||||||
|
* zones must always stay after the groups, regardless of their names.
|
||||||
|
*/
|
||||||
|
void DeckListModel::shiftCustomZonesToEnd(InnerDecklistNode *boardZone)
|
||||||
|
{
|
||||||
|
QList<AbstractDecklistNode *> customZones;
|
||||||
|
for (int i = boardZone->size() - 1; i >= 0; --i) {
|
||||||
|
if (dynamic_cast<DecklistModelSubZoneNode *>(boardZone->at(i))) {
|
||||||
|
customZones.prepend(boardZone->takeAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto *customZone : customZones) {
|
||||||
|
boardZone->append(customZone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sorts a freshly built shadow subtree without emitting model signals.
|
||||||
|
*
|
||||||
|
* Used by rebuildTree while the model reset is still open (emitting layout
|
||||||
|
* changes during a reset is invalid). Mirrors the reordering part of
|
||||||
|
* sortHelper: sort every node, then move board-level custom zones after groups.
|
||||||
|
*/
|
||||||
|
void DeckListModel::sortShadowTree(InnerDecklistNode *node, Qt::SortOrder order)
|
||||||
|
{
|
||||||
|
node->sort(order);
|
||||||
|
|
||||||
|
if (node != root && node->getParent() == root) {
|
||||||
|
shiftCustomZonesToEnd(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = node->size() - 1; i >= 0; --i) {
|
||||||
|
if (auto *subNode = dynamic_cast<InnerDecklistNode *>(node->at(i))) {
|
||||||
|
sortShadowTree(subNode, order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DeckListModel::sortHelper(InnerDecklistNode *node, Qt::SortOrder order)
|
void DeckListModel::sortHelper(InnerDecklistNode *node, Qt::SortOrder order)
|
||||||
{
|
{
|
||||||
// Sort children of node and save the information needed to
|
// Sort children of node and save the information needed to
|
||||||
// update the list of persistent indexes.
|
// update the list of persistent indexes.
|
||||||
QVector<QPair<int, int>> sortResult = node->sort(order);
|
QVector<QPair<int, int>> sortResult = node->sort(order);
|
||||||
|
|
||||||
|
// For board zones, custom zones must stay after the criteria groups,
|
||||||
|
// regardless of their names. Shift them to the end (stable).
|
||||||
|
QHash<AbstractDecklistNode *, int> rowAfterSort;
|
||||||
|
bool isBoardZone = (node != root) && (node->getParent() == root);
|
||||||
|
if (isBoardZone) {
|
||||||
|
for (int i = 0; i < node->size(); ++i) {
|
||||||
|
rowAfterSort.insert(node->at(i), i);
|
||||||
|
}
|
||||||
|
shiftCustomZonesToEnd(node);
|
||||||
|
}
|
||||||
|
|
||||||
QModelIndexList from, to;
|
QModelIndexList from, to;
|
||||||
int columns = columnCount();
|
int columns = columnCount();
|
||||||
for (int i = sortResult.size() - 1; i >= 0; --i) {
|
for (int newRow = 0; newRow < node->size(); ++newRow) {
|
||||||
const int fromRow = sortResult[i].first;
|
AbstractDecklistNode *temp = node->at(newRow);
|
||||||
const int toRow = sortResult[i].second;
|
int preSortRow = sortResult.value(newRow).first;
|
||||||
AbstractDecklistNode *temp = node->at(toRow);
|
if (isBoardZone) {
|
||||||
|
const int rowAfterSortOfNode = rowAfterSort.value(temp, newRow);
|
||||||
|
preSortRow = sortResult.value(rowAfterSortOfNode).first;
|
||||||
|
}
|
||||||
for (int j = 0; j < columns; ++j) {
|
for (int j = 0; j < columns; ++j) {
|
||||||
from << createIndex(fromRow, j, temp);
|
from << createIndex(preSortRow, j, temp);
|
||||||
to << createIndex(toRow, j, temp);
|
to << createIndex(newRow, j, temp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
changePersistentIndexList(from, to);
|
changePersistentIndexList(from, to);
|
||||||
|
|
@ -704,6 +841,15 @@ QList<QString> DeckListModel::getZones() const
|
||||||
return zones;
|
return zones;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList DeckListModel::getCustomZoneNames(const QString &boardZoneName) const
|
||||||
|
{
|
||||||
|
QStringList zoneNames;
|
||||||
|
for (const auto *customZone : deckList->getTree()->getCustomZones(boardZoneName)) {
|
||||||
|
zoneNames.append(customZone->getName());
|
||||||
|
}
|
||||||
|
return zoneNames;
|
||||||
|
}
|
||||||
|
|
||||||
static int maxAllowedForLegality(const FormatRules &format, const QString &legality)
|
static int maxAllowedForLegality(const FormatRules &format, const QString &legality)
|
||||||
{
|
{
|
||||||
for (const AllowedCount &c : format.allowedCounts) {
|
for (const AllowedCount &c : format.allowedCounts) {
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,8 @@ enum
|
||||||
{
|
{
|
||||||
IsCardRole = Qt::UserRole + 1, /**< Indicates whether the item represents a card. */
|
IsCardRole = Qt::UserRole + 1, /**< Indicates whether the item represents a card. */
|
||||||
DepthRole, /**< Depth level within the deck's grouping hierarchy. */
|
DepthRole, /**< Depth level within the deck's grouping hierarchy. */
|
||||||
IsLegalRole /**< Whether the card is legal in the current deck format. */
|
IsLegalRole, /**< Whether the card is legal in the current deck format. */
|
||||||
|
IsCustomZoneRole /**< Whether the item represents a custom zone nested under a board zone. */
|
||||||
};
|
};
|
||||||
} // namespace DeckRoles
|
} // namespace DeckRoles
|
||||||
|
|
||||||
|
|
@ -190,6 +191,21 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class DecklistModelSubZoneNode
|
||||||
|
* @ingroup DeckModels
|
||||||
|
* @brief Model node representing a custom zone nested under a board zone.
|
||||||
|
*
|
||||||
|
* Custom zones group cards by user-defined names (e.g. "Removal", "Utility")
|
||||||
|
* inside a board zone. They are mirrored from the underlying deck tree so that
|
||||||
|
* they can be told apart from criteria group nodes.
|
||||||
|
*/
|
||||||
|
class DecklistModelSubZoneNode : public InnerDecklistNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using InnerDecklistNode::InnerDecklistNode;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class DeckListModel
|
* @class DeckListModel
|
||||||
* @ingroup DeckModels
|
* @ingroup DeckModels
|
||||||
|
|
@ -391,6 +407,14 @@ public:
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] QList<QString> getZones() const;
|
[[nodiscard]] QList<QString> getZones() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the names of the custom zones nested under the given board zone.
|
||||||
|
*
|
||||||
|
* @param boardZoneName The board zone to query (main/side/maybeboard)
|
||||||
|
* @return The custom zone names, in deck order
|
||||||
|
*/
|
||||||
|
[[nodiscard]] QStringList getCustomZoneNames(const QString &boardZoneName) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSharedPointer<DeckList> deckList; /**< Pointer to the decklist providing the underlying data. */
|
QSharedPointer<DeckList> deckList; /**< Pointer to the decklist providing the underlying data. */
|
||||||
InnerDecklistNode *root; /**< Root node of the model tree. */
|
InnerDecklistNode *root; /**< Root node of the model tree. */
|
||||||
|
|
@ -405,6 +429,16 @@ private:
|
||||||
const QString &providerId = "",
|
const QString &providerId = "",
|
||||||
const QString &cardNumber = "") const;
|
const QString &cardNumber = "") const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finds a custom zone node in the model tree by name.
|
||||||
|
*
|
||||||
|
* Custom zone names are unique across the whole deck.
|
||||||
|
*
|
||||||
|
* @param zoneName Name of the custom zone.
|
||||||
|
* @return The custom zone node, or nullptr if not found.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] DecklistModelSubZoneNode *findSubZoneNodeByName(const QString &zoneName) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Determines the sorted insertion row for a card.
|
* @brief Determines the sorted insertion row for a card.
|
||||||
* @param parent The parent node where the card will be inserted.
|
* @param parent The parent node where the card will be inserted.
|
||||||
|
|
@ -427,6 +461,8 @@ private:
|
||||||
void emitRecursiveUpdates(const QModelIndex &index);
|
void emitRecursiveUpdates(const QModelIndex &index);
|
||||||
|
|
||||||
void sortHelper(InnerDecklistNode *node, Qt::SortOrder order);
|
void sortHelper(InnerDecklistNode *node, Qt::SortOrder order);
|
||||||
|
void sortShadowTree(InnerDecklistNode *node, Qt::SortOrder order);
|
||||||
|
void shiftCustomZonesToEnd(InnerDecklistNode *boardZone);
|
||||||
|
|
||||||
template <typename T> T getNode(const QModelIndex &index) const
|
template <typename T> T getNode(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue