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
65void LibraryTree::resizeAllCols() {
66 for (int i = 0; i < m_widget->columnCount(); i++) {
67 m_widget->resizeColumnToContents(i);
68 }
69}
70
71LibraryEntryRef LibraryTree::selectedEntry() {
72 if (!m_widget->selectedItems().empty()) {
73 return m_items.key(m_widget->selectedItems().at(0));
74 } else {
75 return LibraryEntryRef();
76 }
77}
78
79void LibraryTree::selectEntry(LibraryEntryRef game) {
80 if (!game) {
81 return;
82 }
83 if (!m_widget->selectedItems().empty()) {
84 m_widget->selectedItems().at(0)->setSelected(false);
85 }
86 m_items.value(game)->setSelected(true);
87}
88
89void LibraryTree::setViewStyle(LibraryStyle newStyle) {
90 if (newStyle == LibraryStyle::STYLE_LIST) {
91 m_currentStyle = LibraryStyle::STYLE_LIST;
92 m_widget->setIndentation(0);
93 rebuildTree();
94 } else {
95 m_currentStyle = LibraryStyle::STYLE_TREE;
96 m_widget->setIndentation(20);
97 rebuildTree();
98 }
99}
100
101void LibraryTree::addEntries(QList<LibraryEntryRef> items) {
102 m_deferredTreeRebuild = true;
103 AbstractGameList::addEntries(items);
104 m_deferredTreeRebuild = false;
105 rebuildTree();
106}
107
108void LibraryTree::addEntry(LibraryEntryRef item) {
109 if (m_items.contains(item)) {
110 return;
111 }
112
113 QString folder = item->base();
114 if (!m_pathNodes.contains(folder)) {
115 QTreeWidgetItem* i = new TreeWidgetItem;
116 i->setText(0, folder.section("/", -1));
117 m_pathNodes.insert(folder, i);
118 if (m_currentStyle == LibraryStyle::STYLE_TREE) {
119 m_widget->addTopLevelItem(i);
120 }
121 }
122
123 TreeWidgetItem* i = new TreeWidgetItem;
124 i->setText(COL_NAME, item->displayTitle());
125 i->setText(COL_LOCATION, QDir::toNativeSeparators(item->base()));
126 i->setText(COL_PLATFORM, nicePlatformFormat(item->platform()));
127 i->setFilesize(item->filesize());
128 i->setTextAlignment(COL_SIZE, Qt::AlignRight);
129 i->setText(COL_CRC32, QString("%0").arg(item->crc32(), 8, 16, QChar('0')));
130 m_items.insert(item, i);
131
132 rebuildTree();
133}
134
135void LibraryTree::removeEntry(LibraryEntryRef item) {
136 if (!m_items.contains(item)) {
137 return;
138 }
139 delete m_items.take(item);
140}
141
142void LibraryTree::rebuildTree() {
143 if (m_deferredTreeRebuild) {
144 return;
145 }
146
147 LibraryEntryRef currentGame = selectedEntry();
148
149 int count = m_widget->topLevelItemCount();
150 for (int a = 0; a < count; a++) {
151 m_widget->takeTopLevelItem(0);
152 }
153
154 for (QTreeWidgetItem* i : m_pathNodes.values()) {
155 count = i->childCount();
156 for (int a = 0; a < count; a++) {
157 i->takeChild(0);
158 }
159 }
160
161 if (m_currentStyle == LibraryStyle::STYLE_TREE) {
162 for (QTreeWidgetItem* i : m_pathNodes.values()) {
163 m_widget->addTopLevelItem(i);
164 }
165 for (QTreeWidgetItem* i : m_items.values()) {
166 m_pathNodes.value(m_items.key(i)->base())->addChild(i);
167 }
168 } else {
169 for (QTreeWidgetItem* i : m_items.values()) {
170 m_widget->addTopLevelItem(i);
171 }
172 }
173
174 m_widget->expandAll();
175 resizeAllCols();
176 selectEntry(currentGame);
177}
178
179}