ResourcePackManager.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. // Copyright 2018 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "DolphinQt/ResourcePackManager.h"
  4. #include <QDesktopServices>
  5. #include <QDialogButtonBox>
  6. #include <QGridLayout>
  7. #include <QHeaderView>
  8. #include <QPushButton>
  9. #include <QTableWidget>
  10. #include <QUrl>
  11. #include "Common/FileUtil.h"
  12. #include "DolphinQt/QtUtils/ModalMessageBox.h"
  13. #include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
  14. #include "UICommon/ResourcePack/Manager.h"
  15. ResourcePackManager::ResourcePackManager(QWidget* widget) : QDialog(widget)
  16. {
  17. CreateWidgets();
  18. ConnectWidgets();
  19. RepopulateTable();
  20. setWindowTitle(tr("Resource Pack Manager"));
  21. resize(QSize(900, 600));
  22. }
  23. void ResourcePackManager::CreateWidgets()
  24. {
  25. auto* layout = new QGridLayout;
  26. m_table_widget = new QTableWidget;
  27. m_table_widget->setTabKeyNavigation(false);
  28. m_open_directory_button = new NonDefaultQPushButton(tr("Open Directory..."));
  29. m_change_button = new NonDefaultQPushButton(tr("Install"));
  30. m_remove_button = new NonDefaultQPushButton(tr("Remove"));
  31. m_refresh_button = new NonDefaultQPushButton(tr("Refresh"));
  32. m_priority_up_button = new NonDefaultQPushButton(tr("Up"));
  33. m_priority_down_button = new NonDefaultQPushButton(tr("Down"));
  34. auto* buttons = new QDialogButtonBox(QDialogButtonBox::Ok);
  35. connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
  36. layout->addWidget(m_table_widget, 0, 0, 7, 1);
  37. layout->addWidget(m_open_directory_button, 0, 1);
  38. layout->addWidget(m_change_button, 1, 1);
  39. layout->addWidget(m_remove_button, 2, 1);
  40. layout->addWidget(m_refresh_button, 3, 1);
  41. layout->addWidget(m_priority_up_button, 4, 1);
  42. layout->addWidget(m_priority_down_button, 5, 1);
  43. layout->addWidget(buttons, 7, 1, Qt::AlignRight);
  44. setLayout(layout);
  45. setLayout(layout);
  46. }
  47. void ResourcePackManager::ConnectWidgets()
  48. {
  49. connect(m_open_directory_button, &QPushButton::clicked, this,
  50. &ResourcePackManager::OpenResourcePackDir);
  51. connect(m_refresh_button, &QPushButton::clicked, this, &ResourcePackManager::Refresh);
  52. connect(m_change_button, &QPushButton::clicked, this, &ResourcePackManager::Change);
  53. connect(m_remove_button, &QPushButton::clicked, this, &ResourcePackManager::Remove);
  54. connect(m_priority_up_button, &QPushButton::clicked, this, &ResourcePackManager::PriorityUp);
  55. connect(m_priority_down_button, &QPushButton::clicked, this, &ResourcePackManager::PriorityDown);
  56. connect(m_table_widget, &QTableWidget::itemSelectionChanged, this,
  57. &ResourcePackManager::SelectionChanged);
  58. connect(m_table_widget, &QTableWidget::itemDoubleClicked, this,
  59. &ResourcePackManager::ItemDoubleClicked);
  60. }
  61. void ResourcePackManager::OpenResourcePackDir()
  62. {
  63. QDesktopServices::openUrl(
  64. QUrl::fromLocalFile(QString::fromStdString(File::GetUserPath(D_RESOURCEPACK_IDX))));
  65. }
  66. void ResourcePackManager::RepopulateTable()
  67. {
  68. m_table_widget->clear();
  69. m_table_widget->setColumnCount(6);
  70. m_table_widget->setHorizontalHeaderLabels(
  71. {QString{}, tr("Name"), tr("Version"), tr("Description"), tr("Author"), tr("Website")});
  72. auto* header = m_table_widget->horizontalHeader();
  73. for (int i = 0; i < 4; i++)
  74. header->setSectionResizeMode(i, QHeaderView::ResizeToContents);
  75. header->setStretchLastSection(true);
  76. header->setHighlightSections(false);
  77. int size = static_cast<int>(ResourcePack::GetPacks().size());
  78. m_table_widget->setSelectionBehavior(QAbstractItemView::SelectRows);
  79. m_table_widget->setSelectionMode(QAbstractItemView::SingleSelection);
  80. m_table_widget->setRowCount(size);
  81. m_table_widget->setIconSize(QSize(32, 32));
  82. for (int i = 0; i < size; i++)
  83. {
  84. const auto& pack = ResourcePack::GetPacks()[size - 1 - i];
  85. const auto* manifest = pack.GetManifest();
  86. const auto& authors = manifest->GetAuthors();
  87. auto* logo_item = new QTableWidgetItem;
  88. auto* name_item = new QTableWidgetItem(QString::fromStdString(manifest->GetName()));
  89. auto* version_item = new QTableWidgetItem(QString::fromStdString(manifest->GetVersion()));
  90. auto* author_item =
  91. new QTableWidgetItem(authors ? QString::fromStdString(*authors) : tr("Unknown author"));
  92. auto* description_item =
  93. new QTableWidgetItem(QString::fromStdString(manifest->GetDescription().value_or("")));
  94. auto* website_item =
  95. new QTableWidgetItem(QString::fromStdString(manifest->GetWebsite().value_or("")));
  96. QPixmap logo;
  97. logo.loadFromData(reinterpret_cast<const uchar*>(pack.GetLogo().data()),
  98. (int)pack.GetLogo().size());
  99. logo_item->setIcon(QIcon(logo));
  100. QFont link_font = website_item->font();
  101. link_font.setUnderline(true);
  102. website_item->setFont(link_font);
  103. website_item->setForeground(QBrush(Qt::blue));
  104. website_item->setData(Qt::UserRole, website_item->text());
  105. for (auto* item :
  106. {logo_item, name_item, version_item, author_item, description_item, website_item})
  107. {
  108. item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
  109. if (ResourcePack::IsInstalled(pack))
  110. {
  111. item->setBackground(QColor(Qt::green));
  112. auto font = item->font();
  113. font.setBold(true);
  114. item->setFont(font);
  115. }
  116. }
  117. m_table_widget->setItem(i, 0, logo_item);
  118. m_table_widget->setItem(i, 1, name_item);
  119. m_table_widget->setItem(i, 2, version_item);
  120. m_table_widget->setItem(i, 3, description_item);
  121. m_table_widget->setItem(i, 4, author_item);
  122. m_table_widget->setItem(i, 5, website_item);
  123. }
  124. SelectionChanged();
  125. }
  126. // Revert the indicies as to be more intuitive for users
  127. int ResourcePackManager::GetResourcePackIndex(QTableWidgetItem* item) const
  128. {
  129. return m_table_widget->rowCount() - 1 - item->row();
  130. }
  131. void ResourcePackManager::Change()
  132. {
  133. auto items = m_table_widget->selectedItems();
  134. if (items.empty())
  135. return;
  136. if (ResourcePack::IsInstalled(ResourcePack::GetPacks()[GetResourcePackIndex(items[0])]))
  137. {
  138. Uninstall();
  139. }
  140. else
  141. {
  142. Install();
  143. }
  144. }
  145. void ResourcePackManager::Install()
  146. {
  147. auto items = m_table_widget->selectedItems();
  148. if (items.empty())
  149. return;
  150. auto& item = ResourcePack::GetPacks()[GetResourcePackIndex(items[0])];
  151. bool success = item.Install(File::GetUserPath(D_LOAD_IDX));
  152. if (!success)
  153. {
  154. ModalMessageBox::critical(
  155. this, tr("Error"),
  156. tr("Failed to install pack: %1").arg(QString::fromStdString(item.GetError())));
  157. }
  158. RepopulateTable();
  159. }
  160. void ResourcePackManager::Uninstall()
  161. {
  162. auto items = m_table_widget->selectedItems();
  163. if (items.empty())
  164. return;
  165. auto& item = ResourcePack::GetPacks()[GetResourcePackIndex(items[0])];
  166. bool success = item.Uninstall(File::GetUserPath(D_LOAD_IDX));
  167. if (!success)
  168. {
  169. ModalMessageBox::critical(
  170. this, tr("Error"),
  171. tr("Failed to uninstall pack: %1").arg(QString::fromStdString(item.GetError())));
  172. }
  173. RepopulateTable();
  174. }
  175. void ResourcePackManager::Remove()
  176. {
  177. auto items = m_table_widget->selectedItems();
  178. if (items.empty())
  179. return;
  180. ModalMessageBox box(this);
  181. box.setWindowTitle(tr("Confirmation"));
  182. box.setText(tr("Are you sure you want to delete this pack?"));
  183. box.setIcon(QMessageBox::Warning);
  184. box.setStandardButtons(QMessageBox::Yes | QMessageBox::Abort);
  185. if (box.exec() != QMessageBox::Yes)
  186. return;
  187. Uninstall();
  188. File::Delete(ResourcePack::GetPacks()[GetResourcePackIndex(items[0])].GetPath());
  189. RepopulateTable();
  190. }
  191. void ResourcePackManager::PriorityDown()
  192. {
  193. auto items = m_table_widget->selectedItems();
  194. if (items.empty())
  195. return;
  196. auto row = GetResourcePackIndex(items[0]);
  197. if (items[0]->row() >= m_table_widget->rowCount())
  198. return;
  199. auto& pack = ResourcePack::GetPacks()[row];
  200. std::string path = pack.GetPath();
  201. row--;
  202. ResourcePack::Remove(pack);
  203. ResourcePack::Add(path, row);
  204. RepopulateTable();
  205. m_table_widget->selectRow(row == 0 ? m_table_widget->rowCount() - 1 : row);
  206. }
  207. void ResourcePackManager::PriorityUp()
  208. {
  209. auto items = m_table_widget->selectedItems();
  210. if (items.empty())
  211. return;
  212. auto row = GetResourcePackIndex(items[0]);
  213. if (items[0]->row() == 0)
  214. return;
  215. auto& pack = ResourcePack::GetPacks()[row];
  216. std::string path = pack.GetPath();
  217. row++;
  218. ResourcePack::Remove(pack);
  219. ResourcePack::Add(path, items[0]->row() == m_table_widget->rowCount() ? -1 : row);
  220. RepopulateTable();
  221. m_table_widget->selectRow(row == m_table_widget->rowCount() - 1 ? 0 : row);
  222. }
  223. void ResourcePackManager::Refresh()
  224. {
  225. ResourcePack::Init();
  226. RepopulateTable();
  227. }
  228. void ResourcePackManager::SelectionChanged()
  229. {
  230. auto items = m_table_widget->selectedItems();
  231. const bool has_selection = !items.empty();
  232. if (has_selection)
  233. {
  234. m_change_button->setText(
  235. ResourcePack::IsInstalled(ResourcePack::GetPacks()[GetResourcePackIndex(items[0])]) ?
  236. tr("Uninstall") :
  237. tr("Install"));
  238. }
  239. for (auto* item : {m_change_button, m_remove_button})
  240. item->setEnabled(has_selection);
  241. m_priority_down_button->setEnabled(has_selection &&
  242. items[0]->row() < m_table_widget->rowCount() - 1);
  243. m_priority_up_button->setEnabled(has_selection && items[0]->row() != 0);
  244. }
  245. void ResourcePackManager::ItemDoubleClicked(QTableWidgetItem* item)
  246. {
  247. auto item_data = item->data(Qt::UserRole);
  248. if (item_data.isNull())
  249. return;
  250. QDesktopServices::openUrl(QUrl(item_data.toString()));
  251. }