all repos — mgba @ 8dde1b565426b19c7ec16f60bce0401eca7b35a9

mGBA Game Boy Advance Emulator

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

  1/* Copyright (c) 2013-2016 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 "LibraryModel.h"
  7
  8#include <mgba-util/vfs.h>
  9
 10using namespace QGBA;
 11
 12Q_DECLARE_METATYPE(mLibraryEntry);
 13
 14LibraryModel::LibraryModel(const QString& path, QObject* parent)
 15	: QAbstractItemModel(parent)
 16{
 17	if (!path.isNull()) {
 18		m_library = mLibraryLoad(path.toUtf8().constData());
 19	} else {
 20		m_library = mLibraryCreateEmpty();
 21	}
 22	memset(&m_constraints, 0, sizeof(m_constraints));
 23	m_constraints.platform = PLATFORM_NONE;
 24
 25	if (!m_library) {
 26		return;
 27	}
 28	m_loader = new LibraryLoader(m_library);
 29	connect(m_loader, SIGNAL(directoryLoaded(const QString&)), this, SLOT(directoryLoaded(const QString&)));
 30	m_loader->moveToThread(&m_loaderThread);
 31	m_loaderThread.setObjectName("Library Loader Thread");
 32	m_loaderThread.start();
 33}
 34
 35LibraryModel::~LibraryModel() {
 36	clearConstraints();
 37	mLibraryDestroy(m_library);
 38	m_loaderThread.quit();
 39	m_loaderThread.wait();
 40}
 41
 42void LibraryModel::loadDirectory(const QString& path) {
 43	m_queue.append(path);
 44	QMetaObject::invokeMethod(m_loader, "loadDirectory", Q_ARG(const QString&, path));
 45}
 46
 47bool LibraryModel::entryAt(int row, mLibraryEntry* out) const {
 48	mLibraryListing entries;
 49	mLibraryListingInit(&entries, 0);
 50	if (!mLibraryGetEntries(m_library, &entries, 1, row, &m_constraints)) {
 51		mLibraryListingDeinit(&entries);
 52		return false;
 53	}
 54	*out = *mLibraryListingGetPointer(&entries, 0);
 55	mLibraryListingDeinit(&entries);
 56	return true;
 57}
 58
 59VFile* LibraryModel::openVFile(const QModelIndex& index) const {
 60	mLibraryEntry entry;
 61	if (!entryAt(index.row(), &entry)) {
 62		return nullptr;
 63	}
 64	return mLibraryOpenVFile(m_library, &entry);
 65}
 66
 67QVariant LibraryModel::data(const QModelIndex& index, int role) const {
 68	if (!index.isValid()) {
 69		return QVariant();
 70	}
 71	mLibraryEntry entry;
 72	if (!entryAt(index.row(), &entry)) {
 73		return QVariant();
 74	}
 75	if (role == Qt::UserRole) {
 76		return QVariant::fromValue(entry);
 77	}
 78	if (role != Qt::DisplayRole) {
 79		return QVariant();
 80	}
 81	switch (index.column()) {
 82	case 0:
 83		return entry.filename;
 84	case 1:
 85		return (unsigned long long) entry.filesize;
 86	}
 87	return QVariant();
 88}
 89
 90QVariant LibraryModel::headerData(int section, Qt::Orientation orientation, int role) const {
 91	if (role != Qt::DisplayRole) {
 92		return QAbstractItemModel::headerData(section, orientation, role);
 93	}
 94	if (orientation == Qt::Horizontal) {
 95		switch (section) {
 96		case 0:
 97			return tr("Filename");
 98		case 1:
 99			return tr("Size");
100		}
101	}
102	return section;
103}
104
105QModelIndex LibraryModel::index(int row, int column, const QModelIndex& parent) const {
106	if (parent.isValid()) {
107		return QModelIndex();
108	}
109	return createIndex(row, column, nullptr);
110}
111
112QModelIndex LibraryModel::parent(const QModelIndex&) const {
113	return QModelIndex();
114}
115
116int LibraryModel::columnCount(const QModelIndex& parent) const {
117	if (parent.isValid()) {
118		return 0;
119	}
120	return 2;
121}
122
123int LibraryModel::rowCount(const QModelIndex& parent) const {
124	if (parent.isValid()) {
125		return 0;
126	}
127	return mLibraryCount(m_library, &m_constraints);
128}
129
130void LibraryModel::constrainBase(const QString& path) {
131	if (m_constraints.base) {
132		free(const_cast<char*>(m_constraints.base));
133	}
134	m_constraints.base = strdup(path.toUtf8().constData());
135}
136
137void LibraryModel::clearConstraints() {
138	if (m_constraints.base) {
139		free(const_cast<char*>(m_constraints.base));
140	}
141	if (m_constraints.filename) {
142		free(const_cast<char*>(m_constraints.filename));
143	}
144	if (m_constraints.title) {
145		free(const_cast<char*>(m_constraints.title));
146	}
147	memset(&m_constraints, 0, sizeof(m_constraints));
148}
149
150void LibraryModel::directoryLoaded(const QString& path) {
151	m_queue.removeOne(path);
152	beginResetModel();
153	endResetModel();
154	if (m_queue.empty()) {
155		emit doneLoading();
156	}
157}
158
159LibraryLoader::LibraryLoader(mLibrary* library, QObject* parent)
160	: QObject(parent)
161	, m_library(library)
162{
163}
164
165void LibraryLoader::loadDirectory(const QString& path) {
166	mLibraryLoadDirectory(m_library, path.toUtf8().constData());
167	emit directoryLoaded(path);
168}