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}