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}