all repos — mgba @ 8c7d5b5b86652b92e30b7acf08ae103e950784ca

mGBA Game Boy Advance Emulator

src/platform/qt/CheatsModel.cpp (view raw)

  1/* Copyright (c) 2013-2015 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 "CheatsModel.h"
  7
  8#include <QFont>
  9
 10extern "C" {
 11#include "gba/cheats.h"
 12#include "util/vfs.h"
 13}
 14
 15using namespace QGBA;
 16
 17CheatsModel::CheatsModel(GBACheatDevice* device, QObject* parent)
 18	: QAbstractItemModel(parent)
 19	, m_device(device)
 20{
 21}
 22
 23QVariant CheatsModel::data(const QModelIndex& index, int role) const {
 24	if (!index.isValid()) {
 25		return QVariant();
 26	}
 27
 28	if (index.parent().isValid()) {
 29		int row = index.row();
 30		GBACheatSet* cheats = static_cast<GBACheatSet*>(index.internalPointer());
 31		const char* line = *StringListGetPointer(&cheats->lines, row);
 32		switch (role) {
 33		case Qt::DisplayRole:
 34			return line;
 35		case Qt::FontRole:
 36			return QFont("Courier New", 13);
 37		default:
 38			return QVariant();
 39		}
 40	}
 41
 42	int row = index.row();
 43	const GBACheatSet* cheats = *GBACheatSetsGetPointer(&m_device->cheats, index.row());
 44	switch (role) {
 45	case Qt::DisplayRole:
 46	case Qt::EditRole:
 47		return cheats->name ? cheats->name : tr("(untitled)");
 48	case Qt::CheckStateRole:
 49		return cheats->enabled ? Qt::Checked : Qt::Unchecked;
 50	default:
 51		return QVariant();
 52	}
 53}
 54
 55bool CheatsModel::setData(const QModelIndex& index, const QVariant& value, int role) {
 56	if (!index.isValid() || index.parent().isValid()) {
 57		return false;
 58	}
 59
 60	int row = index.row();
 61	GBACheatSet* cheats = *GBACheatSetsGetPointer(&m_device->cheats, index.row());
 62	switch (role) {
 63	case Qt::DisplayRole:
 64	case Qt::EditRole:
 65		if (cheats->name) {
 66			free(cheats->name);
 67			cheats->name = nullptr;
 68		}
 69		cheats->name = strdup(value.toString().toLocal8Bit().constData());
 70		emit dataChanged(index, index);
 71		return true;
 72	case Qt::CheckStateRole:
 73		cheats->enabled = value == Qt::Checked;
 74		emit dataChanged(index, index);
 75		return true;
 76	default:
 77		return false;
 78	}
 79}
 80
 81QModelIndex CheatsModel::index(int row, int column, const QModelIndex& parent) const {
 82	if (parent.isValid()) {
 83		return createIndex(row, column, *GBACheatSetsGetPointer(&m_device->cheats, parent.row()));
 84	} else {
 85		return createIndex(row, column, nullptr);
 86	}
 87}
 88
 89QModelIndex CheatsModel::parent(const QModelIndex& index) const {
 90	if (!index.isValid()) {
 91		return QModelIndex();
 92	}
 93	const GBACheatSet* cheats = static_cast<const GBACheatSet*>(index.internalPointer());
 94	if (!cheats) {
 95		return QModelIndex();
 96	}
 97	for (size_t i = 0; i < GBACheatSetsSize(&m_device->cheats); ++i) {
 98		if (cheats == *GBACheatSetsGetPointer(&m_device->cheats, i)) {
 99			return createIndex(i, 0, nullptr);
100		}
101	}
102	return QModelIndex();
103}
104
105Qt::ItemFlags CheatsModel::flags(const QModelIndex &index) const {
106	if (!index.isValid()) {
107		return 0;
108	}
109
110	if (index.parent().isValid()) {
111		return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
112	}
113
114	return Qt::ItemIsUserCheckable | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
115}
116
117int CheatsModel::columnCount(const QModelIndex& parent) const {
118	return 1;
119}
120
121int CheatsModel::rowCount(const QModelIndex& parent) const {
122	if (parent.isValid()) {
123		if (parent.internalPointer()) {
124			return 0;
125		}
126		const GBACheatSet* set = *GBACheatSetsGetPointer(&m_device->cheats, parent.row());
127		return StringListSize(&set->lines);
128	}
129	return GBACheatSetsSize(&m_device->cheats);
130}
131
132GBACheatSet* CheatsModel::itemAt(const QModelIndex& index) {
133	if (!index.isValid()) {
134		return nullptr;
135	}
136	if (index.parent().isValid()) {
137		return static_cast<GBACheatSet*>(index.internalPointer());
138	}
139	return *GBACheatSetsGetPointer(&m_device->cheats, index.row());
140}
141
142void CheatsModel::removeAt(const QModelIndex& index) {
143	if (!index.isValid() || index.parent().isValid()) {
144		return;
145	}
146	int row = index.row();
147	GBACheatSet* set = *GBACheatSetsGetPointer(&m_device->cheats, index.row());
148	beginRemoveRows(QModelIndex(), row, row);
149	GBACheatRemoveSet(m_device, set);
150	GBACheatSetDeinit(set);
151	delete set;
152	endInsertRows();
153
154}
155
156void CheatsModel::beginAppendRow(const QModelIndex& index) {
157	if (index.parent().isValid()) {
158		beginInsertRows(index.parent(), rowCount(index.parent()), rowCount(index.parent()));
159		return;
160	}
161	beginInsertRows(index, rowCount(index), rowCount(index));
162}
163
164void CheatsModel::endAppendRow() {
165	endInsertRows();
166}
167
168void CheatsModel::loadFile(const QString& path) {
169	VFile* vf = VFileOpen(path.toLocal8Bit().constData(), O_RDONLY);
170	if (!vf) {
171		return;
172	}
173	beginResetModel();
174	GBACheatParseFile(m_device, vf);
175	endResetModel();
176	vf->close(vf);
177}
178
179void CheatsModel::addSet(GBACheatSet* set) {
180	beginInsertRows(QModelIndex(), GBACheatSetsSize(&m_device->cheats), GBACheatSetsSize(&m_device->cheats));
181	GBACheatAddSet(m_device, set);
182	endInsertRows();
183}
184
185void CheatsModel::invalidated() {
186	beginResetModel();
187	endResetModel();
188}