mirror of https://github.com/mgba-emu/mgba.git
Qt: Redo internal library API and clean up LibraryTree
This commit is contained in:
parent
e4b25fc16b
commit
405f12d1bd
|
@ -13,23 +13,35 @@
|
|||
|
||||
using namespace QGBA;
|
||||
|
||||
void AbstractGameList::addEntries(QList<mLibraryEntry*> items) {
|
||||
for (auto item : items) {
|
||||
addEntry(item);
|
||||
}
|
||||
LibraryEntry::LibraryEntry(const mLibraryEntry* entry)
|
||||
: base(entry->base)
|
||||
, filename(entry->filename)
|
||||
, fullpath(QString("%1/%2").arg(entry->base, entry->filename))
|
||||
, title(entry->title)
|
||||
, internalTitle(entry->internalTitle)
|
||||
, internalCode(entry->internalCode)
|
||||
, platform(entry->platform)
|
||||
, filesize(entry->filesize)
|
||||
, crc32(entry->crc32)
|
||||
{
|
||||
}
|
||||
void AbstractGameList::removeEntries(QList<mLibraryEntry*> items) {
|
||||
for (auto item : items) {
|
||||
removeEntry(item);
|
||||
}
|
||||
|
||||
void AbstractGameList::addEntry(const LibraryEntry& item) {
|
||||
addEntries({item});
|
||||
}
|
||||
|
||||
void AbstractGameList::updateEntry(const LibraryEntry& item) {
|
||||
updateEntries({item});
|
||||
}
|
||||
|
||||
void AbstractGameList::removeEntry(const QString& item) {
|
||||
removeEntries({item});
|
||||
}
|
||||
|
||||
LibraryController::LibraryController(QWidget* parent, const QString& path, ConfigController* config)
|
||||
: QStackedWidget(parent)
|
||||
, m_config(config)
|
||||
{
|
||||
mLibraryListingInit(&m_listing, 0);
|
||||
|
||||
if (!path.isNull()) {
|
||||
// This can return NULL if the library is already open
|
||||
m_library = std::shared_ptr<mLibrary>(mLibraryLoad(path.toUtf8().constData()), mLibraryDestroy);
|
||||
|
@ -52,8 +64,6 @@ LibraryController::LibraryController(QWidget* parent, const QString& path, Confi
|
|||
}
|
||||
|
||||
LibraryController::~LibraryController() {
|
||||
freeLibrary();
|
||||
mLibraryListingDeinit(&m_listing);
|
||||
}
|
||||
|
||||
void LibraryController::setViewStyle(LibraryStyle newStyle) {
|
||||
|
@ -68,39 +78,44 @@ void LibraryController::setViewStyle(LibraryStyle newStyle) {
|
|||
} else {
|
||||
newCurrentList = m_libraryGrid.get();
|
||||
}
|
||||
newCurrentList->selectEntry(selectedEntry());
|
||||
newCurrentList->selectEntry(selectedEntry().fullpath);
|
||||
newCurrentList->setViewStyle(newStyle);
|
||||
setCurrentWidget(newCurrentList->widget());
|
||||
m_currentList = newCurrentList;
|
||||
}
|
||||
|
||||
void LibraryController::selectEntry(mLibraryEntry* entry) {
|
||||
void LibraryController::selectEntry(const QString& fullpath) {
|
||||
if (!m_currentList) {
|
||||
return;
|
||||
}
|
||||
m_currentList->selectEntry(entry);
|
||||
m_currentList->selectEntry(fullpath);
|
||||
}
|
||||
|
||||
mLibraryEntry* LibraryController::selectedEntry() {
|
||||
LibraryEntry LibraryController::selectedEntry() {
|
||||
if (!m_currentList) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
return m_currentList->selectedEntry();
|
||||
return m_entries.value(m_currentList->selectedEntry());
|
||||
}
|
||||
|
||||
VFile* LibraryController::selectedVFile() {
|
||||
mLibraryEntry* entry = selectedEntry();
|
||||
if (entry) {
|
||||
return mLibraryOpenVFile(m_library.get(), entry);
|
||||
LibraryEntry entry = selectedEntry();
|
||||
if (!entry.isNull()) {
|
||||
mLibraryEntry libentry = {0};
|
||||
QByteArray baseUtf8(entry.base.toUtf8());
|
||||
QByteArray filenameUtf8(entry.filename.toUtf8());
|
||||
libentry.base = baseUtf8.constData();
|
||||
libentry.filename = filenameUtf8.constData();
|
||||
return mLibraryOpenVFile(m_library.get(), &libentry);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QPair<QString, QString> LibraryController::selectedPath() {
|
||||
mLibraryEntry* entry = selectedEntry();
|
||||
if (entry) {
|
||||
return qMakePair(QString(entry->base), QString(entry->filename));
|
||||
LibraryEntry entry = selectedEntry();
|
||||
if (!entry.isNull()) {
|
||||
return qMakePair(QString(entry.base), QString(entry.filename));
|
||||
} else {
|
||||
return qMakePair(QString(), QString());
|
||||
}
|
||||
|
@ -130,35 +145,47 @@ void LibraryController::refresh() {
|
|||
|
||||
setDisabled(true);
|
||||
|
||||
QSet<QString> allEntries;
|
||||
QList<mLibraryEntry*> newEntries;
|
||||
QHash<QString, LibraryEntry> removedEntries = m_entries;
|
||||
QHash<QString, LibraryEntry> updatedEntries;
|
||||
QList<LibraryEntry> newEntries;
|
||||
|
||||
freeLibrary();
|
||||
mLibraryGetEntries(m_library.get(), &m_listing, 0, 0, nullptr);
|
||||
for (size_t i = 0; i < mLibraryListingSize(&m_listing); i++) {
|
||||
mLibraryEntry* entry = mLibraryListingGetPointer(&m_listing, i);
|
||||
QString fullpath = QString("%1/%2").arg(entry->base, entry->filename);
|
||||
if (!m_entries.contains(fullpath)) {
|
||||
mLibraryListing listing;
|
||||
mLibraryListingInit(&listing, 0);
|
||||
mLibraryGetEntries(m_library.get(), &listing, 0, 0, nullptr);
|
||||
for (size_t i = 0; i < mLibraryListingSize(&listing); i++) {
|
||||
LibraryEntry entry = mLibraryListingGetConstPointer(&listing, i);
|
||||
if (!m_entries.contains(entry.fullpath)) {
|
||||
newEntries.append(entry);
|
||||
} else {
|
||||
updatedEntries[entry.fullpath] = entry;
|
||||
}
|
||||
m_entries[fullpath] = entry;
|
||||
allEntries.insert(fullpath);
|
||||
m_entries[entry.fullpath] = entry;
|
||||
removedEntries.remove(entry.fullpath);
|
||||
}
|
||||
|
||||
// Check for entries that were removed
|
||||
QList<mLibraryEntry*> removedEntries;
|
||||
for (QString& path : m_entries.keys()) {
|
||||
if (!allEntries.contains(path)) {
|
||||
removedEntries.append(m_entries.value(path));
|
||||
m_entries.remove(path);
|
||||
}
|
||||
for (QString& path : removedEntries.keys()) {
|
||||
m_entries.remove(path);
|
||||
}
|
||||
|
||||
m_libraryTree->addEntries(newEntries);
|
||||
m_libraryGrid->addEntries(newEntries);
|
||||
if (!removedEntries.size() && !newEntries.size()) {
|
||||
m_libraryTree->updateEntries(updatedEntries.values());
|
||||
m_libraryGrid->updateEntries(updatedEntries.values());
|
||||
} else if (!updatedEntries.size()) {
|
||||
m_libraryTree->removeEntries(removedEntries.keys());
|
||||
m_libraryGrid->removeEntries(removedEntries.keys());
|
||||
|
||||
m_libraryTree->removeEntries(removedEntries);
|
||||
m_libraryGrid->removeEntries(removedEntries);
|
||||
m_libraryTree->addEntries(newEntries);
|
||||
m_libraryGrid->addEntries(newEntries);
|
||||
} else {
|
||||
m_libraryTree->resetEntries(m_entries.values());
|
||||
m_libraryGrid->resetEntries(m_entries.values());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mLibraryListingSize(&listing); ++i) {
|
||||
mLibraryEntryFree(mLibraryListingGetPointer(&listing, i));
|
||||
}
|
||||
mLibraryListingDeinit(&listing);
|
||||
|
||||
setDisabled(false);
|
||||
selectLastBootedGame();
|
||||
|
@ -171,7 +198,7 @@ void LibraryController::selectLastBootedGame() {
|
|||
}
|
||||
const QString lastfile = m_config->getMRU().first();
|
||||
if (m_entries.contains(lastfile)) {
|
||||
selectEntry(m_entries.value(lastfile));
|
||||
selectEntry(lastfile);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,10 +209,3 @@ void LibraryController::loadDirectory(const QString& dir, bool recursive) {
|
|||
mLibraryLoadDirectory(library.get(), dir.toUtf8().constData(), recursive);
|
||||
m_libraryJob.testAndSetOrdered(libraryJob, -1);
|
||||
}
|
||||
|
||||
void LibraryController::freeLibrary() {
|
||||
for (size_t i = 0; i < mLibraryListingSize(&m_listing); ++i) {
|
||||
mLibraryEntryFree(mLibraryListingGetPointer(&m_listing, i));
|
||||
}
|
||||
mLibraryListingClear(&m_listing);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2014-2017 waddlesplash
|
||||
* Copyright (c) 2014-2021 Jeffrey Pfau
|
||||
* Copyright (c) 2013-2021 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
|
||||
|
@ -29,18 +29,42 @@ enum class LibraryStyle {
|
|||
STYLE_ICON
|
||||
};
|
||||
|
||||
struct LibraryEntry {
|
||||
LibraryEntry() {}
|
||||
LibraryEntry(const mLibraryEntry* entry);
|
||||
|
||||
bool isNull() const { return fullpath.isNull(); }
|
||||
|
||||
QString displayTitle() const { return title.isNull() ? filename : title; }
|
||||
|
||||
QString base;
|
||||
QString filename;
|
||||
QString fullpath;
|
||||
QString title;
|
||||
QByteArray internalTitle;
|
||||
QByteArray internalCode;
|
||||
mPlatform platform;
|
||||
size_t filesize;
|
||||
uint32_t crc32;
|
||||
|
||||
bool operator==(const LibraryEntry& other) const { return other.fullpath == fullpath; }
|
||||
};
|
||||
|
||||
class AbstractGameList {
|
||||
public:
|
||||
virtual mLibraryEntry* selectedEntry() = 0;
|
||||
virtual void selectEntry(mLibraryEntry* game) = 0;
|
||||
virtual QString selectedEntry() = 0;
|
||||
virtual void selectEntry(const QString& fullpath) = 0;
|
||||
|
||||
virtual void setViewStyle(LibraryStyle newStyle) = 0;
|
||||
|
||||
virtual void addEntry(mLibraryEntry* item) = 0;
|
||||
virtual void addEntries(QList<mLibraryEntry*> items);
|
||||
virtual void resetEntries(const QList<LibraryEntry>&) = 0;
|
||||
virtual void addEntries(const QList<LibraryEntry>&) = 0;
|
||||
virtual void updateEntries(const QList<LibraryEntry>&) = 0;
|
||||
virtual void removeEntries(const QList<QString>&) = 0;
|
||||
|
||||
virtual void removeEntry(mLibraryEntry* item) = 0;
|
||||
virtual void removeEntries(QList<mLibraryEntry*> items);
|
||||
virtual void addEntry(const LibraryEntry&);
|
||||
virtual void updateEntry(const LibraryEntry&);
|
||||
virtual void removeEntry(const QString&);
|
||||
|
||||
virtual QWidget* widget() = 0;
|
||||
};
|
||||
|
@ -56,8 +80,8 @@ public:
|
|||
LibraryStyle viewStyle() const { return m_currentStyle; }
|
||||
void setViewStyle(LibraryStyle newStyle);
|
||||
|
||||
void selectEntry(mLibraryEntry* entry);
|
||||
mLibraryEntry* selectedEntry();
|
||||
void selectEntry(const QString& fullpath);
|
||||
LibraryEntry selectedEntry();
|
||||
VFile* selectedVFile();
|
||||
QPair<QString, QString> selectedPath();
|
||||
|
||||
|
@ -77,13 +101,11 @@ private slots:
|
|||
|
||||
private:
|
||||
void loadDirectory(const QString&, bool recursive = true); // Called on separate thread
|
||||
void freeLibrary();
|
||||
|
||||
ConfigController* m_config = nullptr;
|
||||
std::shared_ptr<mLibrary> m_library;
|
||||
QAtomicInteger<qint64> m_libraryJob = -1;
|
||||
mLibraryListing m_listing;
|
||||
QHash<QString, mLibraryEntry*> m_entries;
|
||||
QHash<QString, LibraryEntry> m_entries;
|
||||
|
||||
LibraryStyle m_currentStyle;
|
||||
AbstractGameList* m_currentList = nullptr;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* Copyright (c) 2014-2017 waddlesplash
|
||||
* Copyright (c) 2013-2021 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
|
||||
|
@ -23,22 +24,16 @@ LibraryGrid::~LibraryGrid() {
|
|||
delete m_widget;
|
||||
}
|
||||
|
||||
mLibraryEntry* LibraryGrid::selectedEntry() {
|
||||
QString LibraryGrid::selectedEntry() {
|
||||
if (!m_widget->selectedItems().empty()) {
|
||||
return m_items.key(m_widget->selectedItems().at(0));
|
||||
} else {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void LibraryGrid::selectEntry(mLibraryEntry* game) {
|
||||
if (!game) {
|
||||
return;
|
||||
}
|
||||
if (!m_widget->selectedItems().empty()) {
|
||||
m_widget->selectedItems().at(0)->setSelected(false);
|
||||
}
|
||||
m_items.value(game)->setSelected(true);
|
||||
void LibraryGrid::selectEntry(const QString& game) {
|
||||
m_widget->setCurrentItem(m_items.value(game));
|
||||
}
|
||||
|
||||
void LibraryGrid::setViewStyle(LibraryStyle newStyle) {
|
||||
|
@ -47,33 +42,62 @@ void LibraryGrid::setViewStyle(LibraryStyle newStyle) {
|
|||
m_widget->setIconSize(QSize(GRID_BANNER_WIDTH, GRID_BANNER_HEIGHT));
|
||||
m_widget->setViewMode(QListView::IconMode);
|
||||
} else {
|
||||
m_currentStyle = LibraryStyle::STYLE_ICON;
|
||||
m_widget->setIconSize(QSize(ICON_BANNER_WIDTH, ICON_BANNER_HEIGHT));
|
||||
m_widget->setViewMode(QListView::ListMode);
|
||||
}
|
||||
m_currentStyle = newStyle;
|
||||
|
||||
// QListView resets this when you change the view mode, so let's set it again
|
||||
m_widget->setDragEnabled(false);
|
||||
}
|
||||
|
||||
void LibraryGrid::addEntry(mLibraryEntry* item) {
|
||||
if (m_items.contains(item)) {
|
||||
void LibraryGrid::resetEntries(const QList<LibraryEntry>& items) {
|
||||
m_widget->clear();
|
||||
m_items.clear();
|
||||
addEntries(items);
|
||||
}
|
||||
|
||||
void LibraryGrid::addEntries(const QList<LibraryEntry>& items) {
|
||||
for (const auto& item : items) {
|
||||
addEntry(item);
|
||||
}
|
||||
}
|
||||
|
||||
void LibraryGrid::addEntry(const LibraryEntry& item) {
|
||||
if (m_items.contains(item.fullpath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QListWidgetItem* i = new QListWidgetItem;
|
||||
i->setText(item->title ? item->title : item->filename);
|
||||
i->setText(item.displayTitle());
|
||||
|
||||
m_widget->addItem(i);
|
||||
m_items.insert(item, i);
|
||||
m_items.insert(item.fullpath, i);
|
||||
}
|
||||
|
||||
void LibraryGrid::removeEntry(mLibraryEntry* entry) {
|
||||
if (!m_items.contains(entry)) {
|
||||
void LibraryGrid::updateEntries(const QList<LibraryEntry>& items) {
|
||||
for (const auto& item : items) {
|
||||
updateEntry(item);
|
||||
}
|
||||
}
|
||||
|
||||
void LibraryGrid::updateEntry(const LibraryEntry& item) {
|
||||
QListWidgetItem* i = m_items.value(item.fullpath);
|
||||
i->setText(item.displayTitle());
|
||||
}
|
||||
|
||||
void LibraryGrid::removeEntries(const QList<QString>& items) {
|
||||
for (const auto& item : items) {
|
||||
removeEntry(item);
|
||||
}
|
||||
}
|
||||
|
||||
void LibraryGrid::removeEntry(const QString& item) {
|
||||
if (!m_items.contains(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
delete m_items.take(entry);
|
||||
delete m_items.take(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,16 +16,21 @@ public:
|
|||
explicit LibraryGrid(LibraryController* parent = nullptr);
|
||||
~LibraryGrid();
|
||||
|
||||
// AbstractGameList stuff
|
||||
virtual mLibraryEntry* selectedEntry() override;
|
||||
virtual void selectEntry(mLibraryEntry* game) override;
|
||||
QString selectedEntry() override;
|
||||
void selectEntry(const QString& fullpath) override;
|
||||
|
||||
virtual void setViewStyle(LibraryStyle newStyle) override;
|
||||
void setViewStyle(LibraryStyle newStyle) override;
|
||||
|
||||
virtual void addEntry(mLibraryEntry* item) override;
|
||||
virtual void removeEntry(mLibraryEntry* entry) override;
|
||||
void resetEntries(const QList<LibraryEntry>& items) override;
|
||||
void addEntries(const QList<LibraryEntry>& items) override;
|
||||
void updateEntries(const QList<LibraryEntry>& items) override;
|
||||
void removeEntries(const QList<QString>& items) override;
|
||||
|
||||
virtual QWidget* widget() override { return m_widget; }
|
||||
void addEntry(const LibraryEntry& items) override;
|
||||
void updateEntry(const LibraryEntry& items) override;
|
||||
void removeEntry(const QString& items) override;
|
||||
|
||||
QWidget* widget() override { return m_widget; }
|
||||
|
||||
signals:
|
||||
void startGame();
|
||||
|
@ -40,7 +45,7 @@ private:
|
|||
const quint32 ICON_BANNER_WIDTH = 64;
|
||||
const quint32 ICON_BANNER_HEIGHT = 64;
|
||||
|
||||
QHash<mLibraryEntry*, QListWidgetItem*> m_items;
|
||||
QHash<QString, QListWidgetItem*> m_items;
|
||||
LibraryStyle m_currentStyle;
|
||||
};
|
||||
|
||||
|
|
|
@ -10,11 +10,13 @@
|
|||
#include <QApplication>
|
||||
#include <QDir>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class TreeWidgetItem : public QTreeWidgetItem {
|
||||
class LibraryTreeItem : public QTreeWidgetItem {
|
||||
public:
|
||||
TreeWidgetItem(QTreeWidget* parent = nullptr) : QTreeWidgetItem(parent) {}
|
||||
LibraryTreeItem(QTreeWidget* parent = nullptr) : QTreeWidgetItem(parent) {}
|
||||
void setFilesize(size_t size);
|
||||
|
||||
virtual bool operator<(const QTreeWidgetItem& other) const override;
|
||||
|
@ -22,15 +24,17 @@ protected:
|
|||
size_t m_size = 0;
|
||||
};
|
||||
|
||||
void TreeWidgetItem::setFilesize(size_t size) {
|
||||
}
|
||||
|
||||
void LibraryTreeItem::setFilesize(size_t size) {
|
||||
m_size = size;
|
||||
setText(LibraryTree::COL_SIZE, niceSizeFormat(size));
|
||||
}
|
||||
|
||||
bool TreeWidgetItem::operator<(const QTreeWidgetItem& other) const {
|
||||
bool LibraryTreeItem::operator<(const QTreeWidgetItem& other) const {
|
||||
const int column = treeWidget()->sortColumn();
|
||||
return ((column == LibraryTree::COL_SIZE) ?
|
||||
m_size < dynamic_cast<const TreeWidgetItem*>(&other)->m_size :
|
||||
m_size < dynamic_cast<const LibraryTreeItem*>(&other)->m_size :
|
||||
QTreeWidgetItem::operator<(other));
|
||||
}
|
||||
|
||||
|
@ -56,16 +60,14 @@ LibraryTree::LibraryTree(LibraryController* parent)
|
|||
m_widget->sortByColumn(COL_NAME, Qt::AscendingOrder);
|
||||
|
||||
QObject::connect(m_widget, &QTreeWidget::itemActivated, [this](QTreeWidgetItem* item, int) -> void {
|
||||
if (!m_pathNodes.values().contains(item)) {
|
||||
if (m_items.values().contains(item)) {
|
||||
emit m_controller->startGame();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
LibraryTree::~LibraryTree() {
|
||||
for (QTreeWidgetItem* i : m_items.values()) {
|
||||
delete i;
|
||||
}
|
||||
m_widget->clear();
|
||||
}
|
||||
|
||||
void LibraryTree::resizeAllCols() {
|
||||
|
@ -74,75 +76,97 @@ void LibraryTree::resizeAllCols() {
|
|||
}
|
||||
}
|
||||
|
||||
mLibraryEntry* LibraryTree::selectedEntry() {
|
||||
QString LibraryTree::selectedEntry() {
|
||||
if (!m_widget->selectedItems().empty()) {
|
||||
return m_items.key(m_widget->selectedItems().at(0));
|
||||
} else {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void LibraryTree::selectEntry(mLibraryEntry* game) {
|
||||
if (!game) {
|
||||
void LibraryTree::selectEntry(const QString& game) {
|
||||
if (game.isNull()) {
|
||||
return;
|
||||
}
|
||||
if (!m_widget->selectedItems().empty()) {
|
||||
m_widget->selectedItems().at(0)->setSelected(false);
|
||||
}
|
||||
m_items.value(game)->setSelected(true);
|
||||
m_widget->setCurrentItem(m_items.value(game));
|
||||
}
|
||||
|
||||
void LibraryTree::setViewStyle(LibraryStyle newStyle) {
|
||||
if (newStyle == LibraryStyle::STYLE_LIST) {
|
||||
m_currentStyle = LibraryStyle::STYLE_LIST;
|
||||
m_widget->setIndentation(0);
|
||||
rebuildTree();
|
||||
} else {
|
||||
m_currentStyle = LibraryStyle::STYLE_TREE;
|
||||
m_widget->setIndentation(20);
|
||||
rebuildTree();
|
||||
}
|
||||
m_currentStyle = newStyle;
|
||||
rebuildTree();
|
||||
}
|
||||
|
||||
void LibraryTree::addEntries(QList<mLibraryEntry*> items) {
|
||||
void LibraryTree::resetEntries(const QList<LibraryEntry>& items) {
|
||||
m_deferredTreeRebuild = true;
|
||||
AbstractGameList::addEntries(items);
|
||||
m_entries.clear();
|
||||
m_pathNodes.clear();
|
||||
addEntries(items);
|
||||
}
|
||||
|
||||
void LibraryTree::addEntries(const QList<LibraryEntry>& items) {
|
||||
m_deferredTreeRebuild = true;
|
||||
for (const auto& item : items) {
|
||||
addEntry(item);
|
||||
}
|
||||
m_deferredTreeRebuild = false;
|
||||
rebuildTree();
|
||||
}
|
||||
|
||||
void LibraryTree::addEntry(mLibraryEntry* item) {
|
||||
if (m_items.contains(item)) {
|
||||
return;
|
||||
}
|
||||
void LibraryTree::addEntry(const LibraryEntry& item) {
|
||||
m_entries[item.fullpath] = item;
|
||||
|
||||
QString folder = item->base;
|
||||
QString folder = item.base;
|
||||
if (!m_pathNodes.contains(folder)) {
|
||||
QTreeWidgetItem* i = new TreeWidgetItem;
|
||||
i->setText(0, folder.section("/", -1));
|
||||
m_pathNodes.insert(folder, i);
|
||||
if (m_currentStyle == LibraryStyle::STYLE_TREE) {
|
||||
m_widget->addTopLevelItem(i);
|
||||
}
|
||||
m_pathNodes.insert(folder, 1);
|
||||
} else {
|
||||
++m_pathNodes[folder];
|
||||
}
|
||||
|
||||
TreeWidgetItem* i = new TreeWidgetItem;
|
||||
i->setText(COL_NAME, item->title ? item->title : item->filename);
|
||||
i->setText(COL_LOCATION, QDir::toNativeSeparators(item->base));
|
||||
i->setText(COL_PLATFORM, nicePlatformFormat(item->platform));
|
||||
i->setFilesize(item->filesize);
|
||||
i->setTextAlignment(COL_SIZE, Qt::AlignRight);
|
||||
i->setText(COL_CRC32, QString("%0").arg(item->crc32, 8, 16, QChar('0')));
|
||||
m_items.insert(item, i);
|
||||
|
||||
rebuildTree();
|
||||
}
|
||||
|
||||
void LibraryTree::removeEntry(mLibraryEntry* item) {
|
||||
if (!m_items.contains(item)) {
|
||||
void LibraryTree::updateEntries(const QList<LibraryEntry>& items) {
|
||||
for (const auto& item : items) {
|
||||
updateEntry(item);
|
||||
}
|
||||
}
|
||||
|
||||
void LibraryTree::updateEntry(const LibraryEntry& item) {
|
||||
m_entries[item.fullpath] = item;
|
||||
|
||||
LibraryTreeItem* i = static_cast<LibraryTreeItem*>(m_items.value(item.fullpath));
|
||||
i->setText(COL_NAME, item.displayTitle());
|
||||
i->setText(COL_PLATFORM, nicePlatformFormat(item.platform));
|
||||
i->setFilesize(item.filesize);
|
||||
i->setText(COL_CRC32, QString("%0").arg(item.crc32, 8, 16, QChar('0')));
|
||||
}
|
||||
|
||||
void LibraryTree::removeEntries(const QList<QString>& items) {
|
||||
m_deferredTreeRebuild = true;
|
||||
for (const auto& item : items) {
|
||||
removeEntry(item);
|
||||
}
|
||||
m_deferredTreeRebuild = false;
|
||||
rebuildTree();
|
||||
}
|
||||
|
||||
void LibraryTree::removeEntry(const QString& item) {
|
||||
if (!m_entries.contains(item)) {
|
||||
return;
|
||||
}
|
||||
delete m_items.take(item);
|
||||
QString folder = m_entries.value(item).base;
|
||||
--m_pathNodes[folder];
|
||||
if (m_pathNodes[folder] <= 0) {
|
||||
m_pathNodes.remove(folder);
|
||||
}
|
||||
|
||||
m_entries.remove(item);
|
||||
rebuildTree();
|
||||
}
|
||||
|
||||
void LibraryTree::rebuildTree() {
|
||||
|
@ -150,26 +174,33 @@ void LibraryTree::rebuildTree() {
|
|||
return;
|
||||
}
|
||||
|
||||
mLibraryEntry* currentGame = selectedEntry();
|
||||
|
||||
int count = m_widget->topLevelItemCount();
|
||||
for (int a = count - 1; a >= 0; --a) {
|
||||
m_widget->takeTopLevelItem(a);
|
||||
}
|
||||
|
||||
for (QTreeWidgetItem* i : m_pathNodes.values()) {
|
||||
i->takeChildren();
|
||||
}
|
||||
QString currentGame = selectedEntry();
|
||||
m_widget->clear();
|
||||
m_items.clear();
|
||||
|
||||
QHash<QString, QTreeWidgetItem*> pathNodes;
|
||||
if (m_currentStyle == LibraryStyle::STYLE_TREE) {
|
||||
for (QTreeWidgetItem* i : m_pathNodes.values()) {
|
||||
for (const QString& folder : m_pathNodes.keys()) {
|
||||
QTreeWidgetItem* i = new LibraryTreeItem;
|
||||
pathNodes.insert(folder, i);
|
||||
i->setText(0, folder.section("/", -1));
|
||||
m_widget->addTopLevelItem(i);
|
||||
}
|
||||
for (QTreeWidgetItem* i : m_items.values()) {
|
||||
m_pathNodes.value(m_items.key(i)->base)->addChild(i);
|
||||
}
|
||||
} else {
|
||||
for (QTreeWidgetItem* i : m_items.values()) {
|
||||
}
|
||||
|
||||
for (const auto& item : m_entries.values()) {
|
||||
LibraryTreeItem* i = new LibraryTreeItem;
|
||||
i->setText(COL_NAME, item.displayTitle());
|
||||
i->setText(COL_LOCATION, QDir::toNativeSeparators(item.base));
|
||||
i->setText(COL_PLATFORM, nicePlatformFormat(item.platform));
|
||||
i->setFilesize(item.filesize);
|
||||
i->setTextAlignment(COL_SIZE, Qt::AlignRight);
|
||||
i->setText(COL_CRC32, QString("%0").arg(item.crc32, 8, 16, QChar('0')));
|
||||
m_items.insert(item.fullpath, i);
|
||||
|
||||
if (m_currentStyle == LibraryStyle::STYLE_TREE) {
|
||||
pathNodes.value(item.base)->addChild(i);
|
||||
} else {
|
||||
m_widget->addTopLevelItem(i);
|
||||
}
|
||||
}
|
||||
|
@ -178,5 +209,3 @@ void LibraryTree::rebuildTree() {
|
|||
resizeAllCols();
|
||||
selectEntry(currentGame);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
namespace QGBA {
|
||||
|
||||
class LibraryTreeItem;
|
||||
|
||||
class LibraryTree final : public AbstractGameList {
|
||||
|
||||
public:
|
||||
|
@ -25,17 +27,21 @@ public:
|
|||
explicit LibraryTree(LibraryController* parent = nullptr);
|
||||
~LibraryTree();
|
||||
|
||||
// AbstractGameList stuff
|
||||
virtual mLibraryEntry* selectedEntry() override;
|
||||
virtual void selectEntry(mLibraryEntry* game) override;
|
||||
QString selectedEntry() override;
|
||||
void selectEntry(const QString& fullpath) override;
|
||||
|
||||
virtual void setViewStyle(LibraryStyle newStyle) override;
|
||||
void setViewStyle(LibraryStyle newStyle) override;
|
||||
|
||||
virtual void addEntries(QList<mLibraryEntry*> items) override;
|
||||
virtual void addEntry(mLibraryEntry* item) override;
|
||||
virtual void removeEntry(mLibraryEntry* item) override;
|
||||
void resetEntries(const QList<LibraryEntry>& items) override;
|
||||
void addEntries(const QList<LibraryEntry>& items) override;
|
||||
void updateEntries(const QList<LibraryEntry>& items) override;
|
||||
void removeEntries(const QList<QString>& items) override;
|
||||
|
||||
virtual QWidget* widget() override { return m_widget; }
|
||||
void addEntry(const LibraryEntry& items) override;
|
||||
void updateEntry(const LibraryEntry& items) override;
|
||||
void removeEntry(const QString& items) override;
|
||||
|
||||
QWidget* widget() override { return m_widget; }
|
||||
|
||||
private:
|
||||
QTreeWidget* m_widget;
|
||||
|
@ -44,8 +50,9 @@ private:
|
|||
LibraryController* m_controller;
|
||||
|
||||
bool m_deferredTreeRebuild = false;
|
||||
QHash<mLibraryEntry*, QTreeWidgetItem*> m_items;
|
||||
QHash<QString, QTreeWidgetItem*> m_pathNodes;
|
||||
QHash<QString, LibraryEntry> m_entries;
|
||||
QHash<QString, QTreeWidgetItem*> m_items;
|
||||
QHash<QString, int> m_pathNodes;
|
||||
|
||||
void rebuildTree();
|
||||
void resizeAllCols();
|
||||
|
|
Loading…
Reference in New Issue