Pokered Save Editor 2
Pokemon Red & Blue save file editor - Qt 6 C++/QML
Loading...
Searching...
No Matches
itemoverviewmodel.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2026 Twilight
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15*/
16
21
22#include <algorithm>
23#include <QHash>
24#include <QSet>
25#include <QCollator>
26
27#include "./itemoverviewmodel.h"
31
33 : bag(bag),
34 storage(storage)
35{
36 // Stay live: any add/remove/move/amount-change on either box re-aggregates.
38 connect(this->storage, &ItemStorageBox::itemsChanged, this, &ItemOverviewModel::rebuild);
39
40 rebuild();
41}
42
43int ItemOverviewModel::rowCount(const QModelIndex& parent) const
44{
45 Q_UNUSED(parent)
46 return rows.size();
47}
48
49QVariant ItemOverviewModel::data(const QModelIndex& index, int role) const
50{
51 if(!index.isValid() || index.row() < 0 || index.row() >= rows.size())
52 return QVariant();
53
54 const Row& r = rows.at(index.row());
55
56 if(role == NameRole)
57 return r.name;
58 else if(role == BagCountRole)
59 return r.bag;
60 else if(role == StorageCountRole)
61 return r.storage;
62
63 return QVariant();
64}
65
66QHash<int, QByteArray> ItemOverviewModel::roleNames() const
67{
68 QHash<int, QByteArray> roles;
69 roles[NameRole] = "itemName";
70 roles[BagCountRole] = "bagCount";
71 roles[StorageCountRole] = "storageCount";
72 return roles;
73}
74
76{
77 beginResetModel();
78 rows.clear();
79
80 // Aggregate by item index, summing amounts across any duplicate rows (the
81 // editor supports a box holding the same item more than once). Iterate the
82 // BOXES (not the items DB) so glitch/unknown items present in the save still
83 // appear; resolve each name from the item itself.
84 QHash<int, int> bagAmt;
85 QHash<int, int> stoAmt;
86 QHash<int, QString> names;
87
88 auto collect = [&names](ItemStorageBox* box, QHash<int, int>& amt) {
89 if(box == nullptr)
90 return;
91 for(auto item : box->items) {
92 if(item == nullptr)
93 continue;
94 int ind = item->ind;
95 amt[ind] += item->amount;
96 if(!names.contains(ind)) {
97 auto entry = item->toItem();
98 names[ind] = (entry != nullptr) ? entry->getReadable() : QStringLiteral("???");
99 }
100 }
101 };
102
103 collect(bag, bagAmt);
104 collect(storage, stoAmt);
105
106 // Union of all item indices seen in either box.
107 QSet<int> inds;
108 for(auto it = bagAmt.constBegin(); it != bagAmt.constEnd(); ++it)
109 inds.insert(it.key());
110 for(auto it = stoAmt.constBegin(); it != stoAmt.constEnd(); ++it)
111 inds.insert(it.key());
112
113 for(int ind : inds) {
114 int b = bagAmt.value(ind, 0);
115 int s = stoAmt.value(ind, 0);
116
117 // Drop items that are effectively absent everywhere (e.g. a stray 0-amount
118 // row) -- a row only earns its place if the user actually holds some.
119 if(b <= 0 && s <= 0)
120 continue;
121
122 rows.append(Row{ names.value(ind, QStringLiteral("???")), b, s });
123 }
124
125 // Alphabetical, mirroring ItemStorageBox::sort (numeric-aware, punctuation-
126 // insensitive) so the table reads the same way regardless of either box's order.
127 QCollator collator;
128 collator.setNumericMode(true);
129 collator.setIgnorePunctuation(true);
130 std::sort(rows.begin(), rows.end(), [&collator](const Row& a, const Row& b) {
131 return collator.compare(a.name, b.name) < 0;
132 });
133
134 endResetModel();
135}
void rebuild()
Re-aggregate both boxes (full model reset). Wired to itemsChanged.
virtual int rowCount(const QModelIndex &parent) const override
Row count.
ItemOverviewModel(ItemStorageBox *bag, ItemStorageBox *storage)
virtual QVariant data(const QModelIndex &index, int role) const override
Row+role value.
virtual QHash< int, QByteArray > roleNames() const override
Role -> QML name.
@ StorageCountRole
Total amount in PC storage (0 if none).
@ BagCountRole
Total amount in the bag (0 if none).
@ NameRole
Display name.
A container of Items – either the trainer's bag or a PC item box.
QVector< Item * > items
The stored items.
void itemsChanged()
Box contents changed.