Pokered Save Editor 2
Pokemon Red & Blue save file editor - Qt 6 C++/QML
Loading...
Searching...
No Matches
moveselectmodel.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 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 <QCollator>
24
25#include <pse-db/moves.h>
26#include <pse-db/pokemon.h>
28#include "./moveselectmodel.h"
29
34
36{
37 connect(this, &MoveSelectModel::monChanged, this, &MoveSelectModel::onMonChange);
39}
40
41int MoveSelectModel::rowCount(const QModelIndex& parent) const
42{
43 // Not a tree, just a list, there's no parent
44 Q_UNUSED(parent)
45
46 // Return list count
47 return moveListCache.size();
48}
49
50QVariant MoveSelectModel::data(const QModelIndex& index, int role) const
51{
52 // If index is invalid in any way, return nothing
53 if (!index.isValid())
54 return QVariant();
55
56 if (index.row() >= moveListCache.size())
57 return QVariant();
58
59 // Get Item from Item List Cache
60 auto item = moveListCache.at(index.row());
61
62 if(item == nullptr)
63 return QVariant();
64
65 // Now return requested information
66 if (role == IndRole)
67 return item->ind;
68 else if (role == NameRole)
69 return item->name;
70
71 // All else fails, return nothing
72 return QVariant();
73}
74
75QHash<int, QByteArray> MoveSelectModel::roleNames() const
76{
77 QHash<int, QByteArray> roles;
78
79 roles[IndRole] = "moveInd";
80 roles[NameRole] = "moveName";
81
82 return roles;
83}
84
86{
87 int ret = -1;
88
89 for(int i = 0; i < moveListCache.size(); i++) {
90 if(ind != moveListCache.at(i)->ind)
91 continue;
92
93 ret = i;
94 break;
95 }
96
97 return ret;
98}
99
101{
102 for(auto el : moveListCache)
103 delete el;
104
105 moveListCache.clear();
106
107 if(mon == nullptr)
109 else
111
112 beginResetModel();
113 endResetModel();
114}
115
117{
118 // Setup Collator
119 QCollator collator;
120 collator.setNumericMode(true);
121 collator.setIgnorePunctuation(true);
122
123 moveListCache.append(new MoveSelectEntry("", 0));
124
128
129 moveListCache.append(new MoveSelectEntry("--- Normal Moves ---", -1));
130
131 // Gather normal repeatable items and sort by name, then add into list
132 QVector<MoveDBEntry*> tmp;
133
134 for(auto el : MovesDB::inst()->getStore()) {
135 if(!el->glitch && !el->hm)
136 tmp.append(el);
137 }
138
139 std::sort(
140 tmp.begin(),
141 tmp.end(),
142 [&collator](const MoveDBEntry* mon1, const MoveDBEntry* mon2)
143 {
144 return collator.compare(mon1->readable, mon2->readable) < 0;
145 });
146
147 for(auto el : tmp) {
148 moveListCache.append(new MoveSelectEntry(el->readable, el->ind));
149 }
150
151 tmp.clear();
152
156
157 moveListCache.append(new MoveSelectEntry("--- HM Moves ---", -1));
158
159 for(auto el : MovesDB::inst()->getStore()) {
160 if(!el->glitch && el->hm)
161 tmp.append(el);
162 }
163
164 std::sort(
165 tmp.begin(),
166 tmp.end(),
167 [&collator](const MoveDBEntry* mon1, const MoveDBEntry* mon2)
168 {
169 return collator.compare(
170 "HM 0" + QString::number(*mon1->hm) + ": " + mon1->readable,
171 "HM 0" + QString::number(*mon2->hm) + ": " + mon2->readable) < 0;
172 });
173
174 for(auto el : tmp) {
176 "HM 0" + QString::number(*el->hm) + ": " + el->readable,
177 el->ind));
178 }
179
180 tmp.clear();
181
185
186 // Add first category
187 moveListCache.append(new MoveSelectEntry("--- Glitch Moves ---", -1));
188
189 for(auto el : MovesDB::inst()->getStore()) {
190 if(el->glitch)
191 tmp.append(el);
192 }
193
194 std::sort(
195 tmp.begin(),
196 tmp.end(),
197 [&collator](const MoveDBEntry* mon1, const MoveDBEntry* mon2)
198 {
199 return collator.compare(mon1->readable, mon2->readable) < 0;
200 });
201
202 for(auto el : tmp) {
203 moveListCache.append(new MoveSelectEntry(el->readable, el->ind));
204 }
205
206 tmp.clear();
207}
208
210{
211 if(mon == nullptr)
213
214 moveListCache.append(new MoveSelectEntry("", 0));
215
216 // Setup Collator
217 QCollator collator;
218 collator.setNumericMode(true);
219 collator.setIgnorePunctuation(true);
220
224
225 moveListCache.append(new MoveSelectEntry("--- Initial Moves ---", -1));
226
227 QVector<MoveSelectEntry*> tmp;
228 QVector<MoveDBEntry*> usedMoves;
229
230 for(auto monMove : mon->toInitial) {
231 if(usedMoves.contains(monMove))
232 continue;
233
234 tmp.append(new MoveSelectEntry(monMove->readable, monMove->ind));
235 usedMoves.append(monMove);
236 }
237
238 std::sort(
239 tmp.begin(),
240 tmp.end(),
241 [&collator](const MoveSelectEntry* mon1, const MoveSelectEntry* mon2)
242 {
243 return collator.compare(mon1->name, mon2->name) < 0;
244 });
245
246 if(tmp.size() == 0)
247 moveListCache.removeLast();
248
249 for(auto el : tmp) {
250 moveListCache.append(el);
251 }
252
253 tmp.clear();
254
258
259 moveListCache.append(new MoveSelectEntry("--- Learnable Moves ---", -1));
260
261 for(auto monMove : mon->moves) {
262 if(usedMoves.contains(monMove->toMove))
263 continue;
264
265 tmp.append(new MoveSelectEntry("Lv " + QString::number(monMove->level) + ": " + monMove->toMove->readable,
266 monMove->toMove->ind));
267 usedMoves.append(monMove->toMove);
268 }
269
270 std::sort(
271 tmp.begin(),
272 tmp.end(),
273 [&collator](const MoveSelectEntry* mon1, const MoveSelectEntry* mon2)
274 {
275 return collator.compare(mon1->name, mon2->name) < 0;
276 });
277
278 if(tmp.size() == 0)
279 moveListCache.removeLast();
280
281 for(auto el : tmp) {
282 moveListCache.append(el);
283 }
284
285 tmp.clear();
286
290
291 moveListCache.append(new MoveSelectEntry("--- Teachable Moves ---", -1));
292
293 for(auto monMove : mon->toTmHmMove) {
294 if(usedMoves.contains(monMove) || monMove->hm)
295 continue;
296
297 QString prefix;
298 if((*monMove->tm) < 10)
299 prefix += "TM 0" + QString::number(*monMove->tm) + ": ";
300 else
301 prefix += "TM " + QString::number(*monMove->tm) + ": ";
302
303 tmp.append(new MoveSelectEntry(prefix + monMove->readable,
304 monMove->ind));
305 usedMoves.append(monMove);
306 }
307
308 std::sort(
309 tmp.begin(),
310 tmp.end(),
311 [&collator](const MoveSelectEntry* mon1, const MoveSelectEntry* mon2)
312 {
313 return collator.compare(mon1->name, mon2->name) < 0;
314 });
315
316 bool tmEmpty = false;
317 if(tmp.size() == 0)
318 tmEmpty = true;
319
320 for(auto el : tmp) {
321 moveListCache.append(el);
322 }
323
324 tmp.clear();
325
326 for(auto monMove : mon->toTmHmMove) {
327 if(usedMoves.contains(monMove) || !monMove->hm)
328 continue;
329
330 QString prefix;
331 if(monMove->hm)
332 prefix += "HM 0" + QString::number(*monMove->hm) + ": ";
333
334 tmp.append(new MoveSelectEntry(prefix + monMove->readable,
335 monMove->ind));
336 usedMoves.append(monMove);
337 }
338
339 std::sort(
340 tmp.begin(),
341 tmp.end(),
342 [&collator](const MoveSelectEntry* mon1, const MoveSelectEntry* mon2)
343 {
344 return collator.compare(mon1->name, mon2->name) < 0;
345 });
346
347 if(tmp.size() == 0 && tmEmpty)
348 moveListCache.removeLast();
349
350 for(auto el : tmp) {
351 moveListCache.append(el);
352 }
353
354 tmp.clear();
355
359
360 moveListCache.append(new MoveSelectEntry("--- Incompatible Moves ---", -1));
361
362 for(auto monMove : MovesDB::inst()->getStore()) {
363 if(usedMoves.contains(monMove) || monMove->glitch || monMove->hm)
364 continue;
365
366 tmp.append(new MoveSelectEntry(monMove->readable,
367 monMove->ind));
368 usedMoves.append(monMove);
369 }
370
371 std::sort(
372 tmp.begin(),
373 tmp.end(),
374 [&collator](const MoveSelectEntry* mon1, const MoveSelectEntry* mon2)
375 {
376 return collator.compare(mon1->name, mon2->name) < 0;
377 });
378
379 bool otherMovesEmpty = false;
380 if(tmp.size() == 0)
381 otherMovesEmpty = true;
382
383 for(auto el : tmp) {
384 moveListCache.append(el);
385 }
386
387 tmp.clear();
388
389 for(auto monMove : MovesDB::inst()->getStore()) {
390 if(usedMoves.contains(monMove) || monMove->glitch || !monMove->hm)
391 continue;
392
393 QString prefix;
394 if(monMove->hm)
395 prefix += "HM 0" + QString::number(*monMove->hm) + ": ";
396
397 tmp.append(new MoveSelectEntry(prefix + monMove->readable,
398 monMove->ind));
399 usedMoves.append(monMove);
400 }
401
402 std::sort(
403 tmp.begin(),
404 tmp.end(),
405 [&collator](const MoveSelectEntry* mon1, const MoveSelectEntry* mon2)
406 {
407 return collator.compare(mon1->name, mon2->name) < 0;
408 });
409
410 if(tmp.size() == 0 && otherMovesEmpty)
411 moveListCache.removeLast();
412
413 for(auto el : tmp) {
414 moveListCache.append(el);
415 }
416
417 tmp.clear();
418
422
423 moveListCache.append(new MoveSelectEntry("--- Glitch Moves ---", -1));
424
425 for(auto monMove : MovesDB::inst()->getStore()) {
426 if(usedMoves.contains(monMove) || !monMove->glitch)
427 continue;
428
429 tmp.append(new MoveSelectEntry(monMove->readable,
430 monMove->ind));
431 usedMoves.append(monMove);
432 }
433
434 std::sort(
435 tmp.begin(),
436 tmp.end(),
437 [&collator](const MoveSelectEntry* mon1, const MoveSelectEntry* mon2)
438 {
439 return collator.compare(mon1->name, mon2->name) < 0;
440 });
441
442 if(tmp.size() == 0)
443 moveListCache.removeLast();
444
445 for(auto el : tmp) {
446 moveListCache.append(el);
447 }
448
449 tmp.clear();
450}
451
453{
454 if(box == nullptr ||
455 box->toData() == nullptr ||
456 !box->toData()->pokedex) {
457 mon = nullptr;
458 monChanged();
459 return;
460 }
461
462 mon = box->toData();
463 monChanged();
464}
QVector< MoveSelectEntry * > moveListCache
Cached picker rows.
void rebuildListGeneral()
Rebuild with all moves.
virtual QHash< int, QByteArray > roleNames() const override
Role -> QML name.
void rebuildListSpecific()
Rebuild with mon's legal moves only.
void monFromBox(PokemonBox *box)
Set mon from a QML-passed PokemonBox.
void onMonChange()
React to mon changing.
virtual int rowCount(const QModelIndex &parent) const override
Row count.
virtual QVariant data(const QModelIndex &index, int role) const override
Row+role value.
int moveToListIndex(int ind)
Row index for move ind.
PokemonDBEntry * mon
static MovesDB * inst()
< Number of moves.
Definition moves.cpp:72
A single Pokemon record – the most property-rich object in the tree.
Definition pokemonbox.h:213
PokemonDBEntry * toData()
The species' DB entry for this mon.
One move's static data (type, power, accuracy, PP, TM/HM), with links.
Definition moves.h:46
One move picker row: display name + move index.
MoveSelectEntry(QString name, int ind)
int ind
Move index.
QString name
Display name.
std::optional< var8 > pokedex
Pokedex number, if assigned.
Definition pokemon.h:115