Qt: Refactor out library viewer
Vicki Pfau vi@endrift.com
Tue, 24 Jan 2017 16:04:18 -0800
9 files changed,
230 insertions(+),
59 deletions(-)
jump to
M
src/platform/qt/ArchiveInspector.cpp
→
src/platform/qt/ArchiveInspector.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016 Jeffrey Pfau +/* Copyright (c) 2013-2017 Jeffrey Pfau * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this@@ -7,27 +7,19 @@ #include "ArchiveInspector.h"
#include <mgba-util/vfs.h> -#include "ConfigController.h" - using namespace QGBA; ArchiveInspector::ArchiveInspector(const QString& filename, QWidget* parent) : QDialog(parent) - , m_model(ConfigController::configDir() + "/library.sqlite3") { m_ui.setupUi(this); - connect(&m_model, &LibraryModel::doneLoading, [this]() { + connect(m_ui.archiveView, &LibraryView::doneLoading, [this]() { m_ui.loading->hide(); }); - m_model.loadDirectory(filename); - m_model.constrainBase(filename); - m_ui.archiveListing->setModel(&m_model); + connect(m_ui.archiveView, SIGNAL(accepted()), this, SIGNAL(accepted())); + m_ui.archiveView->setDirectory(filename); } VFile* ArchiveInspector::selectedVFile() const { - QModelIndex index = m_ui.archiveListing->selectionModel()->currentIndex(); - if (!index.isValid()) { - return nullptr; - } - return m_model.openVFile(index); + return m_ui.archiveView->selectedVFile(); }
M
src/platform/qt/ArchiveInspector.h
→
src/platform/qt/ArchiveInspector.h
@@ -1,12 +1,10 @@
-/* Copyright (c) 2013-2016 Jeffrey Pfau +/* Copyright (c) 2013-2017 Jeffrey Pfau * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef QGBA_ARCHIVE_INSPECTOR #define QGBA_ARCHIVE_INSPECTOR - -#include "LibraryModel.h" #include "ui_ArchiveInspector.h"@@ -24,8 +22,6 @@ VFile* selectedVFile() const;
private: Ui::ArchiveInspector m_ui; - - LibraryModel m_model; }; }
M
src/platform/qt/ArchiveInspector.ui
→
src/platform/qt/ArchiveInspector.ui
@@ -6,33 +6,41 @@ <property name="geometry">
<rect> <x>0</x> <y>0</y> - <width>400</width> - <height>300</height> + <width>600</width> + <height>400</height> </rect> </property> <property name="windowTitle"> <string>Open in archive...</string> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="2" column="1"> + <item row="1" column="0"> + <widget class="QLabel" name="loading"> + <property name="text"> + <string>Loading...</string> + </property> + </widget> + </item> + <item row="1" column="1"> <widget class="QDialogButtonBox" name="buttonBox"> <property name="standardButtons"> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Open</set> </property> </widget> </item> - <item row="2" column="0"> - <widget class="QLabel" name="loading"> - <property name="text"> - <string>Loading...</string> - </property> - </widget> - </item> <item row="0" column="0" colspan="2"> - <widget class="QListView" name="archiveListing"/> + <widget class="QGBA::LibraryView" name="archiveView" native="true"/> </item> </layout> </widget> + <customwidgets> + <customwidget> + <class>QGBA::LibraryView</class> + <extends>QWidget</extends> + <header>LibraryView.h</header> + <container>1</container> + </customwidget> + </customwidgets> <resources/> <connections> <connection>@@ -60,22 +68,6 @@ <hints>
<hint type="sourcelabel"> <x>199</x> <y>279</y> - </hint> - <hint type="destinationlabel"> - <x>199</x> - <y>149</y> - </hint> - </hints> - </connection> - <connection> - <sender>archiveListing</sender> - <signal>doubleClicked(QModelIndex)</signal> - <receiver>ArchiveInspector</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>199</x> - <y>129</y> </hint> <hint type="destinationlabel"> <x>199</x>
M
src/platform/qt/CMakeLists.txt
→
src/platform/qt/CMakeLists.txt
@@ -120,6 +120,7 @@ CheatsView.ui
DebuggerConsole.ui GIFView.ui IOViewer.ui + LibraryView.ui LoadSaveState.ui LogView.ui MemoryView.ui@@ -191,7 +192,8 @@
if(USE_SQLITE3) list(APPEND SOURCE_FILES ArchiveInspector.cpp - LibraryModel.cpp) + LibraryModel.cpp + LibraryView.cpp) endif() qt5_add_resources(RESOURCES resources.qrc)
M
src/platform/qt/LibraryModel.cpp
→
src/platform/qt/LibraryModel.cpp
@@ -5,15 +5,61 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "LibraryModel.h" +#include <QFontMetrics> + #include <mgba-util/vfs.h> using namespace QGBA; Q_DECLARE_METATYPE(mLibraryEntry); +QMap<QString, LibraryModel::LibraryColumn> LibraryModel::s_columns; + LibraryModel::LibraryModel(const QString& path, QObject* parent) : QAbstractItemModel(parent) { + if (s_columns.empty()) { + s_columns["filename"] = { + tr("Filename"), + [](const mLibraryEntry& e) -> QString { + return e.filename; + } + }; + s_columns["size"] = { + tr("Size"), + [](const mLibraryEntry& e) -> QString { + double size = e.filesize; + QString unit = "B"; + if (size > 1024.0) { + size /= 1024.0; + unit = "kiB"; + } + if (size > 1024.0) { + size /= 1024.0; + unit = "MiB"; + } + return QString("%0 %1").arg(size, 0, 'f', 1).arg(unit); + } + }; + s_columns["platform"] = { + tr("Platform"), + [](const mLibraryEntry& e) -> QString { + int platform = e.platform; + switch (platform) { +#ifdef M_CORE_GBA + case PLATFORM_GBA: + return tr("GBA"); +#endif +#ifdef M_CORE_GB + case PLATFORM_GB: + return tr("GB"); +#endif + default: + return tr("?"); + } + } + }; + } if (!path.isNull()) { m_library = mLibraryLoad(path.toUtf8().constData()); } else {@@ -21,6 +67,9 @@ m_library = mLibraryCreateEmpty();
} memset(&m_constraints, 0, sizeof(m_constraints)); m_constraints.platform = PLATFORM_NONE; + m_columns.append(s_columns["filename"]); + m_columns.append(s_columns["platform"]); + m_columns.append(s_columns["size"]); if (!m_library) { return;@@ -75,16 +124,19 @@ }
if (role == Qt::UserRole) { return QVariant::fromValue(entry); } - if (role != Qt::DisplayRole) { + if (index.column() >= m_columns.count()) { return QVariant(); } - switch (index.column()) { - case 0: - return entry.filename; - case 1: - return (unsigned long long) entry.filesize; + switch (role) { + case Qt::DisplayRole: + return m_columns[index.column()].value(entry); + case Qt::SizeHintRole: { + QFontMetrics fm((QFont())); + return fm.size(Qt::TextSingleLine, m_columns[index.column()].value(entry)); } - return QVariant(); + default: + return QVariant(); + } } QVariant LibraryModel::headerData(int section, Qt::Orientation orientation, int role) const {@@ -92,12 +144,10 @@ if (role != Qt::DisplayRole) {
return QAbstractItemModel::headerData(section, orientation, role); } if (orientation == Qt::Horizontal) { - switch (section) { - case 0: - return tr("Filename"); - case 1: - return tr("Size"); + if (section >= m_columns.count()) { + return QVariant(); } + return m_columns[section].name; } return section; }@@ -117,7 +167,7 @@ int LibraryModel::columnCount(const QModelIndex& parent) const {
if (parent.isValid()) { return 0; } - return 2; + return m_columns.count(); } int LibraryModel::rowCount(const QModelIndex& parent) const {
M
src/platform/qt/LibraryModel.h
→
src/platform/qt/LibraryModel.h
@@ -50,11 +50,19 @@ private slots:
void directoryLoaded(const QString& path); private: + struct LibraryColumn { + QString name; + std::function<QString(const mLibraryEntry&)> value; + }; + mLibrary* m_library; mLibraryEntry m_constraints; LibraryLoader* m_loader; QThread m_loaderThread; QStringList m_queue; + + QList<LibraryColumn> m_columns; + static QMap<QString, LibraryColumn> s_columns; }; class LibraryLoader : public QObject {
A
src/platform/qt/LibraryView.cpp
@@ -0,0 +1,42 @@
+/* Copyright (c) 2013-2017 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "LibraryView.h" + +#include <mgba-util/vfs.h> + +#include "ConfigController.h" + +using namespace QGBA; + +LibraryView::LibraryView(QWidget* parent) + : QWidget(parent) + , m_model(ConfigController::configDir() + "/library.sqlite3") +{ + m_ui.setupUi(this); + connect(&m_model, SIGNAL(doneLoading()), this, SIGNAL(doneLoading())); + connect(&m_model, SIGNAL(doneLoading()), this, SLOT(resizeColumns())); + connect(m_ui.listing, SIGNAL(activated(const QModelIndex&)), this, SIGNAL(accepted())); + m_ui.listing->horizontalHeader()->setSectionsMovable(true); + m_ui.listing->setModel(&m_model); + resizeColumns(); +} + +void LibraryView::setDirectory(const QString& filename) { + m_model.loadDirectory(filename); + m_model.constrainBase(filename); +} + +VFile* LibraryView::selectedVFile() const { + QModelIndex index = m_ui.listing->selectionModel()->currentIndex(); + if (!index.isValid()) { + return nullptr; + } + return m_model.openVFile(index); +} + +void LibraryView::resizeColumns() { + m_ui.listing->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents); +}
A
src/platform/qt/LibraryView.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2013-2017 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef QGBA_LIBRARY_VIEW +#define QGBA_LIBRARY_VIEW + +#include "LibraryModel.h" + +#include "ui_LibraryView.h" + +struct VFile; + +namespace QGBA { + +class LibraryView : public QWidget { +Q_OBJECT + +public: + LibraryView(QWidget* parent = nullptr); + + VFile* selectedVFile() const; + +signals: + void doneLoading(); + void accepted(); + +public slots: + void setDirectory(const QString&); + +private slots: + void resizeColumns(); + +private: + Ui::LibraryView m_ui; + + LibraryModel m_model; +}; + +} + +#endif
A
src/platform/qt/LibraryView.ui
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>LibraryView</class> + <widget class="QWidget" name="LibraryView"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Library</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QTableView" name="listing"> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + <property name="showGrid"> + <bool>false</bool> + </property> + <attribute name="horizontalHeaderStretchLastSection"> + <bool>true</bool> + </attribute> + <attribute name="verticalHeaderVisible"> + <bool>false</bool> + </attribute> + <attribute name="verticalHeaderMinimumSectionSize"> + <number>0</number> + </attribute> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui>