all repos — mgba @ c8e1e14d3f36ad1507f69d990cf94629df9db97d

mGBA Game Boy Advance Emulator

src/platform/qt/library/LibraryTree.cpp (view raw)

  1/* Copyright (c) 2014-2017 waddlesplash
  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 "LibraryTree.h"
  7
  8#include "utils.h"
  9
 10#include <QApplication>
 11#include <QDir>
 12
 13namespace QGBA {
 14
 15class TreeWidgetItem : public QTreeWidgetItem {
 16public:
 17	TreeWidgetItem(QTreeWidget* parent = nullptr) : QTreeWidgetItem(parent) {}
 18	void setFilesize(size_t size);
 19
 20	virtual bool operator<(const QTreeWidgetItem& other) const override;
 21protected:
 22	size_t m_size = 0;
 23};
 24
 25void TreeWidgetItem::setFilesize(size_t size) {
 26	m_size = size;
 27	setText(LibraryTree::COL_SIZE, niceSizeFormat(size));
 28}
 29
 30bool TreeWidgetItem::operator<(const QTreeWidgetItem& other) const {
 31	const int column = treeWidget()->sortColumn();
 32	return ((column == LibraryTree::COL_SIZE) ?
 33		m_size < dynamic_cast<const TreeWidgetItem*>(&other)->m_size :
 34		QTreeWidgetItem::operator<(other));
 35}
 36
 37LibraryTree::LibraryTree(LibraryController* parent)
 38	: m_widget(new QTreeWidget(parent))
 39	, m_controller(parent)
 40{
 41	m_widget->setObjectName("LibraryTree");
 42	m_widget->setSortingEnabled(true);
 43	m_widget->setAlternatingRowColors(true);
 44
 45	QTreeWidgetItem* header = new QTreeWidgetItem({
 46		QApplication::translate("LibraryTree", "Name", nullptr),
 47		QApplication::translate("LibraryTree", "Location", nullptr),
 48		QApplication::translate("LibraryTree", "Platform", nullptr),
 49		QApplication::translate("LibraryTree", "Size", nullptr),
 50		QApplication::translate("LibraryTree", "CRC32", nullptr),
 51	});
 52	header->setTextAlignment(3, Qt::AlignTrailing | Qt::AlignVCenter);
 53	m_widget->setHeaderItem(header);
 54
 55	setViewStyle(LibraryStyle::STYLE_TREE);
 56	m_widget->sortByColumn(COL_NAME, Qt::AscendingOrder);
 57
 58	QObject::connect(m_widget, &QTreeWidget::itemActivated, [this](QTreeWidgetItem* item, int) -> void {
 59		if (!m_pathNodes.values().contains(item)) {
 60			emit m_controller->startGame();
 61		}
 62	});
 63}
 64
 65LibraryTree::~LibraryTree() {
 66	for (QTreeWidgetItem* i : m_items.values()) {
 67		delete i;
 68	}
 69}
 70
 71void LibraryTree::resizeAllCols() {
 72	for (int i = 0; i < m_widget->columnCount(); i++) {
 73		m_widget->resizeColumnToContents(i);
 74	}
 75}
 76
 77LibraryEntryRef LibraryTree::selectedEntry() {
 78	if (!m_widget->selectedItems().empty()) {
 79		return m_items.key(m_widget->selectedItems().at(0));
 80	} else {
 81		return LibraryEntryRef();
 82	}
 83}
 84
 85void LibraryTree::selectEntry(LibraryEntryRef game) {
 86	if (!game) {
 87		return;
 88	}
 89	if (!m_widget->selectedItems().empty()) {
 90		m_widget->selectedItems().at(0)->setSelected(false);
 91	}
 92	m_items.value(game)->setSelected(true);
 93}
 94
 95void LibraryTree::setViewStyle(LibraryStyle newStyle) {
 96	if (newStyle == LibraryStyle::STYLE_LIST) {
 97		m_currentStyle = LibraryStyle::STYLE_LIST;
 98		m_widget->setIndentation(0);
 99		rebuildTree();
100	} else {
101		m_currentStyle = LibraryStyle::STYLE_TREE;
102		m_widget->setIndentation(20);
103		rebuildTree();
104	}
105}
106
107void LibraryTree::addEntries(QList<LibraryEntryRef> items) {
108	m_deferredTreeRebuild = true;
109	AbstractGameList::addEntries(items);
110	m_deferredTreeRebuild = false;
111	rebuildTree();
112}
113
114void LibraryTree::addEntry(LibraryEntryRef item) {
115	if (m_items.contains(item)) {
116		return;
117	}
118
119	QString folder = item->base();
120	if (!m_pathNodes.contains(folder)) {
121		QTreeWidgetItem* i = new TreeWidgetItem;
122		i->setText(0, folder.section("/", -1));
123		m_pathNodes.insert(folder, i);
124		if (m_currentStyle == LibraryStyle::STYLE_TREE) {
125			m_widget->addTopLevelItem(i);
126		}
127	}
128
129	TreeWidgetItem* i = new TreeWidgetItem;
130	i->setText(COL_NAME, item->displayTitle());
131	i->setText(COL_LOCATION, QDir::toNativeSeparators(item->base()));
132	i->setText(COL_PLATFORM, nicePlatformFormat(item->platform()));
133	i->setFilesize(item->filesize());
134	i->setTextAlignment(COL_SIZE, Qt::AlignRight);
135	i->setText(COL_CRC32, QString("%0").arg(item->crc32(), 8, 16, QChar('0')));
136	m_items.insert(item, i);
137
138	rebuildTree();
139}
140
141void LibraryTree::removeEntry(LibraryEntryRef item) {
142	if (!m_items.contains(item)) {
143		return;
144	}
145	delete m_items.take(item);
146}
147
148void LibraryTree::rebuildTree() {
149	if (m_deferredTreeRebuild) {
150		return;
151	}
152
153	LibraryEntryRef currentGame = selectedEntry();
154
155	int count = m_widget->topLevelItemCount();
156	for (int a = count - 1; a >= 0; --a) {
157		m_widget->takeTopLevelItem(a);
158	}
159
160	for (QTreeWidgetItem* i : m_pathNodes.values()) {
161		i->takeChildren();
162	}
163
164	if (m_currentStyle == LibraryStyle::STYLE_TREE) {
165		for (QTreeWidgetItem* i : m_pathNodes.values()) {
166			m_widget->addTopLevelItem(i);
167		}
168		for (QTreeWidgetItem* i : m_items.values()) {
169			m_pathNodes.value(m_items.key(i)->base())->addChild(i);
170		}
171	} else {
172		for (QTreeWidgetItem* i : m_items.values()) {
173			m_widget->addTopLevelItem(i);
174		}
175	}
176
177	m_widget->expandAll();
178	resizeAllCols();
179	selectEntry(currentGame);
180}
181
182}