1 /* Copyright (c) 2013-2019 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "BattleChipModel.h"
7
8 #include "ConfigController.h"
9 #include "GBAApp.h"
10
11 #include <QFile>
12 #include <QMimeData>
13 #include <QResource>
14
15 using namespace QGBA;
16
BattleChipModel(QObject * parent)17 BattleChipModel::BattleChipModel(QObject* parent)
18 : QAbstractListModel(parent)
19 {
20 QResource::registerResource(GBAApp::dataDir() + "/chips.rcc", "/exe");
21 QResource::registerResource(ConfigController::configDir() + "/chips.rcc", "/exe");
22 }
23
rowCount(const QModelIndex & parent) const24 int BattleChipModel::rowCount(const QModelIndex& parent) const {
25 if (parent.isValid()) {
26 return 0;
27 }
28 return m_deck.count();
29 }
30
data(const QModelIndex & index,int role) const31 QVariant BattleChipModel::data(const QModelIndex& index, int role) const {
32 const BattleChip& item = m_deck[index.row()];
33
34 switch (role) {
35 case Qt::DisplayRole:
36 return item.name;
37 case Qt::DecorationRole:
38 return item.icon.scaled(item.icon.size() * m_scale);
39 case Qt::UserRole:
40 return item.id;
41 }
42 return QVariant();
43 }
44
flags(const QModelIndex &) const45 Qt::ItemFlags BattleChipModel::flags(const QModelIndex&) const {
46 return Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren;
47 }
48
removeRows(int row,int count,const QModelIndex & parent)49 bool BattleChipModel::removeRows(int row, int count, const QModelIndex& parent) {
50 if (parent.isValid()) {
51 return false;
52 }
53 beginRemoveRows(QModelIndex(), row, row + count - 1);
54 for (int i = 0; i < count; ++i) {
55 m_deck.removeAt(row);
56 }
57 endRemoveRows();
58 return true;
59 }
60
mimeTypes() const61 QStringList BattleChipModel::mimeTypes() const {
62 return {"text/plain"};
63 }
64
supportedDropActions() const65 Qt::DropActions BattleChipModel::supportedDropActions() const {
66 return Qt::MoveAction;
67 }
68
mimeData(const QModelIndexList & indices) const69 QMimeData* BattleChipModel::mimeData(const QModelIndexList& indices) const {
70 QStringList deck;
71 for (const QModelIndex& index : indices) {
72 if (index.parent().isValid()) {
73 continue;
74 }
75 deck.append(QString::number(m_deck[index.row()].id));
76 }
77
78 QMimeData* mimeData = new QMimeData();
79 mimeData->setData("text/plain", deck.join(',').toLocal8Bit());
80 return mimeData;
81 }
82
dropMimeData(const QMimeData * data,Qt::DropAction,int row,int,const QModelIndex & parent)83 bool BattleChipModel::dropMimeData(const QMimeData* data, Qt::DropAction, int row, int, const QModelIndex& parent) {
84 if (parent.parent().isValid()) {
85 return false;
86 }
87 QStringList deck = QString::fromLocal8Bit(data->data("text/plain")).split(',');
88 if (deck.isEmpty()) {
89 return true;
90 }
91
92 row = parent.row();
93 beginInsertRows(QModelIndex(), row, row + deck.count() - 1);
94 for (int i = 0; i < deck.count(); ++i) {
95 int id = deck[i].toInt();
96 m_deck.insert(row + i, createChip(id));
97 }
98 endInsertRows();
99 return true;
100 }
101
setFlavor(int flavor)102 void BattleChipModel::setFlavor(int flavor) {
103 m_chipIdToName.clear();
104 if (flavor == GBA_FLAVOR_BEAST_LINK_GATE_US) {
105 flavor = GBA_FLAVOR_BEAST_LINK_GATE;
106 }
107 m_flavor = flavor;
108
109 QFile file(QString(":/exe/exe%1/chip-names.txt").arg(flavor));
110 file.open(QIODevice::ReadOnly | QIODevice::Text);
111 int id = 0;
112 while (true) {
113 QByteArray line = file.readLine();
114 if (line.isEmpty()) {
115 break;
116 }
117 ++id;
118 if (line.trimmed().isEmpty()) {
119 continue;
120 }
121 QString name = QString::fromUtf8(line).trimmed();
122 m_chipIdToName[id] = name;
123 }
124
125 }
126
addChip(int id)127 void BattleChipModel::addChip(int id) {
128 beginInsertRows(QModelIndex(), m_deck.count(), m_deck.count());
129 m_deck.append(createChip(id));
130 endInsertRows();
131 }
132
removeChip(const QModelIndex & index)133 void BattleChipModel::removeChip(const QModelIndex& index) {
134 beginRemoveRows(QModelIndex(), index.row(), index.row());
135 m_deck.removeAt(index.row());
136 endRemoveRows();
137 }
138
setChips(QList<int> ids)139 void BattleChipModel::setChips(QList<int> ids) {
140 beginResetModel();
141 m_deck.clear();
142 for (int id : ids) {
143 m_deck.append(createChip(id));
144 }
145 endResetModel();
146 }
147
clear()148 void BattleChipModel::clear() {
149 beginResetModel();
150 m_deck.clear();
151 endResetModel();
152 }
153
setScale(int scale)154 void BattleChipModel::setScale(int scale) {
155 m_scale = scale;
156 }
157
reloadAssets()158 void BattleChipModel::reloadAssets() {
159 QResource::unregisterResource(ConfigController::configDir() + "/chips.rcc", "/exe");
160 QResource::unregisterResource(GBAApp::dataDir() + "/chips.rcc", "/exe");
161
162 QResource::registerResource(GBAApp::dataDir() + "/chips.rcc", "/exe");
163 QResource::registerResource(ConfigController::configDir() + "/chips.rcc", "/exe");
164
165 emit layoutAboutToBeChanged();
166 setFlavor(m_flavor);
167 for (int i = 0; i < m_deck.count(); ++i) {
168 m_deck[i] = createChip(m_deck[i].id);
169 }
170 emit layoutChanged();
171 }
172
createChip(int id) const173 BattleChipModel::BattleChip BattleChipModel::createChip(int id) const {
174 QString path = QString(":/exe/exe%1/%2.png").arg(m_flavor).arg(id, 3, 10, QLatin1Char('0'));
175 if (!QFile(path).exists()) {
176 path = QString(":/exe/exe%1/placeholder.png").arg(m_flavor);
177 }
178 QPixmap icon(path);
179
180 BattleChip chip = {
181 id,
182 m_chipIdToName[id],
183 icon
184 };
185 return chip;
186 }
187