Merge pull request #7 from georgemoralis/new_game_list
New main window , game list , game grid modes
This commit is contained in:
commit
7ef659ff3f
|
@ -400,3 +400,4 @@ FodyWeavers.xsd
|
||||||
/shadPS4/psf.txt
|
/shadPS4/psf.txt
|
||||||
/tools/pkg extractor/game/*
|
/tools/pkg extractor/game/*
|
||||||
/tools/pkg extractor/*.pkg
|
/tools/pkg extractor/*.pkg
|
||||||
|
/shadPS4/shadps4.ini
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDockWidget>
|
||||||
|
#include <QStyleOption>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
class custom_dock_widget : public QDockWidget
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::shared_ptr<QWidget> m_title_bar_widget;
|
||||||
|
bool m_is_title_bar_visible = true;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit custom_dock_widget(const QString& title, QWidget* parent = Q_NULLPTR, Qt::WindowFlags flags = Qt::WindowFlags())
|
||||||
|
: QDockWidget(title, parent, flags)
|
||||||
|
{
|
||||||
|
m_title_bar_widget.reset(titleBarWidget());
|
||||||
|
|
||||||
|
connect(this, &QDockWidget::topLevelChanged, [this](bool/* topLevel*/)
|
||||||
|
{
|
||||||
|
SetTitleBarVisible(m_is_title_bar_visible);
|
||||||
|
style()->unpolish(this);
|
||||||
|
style()->polish(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTitleBarVisible(bool visible)
|
||||||
|
{
|
||||||
|
if (visible || isFloating())
|
||||||
|
{
|
||||||
|
if (m_title_bar_widget.get() != titleBarWidget())
|
||||||
|
{
|
||||||
|
setTitleBarWidget(m_title_bar_widget.get());
|
||||||
|
QMargins margins = widget()->contentsMargins();
|
||||||
|
margins.setTop(0);
|
||||||
|
widget()->setContentsMargins(margins);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setTitleBarWidget(new QWidget());
|
||||||
|
QMargins margins = widget()->contentsMargins();
|
||||||
|
margins.setTop(1);
|
||||||
|
widget()->setContentsMargins(margins);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_is_title_bar_visible = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent* event) override
|
||||||
|
{
|
||||||
|
// We need to repaint the dock widgets as plain widgets in floating mode.
|
||||||
|
// Source: https://stackoverflow.com/questions/10272091/cannot-add-a-background-image-to-a-qdockwidget
|
||||||
|
if (isFloating())
|
||||||
|
{
|
||||||
|
QStyleOption opt;
|
||||||
|
opt.initFrom(this);
|
||||||
|
QPainter p(this);
|
||||||
|
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use inherited method for docked mode because otherwise the dock would lose the title etc.
|
||||||
|
QDockWidget::paintEvent(event);
|
||||||
|
}
|
||||||
|
};
|
|
@ -3,7 +3,7 @@
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
custom_table_widget_item::custom_table_widget_item(const std::string& text, int sort_role, const QVariant& sort_value)
|
custom_table_widget_item::custom_table_widget_item(const std::string& text, int sort_role, const QVariant& sort_value)
|
||||||
: QTableWidgetItem(QString::fromStdString(text).simplified()) // simplified() forces single line text
|
: game_list_item(QString::fromStdString(text).simplified()) // simplified() forces single line text
|
||||||
{
|
{
|
||||||
if (sort_role != Qt::DisplayRole)
|
if (sort_role != Qt::DisplayRole)
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ custom_table_widget_item::custom_table_widget_item(const std::string& text, int
|
||||||
}
|
}
|
||||||
|
|
||||||
custom_table_widget_item::custom_table_widget_item(const QString& text, int sort_role, const QVariant& sort_value)
|
custom_table_widget_item::custom_table_widget_item(const QString& text, int sort_role, const QVariant& sort_value)
|
||||||
: QTableWidgetItem(text.simplified()) // simplified() forces single line text
|
: game_list_item(text.simplified()) // simplified() forces single line text
|
||||||
{
|
{
|
||||||
if (sort_role != Qt::DisplayRole)
|
if (sort_role != Qt::DisplayRole)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "game_list_item.h"
|
||||||
#include <QTableWidgetItem>
|
#include <QTableWidgetItem>
|
||||||
|
|
||||||
class custom_table_widget_item : public QTableWidgetItem
|
class custom_table_widget_item : public game_list_item
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int m_sort_role = Qt::DisplayRole;
|
int m_sort_role = Qt::DisplayRole;
|
||||||
|
|
|
@ -1,6 +1,511 @@
|
||||||
#include "game_list_frame.h"
|
#include "game_list_frame.h"
|
||||||
#include "gui_settings.h"
|
#include "gui_settings.h"
|
||||||
|
#include "custom_table_widget_item.h"
|
||||||
|
#include "qt_utils.h"
|
||||||
|
#include "../emulator/fileFormat/PSF.h"
|
||||||
|
#include <QPainter>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
game_list_frame::game_list_frame(std::shared_ptr<gui_settings> gui_settings, QWidget* parent)
|
||||||
|
: custom_dock_widget(tr("Game List"), parent)
|
||||||
|
, m_gui_settings(std::move(gui_settings))
|
||||||
|
{
|
||||||
|
m_icon_size = gui::game_list_icon_size_min; // ensure a valid size
|
||||||
|
m_is_list_layout = m_gui_settings->GetValue(gui::game_list_listMode).toBool();
|
||||||
|
m_margin_factor = m_gui_settings->GetValue(gui::game_list_marginFactor).toReal();
|
||||||
|
m_text_factor = m_gui_settings->GetValue(gui::game_list_textFactor).toReal();
|
||||||
|
m_icon_color = m_gui_settings->GetValue(gui::game_list_iconColor).value<QColor>();
|
||||||
|
m_col_sort_order = m_gui_settings->GetValue(gui::game_list_sortAsc).toBool() ? Qt::AscendingOrder : Qt::DescendingOrder;
|
||||||
|
m_sort_column = m_gui_settings->GetValue(gui::game_list_sortCol).toInt();
|
||||||
|
|
||||||
|
m_old_layout_is_list = m_is_list_layout;
|
||||||
|
|
||||||
|
// Save factors for first setup
|
||||||
|
m_gui_settings->SetValue(gui::game_list_iconColor, m_icon_color);
|
||||||
|
m_gui_settings->SetValue(gui::game_list_marginFactor, m_margin_factor);
|
||||||
|
m_gui_settings->SetValue(gui::game_list_textFactor, m_text_factor);
|
||||||
|
|
||||||
|
m_game_dock = new QMainWindow(this);
|
||||||
|
m_game_dock->setWindowFlags(Qt::Widget);
|
||||||
|
setWidget(m_game_dock);
|
||||||
|
|
||||||
|
m_game_grid = new game_list_grid(QSize(), m_icon_color, m_margin_factor, m_text_factor, false);
|
||||||
|
|
||||||
|
m_game_list = new game_list_table();
|
||||||
|
m_game_list->setShowGrid(false);
|
||||||
|
m_game_list->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
|
m_game_list->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
m_game_list->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
m_game_list->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||||
|
m_game_list->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||||
|
m_game_list->verticalScrollBar()->installEventFilter(this);
|
||||||
|
m_game_list->verticalScrollBar()->setSingleStep(20);
|
||||||
|
m_game_list->horizontalScrollBar()->setSingleStep(20);
|
||||||
|
m_game_list->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
|
||||||
|
m_game_list->verticalHeader()->setVisible(false);
|
||||||
|
m_game_list->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
m_game_list->horizontalHeader()->setHighlightSections(false);
|
||||||
|
m_game_list->horizontalHeader()->setSortIndicatorShown(true);
|
||||||
|
m_game_list->horizontalHeader()->setStretchLastSection(true);
|
||||||
|
m_game_list->horizontalHeader()->setDefaultSectionSize(150);
|
||||||
|
m_game_list->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
|
||||||
|
m_game_list->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
m_game_list->setAlternatingRowColors(true);
|
||||||
|
m_game_list->installEventFilter(this);
|
||||||
|
m_game_list->setColumnCount(gui::column_count);
|
||||||
|
|
||||||
|
m_central_widget = new QStackedWidget(this);
|
||||||
|
m_central_widget->addWidget(m_game_list);
|
||||||
|
m_central_widget->addWidget(m_game_grid);
|
||||||
|
m_central_widget->setCurrentWidget(m_is_list_layout ? m_game_list : m_game_grid);
|
||||||
|
|
||||||
|
m_game_dock->setCentralWidget(m_central_widget);
|
||||||
|
|
||||||
|
// Actions regarding showing/hiding columns
|
||||||
|
auto add_column = [this](gui::game_list_columns col, const QString& header_text, const QString& action_text)
|
||||||
|
{
|
||||||
|
m_game_list->setHorizontalHeaderItem(col, new QTableWidgetItem(header_text));
|
||||||
|
m_columnActs.append(new QAction(action_text, this));
|
||||||
|
};
|
||||||
|
|
||||||
|
add_column(gui::column_icon, tr("Icon"), tr("Show Icons"));
|
||||||
|
add_column(gui::column_name, tr("Name"), tr("Show Names"));
|
||||||
|
add_column(gui::column_serial, tr("Serial"), tr("Show Serials"));
|
||||||
|
add_column(gui::column_firmware, tr("Firmware"), tr("Show Firmwares"));
|
||||||
|
add_column(gui::column_version, tr("Version"), tr("Show Versions"));
|
||||||
|
add_column(gui::column_category, tr("Category"), tr("Show Categories"));
|
||||||
|
add_column(gui::column_path, tr("Path"), tr("Show Paths"));
|
||||||
|
|
||||||
|
for (int col = 0; col < m_columnActs.count(); ++col)
|
||||||
|
{
|
||||||
|
m_columnActs[col]->setCheckable(true);
|
||||||
|
|
||||||
|
connect(m_columnActs[col], &QAction::triggered, this, [this, col](bool checked)
|
||||||
|
{
|
||||||
|
if (!checked) // be sure to have at least one column left so you can call the context menu at all time
|
||||||
|
{
|
||||||
|
int c = 0;
|
||||||
|
for (int i = 0; i < m_columnActs.count(); ++i)
|
||||||
|
{
|
||||||
|
if (m_gui_settings->GetGamelistColVisibility(i) && ++c > 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c < 2)
|
||||||
|
{
|
||||||
|
m_columnActs[col]->setChecked(true); // re-enable the checkbox if we don't change the actual state
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_game_list->setColumnHidden(col, !checked); // Negate because it's a set col hidden and we have menu say show.
|
||||||
|
m_gui_settings->SetGamelistColVisibility(col, checked);
|
||||||
|
|
||||||
|
if (checked) // handle hidden columns that have zero width after showing them (stuck between others)
|
||||||
|
{
|
||||||
|
FixNarrowColumns();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//events
|
||||||
|
connect(m_game_list->horizontalHeader(), &QHeaderView::customContextMenuRequested, this, [this](const QPoint& pos)
|
||||||
|
{
|
||||||
|
QMenu* configure = new QMenu(this);
|
||||||
|
configure->addActions(m_columnActs);
|
||||||
|
configure->exec(m_game_list->horizontalHeader()->viewport()->mapToGlobal(pos));
|
||||||
|
});
|
||||||
|
connect(m_game_list->horizontalHeader(), &QHeaderView::sectionClicked, this, &game_list_frame::OnHeaderColumnClicked);
|
||||||
|
connect(&m_repaint_watcher, &QFutureWatcher<game_list_item*>::resultReadyAt, this, [this](int index)
|
||||||
|
{
|
||||||
|
if (!m_is_list_layout) return;
|
||||||
|
if (game_list_item* item = m_repaint_watcher.resultAt(index))
|
||||||
|
{
|
||||||
|
item->call_icon_func();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(&m_repaint_watcher, &QFutureWatcher<game_list_item*>::finished, this, &game_list_frame::OnRepaintFinished);
|
||||||
|
|
||||||
|
connect(&m_refresh_watcher, &QFutureWatcher<void>::finished, this, &game_list_frame::OnRefreshFinished);
|
||||||
|
connect(&m_refresh_watcher, &QFutureWatcher<void>::canceled, this, [this]()
|
||||||
|
{
|
||||||
|
gui::utils::stop_future_watcher(m_repaint_watcher, true);
|
||||||
|
|
||||||
|
m_path_list.clear();
|
||||||
|
m_game_data.clear();
|
||||||
|
m_games.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
game_list_frame::~game_list_frame() {
|
||||||
|
gui::utils::stop_future_watcher(m_repaint_watcher, true);
|
||||||
|
gui::utils::stop_future_watcher(m_refresh_watcher, true);
|
||||||
|
SaveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_list_frame::OnRefreshFinished()
|
||||||
|
{
|
||||||
|
gui::utils::stop_future_watcher(m_repaint_watcher, true);
|
||||||
|
for (auto&& g : m_games)
|
||||||
|
{
|
||||||
|
m_game_data.push_back(g);
|
||||||
|
}
|
||||||
|
m_games.clear();
|
||||||
|
// Sort by name at the very least.
|
||||||
|
std::sort(m_game_data.begin(), m_game_data.end(), [&](const game_info& game1, const game_info& game2)
|
||||||
|
{
|
||||||
|
const QString title1 = m_titles.value(QString::fromStdString(game1->info.serial), QString::fromStdString(game1->info.name));
|
||||||
|
const QString title2 = m_titles.value(QString::fromStdString(game2->info.serial), QString::fromStdString(game2->info.name));
|
||||||
|
return title1.toLower() < title2.toLower();
|
||||||
|
});
|
||||||
|
|
||||||
|
m_path_list.clear();
|
||||||
|
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_list_frame::OnRepaintFinished()
|
||||||
|
{
|
||||||
|
if (m_is_list_layout)
|
||||||
|
{
|
||||||
|
// Fixate vertical header and row height
|
||||||
|
m_game_list->verticalHeader()->setMinimumSectionSize(m_icon_size.height());
|
||||||
|
m_game_list->verticalHeader()->setMaximumSectionSize(m_icon_size.height());
|
||||||
|
|
||||||
|
// Resize the icon column
|
||||||
|
m_game_list->resizeColumnToContents(gui::column_icon);
|
||||||
|
|
||||||
|
// Shorten the last section to remove horizontal scrollbar if possible
|
||||||
|
m_game_list->resizeColumnToContents(gui::column_count - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The game grid needs to be recreated from scratch
|
||||||
|
int games_per_row = 0;
|
||||||
|
|
||||||
|
if (m_icon_size.width() > 0 && m_icon_size.height() > 0)
|
||||||
|
{
|
||||||
|
games_per_row = width() / (m_icon_size.width() + m_icon_size.width() * m_game_grid->getMarginFactor() * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int scroll_position = m_game_grid->verticalScrollBar()->value();
|
||||||
|
//TODO add connections
|
||||||
|
PopulateGameGrid(games_per_row, m_icon_size, m_icon_color);
|
||||||
|
m_central_widget->addWidget(m_game_grid);
|
||||||
|
m_central_widget->setCurrentWidget(m_game_grid);
|
||||||
|
m_game_grid->verticalScrollBar()->setValue(scroll_position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool game_list_frame::IsEntryVisible(const game_info& game)
|
||||||
|
{
|
||||||
|
const QString serial = QString::fromStdString(game->info.serial);
|
||||||
|
return SearchMatchesApp(QString::fromStdString(game->info.name), serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_list_frame::PopulateGameGrid(int maxCols, const QSize& image_size, const QColor& image_color)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
int c = 0;
|
||||||
|
|
||||||
|
const std::string selected_item = CurrentSelectionPath();
|
||||||
|
|
||||||
|
// Release old data
|
||||||
|
m_game_list->clear_list();
|
||||||
|
m_game_grid->deleteLater();
|
||||||
|
|
||||||
|
const bool show_text = m_icon_size_index > gui::game_list_max_slider_pos * 2 / 5;
|
||||||
|
|
||||||
|
if (m_icon_size_index < gui::game_list_max_slider_pos * 2 / 3)
|
||||||
|
{
|
||||||
|
m_game_grid = new game_list_grid(image_size, image_color, m_margin_factor, m_text_factor * 2, show_text);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_game_grid = new game_list_grid(image_size, image_color, m_margin_factor, m_text_factor, show_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get list of matching apps
|
||||||
|
QList<game_info> matching_apps;
|
||||||
|
|
||||||
|
for (const auto& app : m_game_data)
|
||||||
|
{
|
||||||
|
if (IsEntryVisible(app))
|
||||||
|
{
|
||||||
|
matching_apps.push_back(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const int entries = matching_apps.count();
|
||||||
|
|
||||||
|
// Edge cases!
|
||||||
|
if (entries == 0)
|
||||||
|
{ // For whatever reason, 0%x is division by zero. Absolute nonsense by definition of modulus. But, I'll acquiesce.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
maxCols = std::clamp(maxCols, 1, entries);
|
||||||
|
|
||||||
|
const int needs_extra_row = (entries % maxCols) != 0;
|
||||||
|
const int max_rows = needs_extra_row + entries / maxCols;
|
||||||
|
m_game_grid->setRowCount(max_rows);
|
||||||
|
m_game_grid->setColumnCount(maxCols);
|
||||||
|
|
||||||
|
for (const auto& app : matching_apps)
|
||||||
|
{
|
||||||
|
const QString serial = QString::fromStdString(app->info.serial);
|
||||||
|
const QString title = m_titles.value(serial, QString::fromStdString(app->info.name));
|
||||||
|
|
||||||
|
game_list_item* item = m_game_grid->addItem(app, title, r, c);
|
||||||
|
app->item = item;
|
||||||
|
item->setData(gui::game_role, QVariant::fromValue(app));
|
||||||
|
|
||||||
|
item->setToolTip(tr("%0 [%1]").arg(title).arg(serial));
|
||||||
|
|
||||||
|
|
||||||
|
if (selected_item == app->info.path + app->info.icon_path)
|
||||||
|
{
|
||||||
|
m_game_grid->setCurrentItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++c >= maxCols)
|
||||||
|
{
|
||||||
|
c = 0;
|
||||||
|
r++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c != 0)
|
||||||
|
{ // if left over games exist -- if empty entries exist
|
||||||
|
for (int col = c; col < maxCols; ++col)
|
||||||
|
{
|
||||||
|
game_list_item* empty_item = new game_list_item();
|
||||||
|
empty_item->setFlags(Qt::NoItemFlags);
|
||||||
|
m_game_grid->setItem(r, col, empty_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_game_grid->resizeColumnsToContents();
|
||||||
|
m_game_grid->resizeRowsToContents();
|
||||||
|
m_game_grid->installEventFilter(this);
|
||||||
|
m_game_grid->verticalScrollBar()->installEventFilter(this);
|
||||||
|
}
|
||||||
|
void game_list_frame::Refresh(const bool from_drive, const bool scroll_after)
|
||||||
|
{
|
||||||
|
gui::utils::stop_future_watcher(m_repaint_watcher, true);
|
||||||
|
gui::utils::stop_future_watcher(m_refresh_watcher, from_drive);
|
||||||
|
|
||||||
|
if (from_drive)
|
||||||
|
{
|
||||||
|
m_path_list.clear();
|
||||||
|
m_game_data.clear();
|
||||||
|
m_games.clear();
|
||||||
|
|
||||||
|
//TODO better ATM manually add path from 1 dir to m_paths_list
|
||||||
|
QDir parent_folder(QString::fromStdString(QDir::currentPath().toStdString() + "/game/"));
|
||||||
|
QFileInfoList fList = parent_folder.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::DirsFirst);
|
||||||
|
foreach(QFileInfo item, fList)
|
||||||
|
{
|
||||||
|
m_path_list.emplace_back(item.absoluteFilePath().toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_refresh_watcher.setFuture(QtConcurrent::map(m_path_list, [this](const std::string& dir)
|
||||||
|
{
|
||||||
|
GameInfo game{};
|
||||||
|
game.path = dir;
|
||||||
|
PSF psf;
|
||||||
|
if (psf.open(game.path + "/sce_sys/PARAM.SFO"))
|
||||||
|
{
|
||||||
|
QString iconpath(QString::fromStdString(game.path) + "/sce_sys/ICON0.PNG");
|
||||||
|
game.icon_path = iconpath.toStdString();
|
||||||
|
game.name = psf.get_string("TITLE");
|
||||||
|
game.serial = psf.get_string("TITLE_ID");
|
||||||
|
game.fw = (QString("%1").arg(psf.get_integer("SYSTEM_VER"), 8, 16, QLatin1Char('0'))).mid(1, 3).insert(1, '.').toStdString();
|
||||||
|
game.version = psf.get_string("APP_VER");
|
||||||
|
game.category = psf.get_string("CATEGORY");
|
||||||
|
|
||||||
|
m_titles.insert(QString::fromStdString(game.serial), QString::fromStdString(game.name));
|
||||||
|
|
||||||
|
gui_game_info info{};
|
||||||
|
info.info = game;
|
||||||
|
|
||||||
|
m_games.push_back(std::make_shared<gui_game_info>(std::move(info)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Fill Game List / Game Grid
|
||||||
|
|
||||||
|
if (m_is_list_layout)
|
||||||
|
{
|
||||||
|
const int scroll_position = m_game_list->verticalScrollBar()->value();
|
||||||
|
PopulateGameList();
|
||||||
|
SortGameList();
|
||||||
|
RepaintIcons();
|
||||||
|
|
||||||
|
if (scroll_after)
|
||||||
|
{
|
||||||
|
m_game_list->scrollTo(m_game_list->currentIndex(), QAbstractItemView::PositionAtCenter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_game_list->verticalScrollBar()->setValue(scroll_position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RepaintIcons();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Cleans and readds entries to table widget in UI.
|
||||||
|
*/
|
||||||
|
void game_list_frame::PopulateGameList()
|
||||||
|
{
|
||||||
|
int selected_row = -1;
|
||||||
|
|
||||||
|
const std::string selected_item = CurrentSelectionPath();
|
||||||
|
|
||||||
|
// Release old data
|
||||||
|
m_game_grid->clear_list();
|
||||||
|
m_game_list->clear_list();
|
||||||
|
|
||||||
|
m_game_list->setRowCount(m_game_data.size());
|
||||||
|
|
||||||
|
int row = 0;
|
||||||
|
int index = -1;
|
||||||
|
for (const auto& game : m_game_data)
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (!IsEntryVisible(game))
|
||||||
|
{
|
||||||
|
game->item = nullptr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString serial = QString::fromStdString(game->info.serial);
|
||||||
|
const QString title = m_titles.value(serial, QString::fromStdString(game->info.name));
|
||||||
|
|
||||||
|
// Icon
|
||||||
|
custom_table_widget_item* icon_item = new custom_table_widget_item;
|
||||||
|
game->item = icon_item;
|
||||||
|
icon_item->set_icon_func([this, icon_item, game](int)
|
||||||
|
{
|
||||||
|
icon_item->setData(Qt::DecorationRole, game->pxmap);
|
||||||
|
game->pxmap = {};
|
||||||
|
});
|
||||||
|
|
||||||
|
icon_item->setData(Qt::UserRole, index, true);
|
||||||
|
icon_item->setData(gui::custom_roles::game_role, QVariant::fromValue(game));
|
||||||
|
|
||||||
|
// Title
|
||||||
|
custom_table_widget_item* title_item = new custom_table_widget_item(title);
|
||||||
|
|
||||||
|
// Serial
|
||||||
|
custom_table_widget_item* serial_item = new custom_table_widget_item(serial);
|
||||||
|
|
||||||
|
// Version
|
||||||
|
QString app_version = QString::fromStdString(game->info.version);
|
||||||
|
|
||||||
|
m_game_list->setItem(row, gui::column_icon, icon_item);
|
||||||
|
m_game_list->setItem(row, gui::column_name, title_item);
|
||||||
|
m_game_list->setItem(row, gui::column_serial, serial_item);
|
||||||
|
m_game_list->setItem(row, gui::column_firmware, new custom_table_widget_item(game->info.fw));
|
||||||
|
m_game_list->setItem(row, gui::column_version, new custom_table_widget_item(app_version));
|
||||||
|
m_game_list->setItem(row, gui::column_category, new custom_table_widget_item(game->info.category));
|
||||||
|
m_game_list->setItem(row, gui::column_path, new custom_table_widget_item(game->info.path));
|
||||||
|
|
||||||
|
if (selected_item == game->info.path + game->info.icon_path)
|
||||||
|
{
|
||||||
|
selected_row = row;
|
||||||
|
}
|
||||||
|
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
m_game_list->setRowCount(row);
|
||||||
|
m_game_list->selectRow(selected_row);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string game_list_frame::CurrentSelectionPath()
|
||||||
|
{
|
||||||
|
std::string selection;
|
||||||
|
|
||||||
|
QTableWidgetItem* item = nullptr;
|
||||||
|
|
||||||
|
if (m_old_layout_is_list)
|
||||||
|
{
|
||||||
|
if (!m_game_list->selectedItems().isEmpty())
|
||||||
|
{
|
||||||
|
item = m_game_list->item(m_game_list->currentRow(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_game_grid)
|
||||||
|
{
|
||||||
|
if (!m_game_grid->selectedItems().isEmpty())
|
||||||
|
{
|
||||||
|
item = m_game_grid->currentItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item)
|
||||||
|
{
|
||||||
|
if (const QVariant var = item->data(gui::game_role); var.canConvert<game_info>())
|
||||||
|
{
|
||||||
|
if (const game_info game = var.value<game_info>())
|
||||||
|
{
|
||||||
|
selection = game->info.path + game->info.icon_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_old_layout_is_list = m_is_list_layout;
|
||||||
|
|
||||||
|
return selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_list_frame::RepaintIcons(const bool& from_settings)
|
||||||
|
{
|
||||||
|
gui::utils::stop_future_watcher(m_repaint_watcher, true);
|
||||||
|
|
||||||
|
if (from_settings)
|
||||||
|
{
|
||||||
|
//TODO m_icon_color = gui::utils::get_label_color("gamelist_icon_background_color");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_is_list_layout)
|
||||||
|
{
|
||||||
|
QPixmap placeholder(m_icon_size);
|
||||||
|
placeholder.fill(Qt::transparent);
|
||||||
|
|
||||||
|
for (auto& game : m_game_data)
|
||||||
|
{
|
||||||
|
game->pxmap = placeholder;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fixate vertical header and row height
|
||||||
|
m_game_list->verticalHeader()->setMinimumSectionSize(m_icon_size.height());
|
||||||
|
m_game_list->verticalHeader()->setMaximumSectionSize(m_icon_size.height());
|
||||||
|
|
||||||
|
// Resize the icon column
|
||||||
|
m_game_list->resizeColumnToContents(gui::column_icon);
|
||||||
|
|
||||||
|
// Shorten the last section to remove horizontal scrollbar if possible
|
||||||
|
m_game_list->resizeColumnToContents(gui::column_count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::function func = [this](const game_info& game) -> game_list_item*
|
||||||
|
{
|
||||||
|
if (game->icon.isNull() && (game->info.icon_path.empty() || !game->icon.load(QString::fromStdString(game->info.icon_path))))
|
||||||
|
{
|
||||||
|
//TODO added warning message if no found
|
||||||
|
}
|
||||||
|
game->pxmap = PaintedPixmap(game->icon);
|
||||||
|
return game->item;
|
||||||
|
};
|
||||||
|
m_repaint_watcher.setFuture(QtConcurrent::mapped(m_game_data, func));
|
||||||
|
}
|
||||||
|
|
||||||
void game_list_frame::FixNarrowColumns() const
|
void game_list_frame::FixNarrowColumns() const
|
||||||
{
|
{
|
||||||
|
@ -44,6 +549,26 @@ void game_list_frame::ResizeColumnsToContents(int spacing) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void game_list_frame::OnHeaderColumnClicked(int col)
|
||||||
|
{
|
||||||
|
if (col == 0) return; // Don't "sort" icons.
|
||||||
|
|
||||||
|
if (col == m_sort_column)
|
||||||
|
{
|
||||||
|
m_col_sort_order = (m_col_sort_order == Qt::AscendingOrder) ? Qt::DescendingOrder : Qt::AscendingOrder;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_col_sort_order = Qt::AscendingOrder;
|
||||||
|
}
|
||||||
|
m_sort_column = col;
|
||||||
|
|
||||||
|
m_gui_settings->SetValue(gui::game_list_sortAsc, m_col_sort_order == Qt::AscendingOrder);
|
||||||
|
m_gui_settings->SetValue(gui::game_list_sortCol, col);
|
||||||
|
|
||||||
|
SortGameList();
|
||||||
|
}
|
||||||
|
|
||||||
void game_list_frame::SortGameList() const
|
void game_list_frame::SortGameList() const
|
||||||
{
|
{
|
||||||
// Back-up old header sizes to handle unwanted column resize in case of zero search results
|
// Back-up old header sizes to handle unwanted column resize in case of zero search results
|
||||||
|
@ -110,3 +635,149 @@ void game_list_frame::SortGameList() const
|
||||||
// Shorten the last section to remove horizontal scrollbar if possible
|
// Shorten the last section to remove horizontal scrollbar if possible
|
||||||
m_game_list->resizeColumnToContents(gui::column_count - 1);
|
m_game_list->resizeColumnToContents(gui::column_count - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPixmap game_list_frame::PaintedPixmap(const QPixmap& icon) const
|
||||||
|
{
|
||||||
|
const qreal device_pixel_ratio = devicePixelRatioF();
|
||||||
|
QSize canvas_size(320, 176);
|
||||||
|
QSize icon_size(icon.size());
|
||||||
|
QPoint target_pos;
|
||||||
|
|
||||||
|
if (!icon.isNull())
|
||||||
|
{
|
||||||
|
// Let's upscale the original icon to at least fit into the outer rect of the size of PS3's ICON0.PNG
|
||||||
|
if (icon_size.width() < 320 || icon_size.height() < 176)
|
||||||
|
{
|
||||||
|
icon_size.scale(320, 176, Qt::KeepAspectRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas_size = icon_size;
|
||||||
|
|
||||||
|
// Calculate the centered size and position of the icon on our canvas.
|
||||||
|
if (icon_size.width() != 320 || icon_size.height() != 176)
|
||||||
|
{
|
||||||
|
constexpr double target_ratio = 320.0 / 176.0; // aspect ratio 20:11
|
||||||
|
|
||||||
|
if ((icon_size.width() / static_cast<double>(icon_size.height())) > target_ratio)
|
||||||
|
{
|
||||||
|
canvas_size.setHeight(std::ceil(icon_size.width() / target_ratio));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
canvas_size.setWidth(std::ceil(icon_size.height() * target_ratio));
|
||||||
|
}
|
||||||
|
|
||||||
|
target_pos.setX(std::max<int>(0, (canvas_size.width() - icon_size.width()) / 2.0));
|
||||||
|
target_pos.setY(std::max<int>(0, (canvas_size.height() - icon_size.height()) / 2.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a canvas large enough to fit our entire scaled icon
|
||||||
|
QPixmap canvas(canvas_size * device_pixel_ratio);
|
||||||
|
canvas.setDevicePixelRatio(device_pixel_ratio);
|
||||||
|
canvas.fill(m_icon_color);
|
||||||
|
|
||||||
|
// Create a painter for our canvas
|
||||||
|
QPainter painter(&canvas);
|
||||||
|
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||||
|
|
||||||
|
// Draw the icon onto our canvas
|
||||||
|
if (!icon.isNull())
|
||||||
|
{
|
||||||
|
painter.drawPixmap(target_pos.x(), target_pos.y(), icon_size.width(), icon_size.height(), icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish the painting
|
||||||
|
painter.end();
|
||||||
|
|
||||||
|
// Scale and return our final image
|
||||||
|
return canvas.scaled(m_icon_size * device_pixel_ratio, Qt::KeepAspectRatio, Qt::TransformationMode::SmoothTransformation);
|
||||||
|
}
|
||||||
|
void game_list_frame::SetListMode(const bool& is_list)
|
||||||
|
{
|
||||||
|
m_old_layout_is_list = m_is_list_layout;
|
||||||
|
m_is_list_layout = is_list;
|
||||||
|
|
||||||
|
m_gui_settings->SetValue(gui::game_list_listMode, is_list);
|
||||||
|
|
||||||
|
Refresh(true);
|
||||||
|
|
||||||
|
m_central_widget->setCurrentWidget(m_is_list_layout ? m_game_list : m_game_grid);
|
||||||
|
}
|
||||||
|
void game_list_frame::SetSearchText(const QString& text)
|
||||||
|
{
|
||||||
|
m_search_text = text;
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
void game_list_frame::closeEvent(QCloseEvent* event)
|
||||||
|
{
|
||||||
|
QDockWidget::closeEvent(event);
|
||||||
|
Q_EMIT GameListFrameClosed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_list_frame::resizeEvent(QResizeEvent* event)
|
||||||
|
{
|
||||||
|
if (!m_is_list_layout)
|
||||||
|
{
|
||||||
|
Refresh(false, m_game_grid->selectedItems().count());
|
||||||
|
}
|
||||||
|
QDockWidget::resizeEvent(event);
|
||||||
|
}
|
||||||
|
void game_list_frame::ResizeIcons(const int& slider_pos)
|
||||||
|
{
|
||||||
|
m_icon_size_index = slider_pos;
|
||||||
|
m_icon_size = gui_settings::SizeFromSlider(slider_pos);
|
||||||
|
|
||||||
|
RepaintIcons();
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_list_frame::LoadSettings()
|
||||||
|
{
|
||||||
|
m_col_sort_order = m_gui_settings->GetValue(gui::game_list_sortAsc).toBool() ? Qt::AscendingOrder : Qt::DescendingOrder;
|
||||||
|
m_sort_column = m_gui_settings->GetValue(gui::game_list_sortCol).toInt();
|
||||||
|
|
||||||
|
Refresh(true);
|
||||||
|
|
||||||
|
const QByteArray state = m_gui_settings->GetValue(gui::game_list_state).toByteArray();
|
||||||
|
if (!m_game_list->horizontalHeader()->restoreState(state) && m_game_list->rowCount())
|
||||||
|
{
|
||||||
|
// If no settings exist, resize to contents.
|
||||||
|
ResizeColumnsToContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int col = 0; col < m_columnActs.count(); ++col)
|
||||||
|
{
|
||||||
|
const bool vis = m_gui_settings->GetGamelistColVisibility(col);
|
||||||
|
m_columnActs[col]->setChecked(vis);
|
||||||
|
m_game_list->setColumnHidden(col, !vis);
|
||||||
|
}
|
||||||
|
SortGameList();
|
||||||
|
FixNarrowColumns();
|
||||||
|
|
||||||
|
m_game_list->horizontalHeader()->restoreState(m_game_list->horizontalHeader()->saveState());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_list_frame::SaveSettings()
|
||||||
|
{
|
||||||
|
for (int col = 0; col < m_columnActs.count(); ++col)
|
||||||
|
{
|
||||||
|
m_gui_settings->SetGamelistColVisibility(col, m_columnActs[col]->isChecked());
|
||||||
|
}
|
||||||
|
m_gui_settings->SetValue(gui::game_list_sortCol, m_sort_column);
|
||||||
|
m_gui_settings->SetValue(gui::game_list_sortAsc, m_col_sort_order == Qt::AscendingOrder);
|
||||||
|
m_gui_settings->SetValue(gui::game_list_state, m_game_list->horizontalHeader()->saveState());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns false if the game should be hidden because it doesn't match search term in toolbar.
|
||||||
|
*/
|
||||||
|
bool game_list_frame::SearchMatchesApp(const QString& name, const QString& serial) const
|
||||||
|
{
|
||||||
|
if (!m_search_text.isEmpty())
|
||||||
|
{
|
||||||
|
const QString search_text = m_search_text.toLower();
|
||||||
|
return m_titles.value(serial, name).toLower().contains(search_text) || serial.toLower().contains(search_text);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -1,33 +1,104 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "game_list_table.h"
|
#include "game_list_table.h"
|
||||||
|
#include "custom_dock_widget.h"
|
||||||
#include "shadps4gui.h"
|
#include "shadps4gui.h"
|
||||||
|
#include "game_list_grid.h"
|
||||||
|
#include "game_list_item.h"
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
|
#include <QScrollbar>
|
||||||
|
#include <QStackedWidget>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <deque>
|
||||||
|
#include <QFutureWatcher>
|
||||||
|
#include <QtConcurrent>
|
||||||
|
|
||||||
class game_list_frame
|
class game_list_frame : public custom_dock_widget
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
public :
|
public :
|
||||||
|
explicit game_list_frame(std::shared_ptr<gui_settings> gui_settings,QWidget* parent = nullptr);
|
||||||
|
~game_list_frame();
|
||||||
/** Fix columns with width smaller than the minimal section size */
|
/** Fix columns with width smaller than the minimal section size */
|
||||||
void FixNarrowColumns() const;
|
void FixNarrowColumns() const;
|
||||||
|
|
||||||
|
/** Loads from settings. Public so that main frame can easily reset these settings if needed. */
|
||||||
|
void LoadSettings();
|
||||||
|
|
||||||
|
/** Saves settings. Public so that main frame can save this when a caching of column widths is needed for settings backup */
|
||||||
|
void SaveSettings();
|
||||||
|
|
||||||
/** Resizes the columns to their contents and adds a small spacing */
|
/** Resizes the columns to their contents and adds a small spacing */
|
||||||
void ResizeColumnsToContents(int spacing = 20) const;
|
void ResizeColumnsToContents(int spacing = 20) const;
|
||||||
|
|
||||||
|
/** Refresh the gamelist with/without loading game data from files. Public so that main frame can refresh after vfs or install */
|
||||||
|
void Refresh(const bool from_drive = false, const bool scroll_after = true);
|
||||||
|
|
||||||
|
/** Repaint Gamelist Icons with new background color */
|
||||||
|
void RepaintIcons(const bool& from_settings = false);
|
||||||
|
|
||||||
|
/** Resize Gamelist Icons to size given by slider position */
|
||||||
|
void ResizeIcons(const int& slider_pos);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void SetSearchText(const QString& text);
|
||||||
|
void SetListMode(const bool& is_list);
|
||||||
|
private Q_SLOTS:
|
||||||
|
void OnHeaderColumnClicked(int col);
|
||||||
|
void OnRepaintFinished();
|
||||||
|
void OnRefreshFinished();
|
||||||
|
Q_SIGNALS:
|
||||||
|
void GameListFrameClosed();
|
||||||
|
void RequestIconSizeChange(const int& val);
|
||||||
|
protected:
|
||||||
|
void closeEvent(QCloseEvent* event) override;
|
||||||
|
void resizeEvent(QResizeEvent* event) override;
|
||||||
private:
|
private:
|
||||||
|
QPixmap PaintedPixmap(const QPixmap& icon) const;
|
||||||
void SortGameList() const;
|
void SortGameList() const;
|
||||||
|
std::string CurrentSelectionPath();
|
||||||
|
void PopulateGameList();
|
||||||
|
void PopulateGameGrid(int maxCols, const QSize& image_size, const QColor& image_color);
|
||||||
|
bool SearchMatchesApp(const QString& name, const QString& serial) const;
|
||||||
|
bool IsEntryVisible(const game_info& game);
|
||||||
|
|
||||||
|
// Which widget we are displaying depends on if we are in grid or list mode.
|
||||||
|
QMainWindow* m_game_dock = nullptr;
|
||||||
|
QStackedWidget* m_central_widget = nullptr;
|
||||||
|
|
||||||
|
// Game Grid
|
||||||
|
game_list_grid* m_game_grid = nullptr;
|
||||||
|
|
||||||
// Game List
|
// Game List
|
||||||
game_list_table* m_game_list = nullptr;
|
game_list_table* m_game_list = nullptr;
|
||||||
QList<QAction*> m_columnActs;
|
QList<QAction*> m_columnActs;
|
||||||
Qt::SortOrder m_col_sort_order;
|
Qt::SortOrder m_col_sort_order;
|
||||||
int m_sort_column;
|
int m_sort_column;
|
||||||
|
QMap<QString, QString> m_titles;
|
||||||
|
|
||||||
|
// List Mode
|
||||||
|
bool m_is_list_layout = true;
|
||||||
|
bool m_old_layout_is_list = true;
|
||||||
|
|
||||||
// data
|
// data
|
||||||
|
std::shared_ptr<gui_settings> m_gui_settings;
|
||||||
QList<game_info> m_game_data;
|
QList<game_info> m_game_data;
|
||||||
|
std::vector<std::string> m_path_list;
|
||||||
|
std::deque<game_info> m_games;
|
||||||
|
QFutureWatcher<game_list_item*> m_repaint_watcher;
|
||||||
|
QFutureWatcher<void> m_refresh_watcher;
|
||||||
|
|
||||||
|
// Search
|
||||||
|
QString m_search_text;
|
||||||
|
|
||||||
|
// Icon Size
|
||||||
|
int m_icon_size_index = 0;
|
||||||
|
|
||||||
// Icons
|
// Icons
|
||||||
QSize m_icon_size;
|
QSize m_icon_size;
|
||||||
|
QColor m_icon_color;
|
||||||
|
qreal m_margin_factor;
|
||||||
|
qreal m_text_factor;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "game_list_grid.h"
|
#include "game_list_grid.h"
|
||||||
#include "game_list_grid_delegate.h"
|
#include "game_list_grid_delegate.h"
|
||||||
|
#include "game_list_item.h"
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
|
||||||
|
@ -56,8 +56,11 @@ void game_list_grid::setIconSize(const QSize& size) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QTableWidgetItem* game_list_grid::addItem(const game_info& app, const QString& name, const QString& movie_path, const int& row, const int& col)
|
game_list_item* game_list_grid::addItem(const game_info& app, const QString& name,const int& row, const int& col)
|
||||||
{
|
{
|
||||||
|
game_list_item* item = new game_list_item;
|
||||||
|
item->set_icon_func([this, app, item](int)
|
||||||
|
{
|
||||||
const qreal device_pixel_ratio = devicePixelRatioF();
|
const qreal device_pixel_ratio = devicePixelRatioF();
|
||||||
|
|
||||||
// define size of expanded image, which is raw image size + margins
|
// define size of expanded image, which is raw image size + margins
|
||||||
|
@ -94,9 +97,8 @@ QTableWidgetItem* game_list_grid::addItem(const game_info& app, const QString& n
|
||||||
painter.end();
|
painter.end();
|
||||||
|
|
||||||
// create item with expanded image, title and position
|
// create item with expanded image, title and position
|
||||||
QTableWidgetItem* item = new QTableWidgetItem();
|
|
||||||
item->setData(Qt::ItemDataRole::DecorationRole, QPixmap::fromImage(exp_img));
|
item->setData(Qt::ItemDataRole::DecorationRole, QPixmap::fromImage(exp_img));
|
||||||
|
});
|
||||||
if (m_text_enabled)
|
if (m_text_enabled)
|
||||||
{
|
{
|
||||||
item->setData(Qt::ItemDataRole::DisplayRole, name);
|
item->setData(Qt::ItemDataRole::DisplayRole, name);
|
||||||
|
|
|
@ -19,7 +19,7 @@ public:
|
||||||
|
|
||||||
void enableText(const bool& enabled);
|
void enableText(const bool& enabled);
|
||||||
void setIconSize(const QSize& size) const;
|
void setIconSize(const QSize& size) const;
|
||||||
QTableWidgetItem* addItem(const game_info& app, const QString& name, const QString& movie_path, const int& row, const int& col);
|
game_list_item* addItem(const game_info& app, const QString& name,const int& row, const int& col);
|
||||||
|
|
||||||
[[nodiscard]] qreal getMarginFactor() const;
|
[[nodiscard]] qreal getMarginFactor() const;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QTableWidgetItem>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
using icon_callback_t = std::function<void(int)>;
|
||||||
|
|
||||||
|
class game_list_item : public QTableWidgetItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
game_list_item() : QTableWidgetItem()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
game_list_item(const QString& text, int type = Type) : QTableWidgetItem(text, type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
game_list_item(const QIcon& icon, const QString& text, int type = Type) : QTableWidgetItem(icon, text, type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~game_list_item()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void call_icon_func() const
|
||||||
|
{
|
||||||
|
if (m_icon_callback)
|
||||||
|
{
|
||||||
|
m_icon_callback(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_icon_func(const icon_callback_t& func)
|
||||||
|
{
|
||||||
|
m_icon_callback = func;
|
||||||
|
call_icon_func();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
icon_callback_t m_icon_callback = nullptr;
|
||||||
|
};
|
|
@ -3,12 +3,14 @@
|
||||||
#include <QTableWidget>
|
#include <QTableWidget>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include "../emulator/gameInfo.h"
|
#include "../emulator/gameInfo.h"
|
||||||
|
#include "game_list_item.h"
|
||||||
|
|
||||||
struct gui_game_info
|
struct gui_game_info
|
||||||
{
|
{
|
||||||
GameInfo info{};
|
GameInfo info{};
|
||||||
QPixmap icon;
|
QPixmap icon;
|
||||||
QPixmap pxmap;
|
QPixmap pxmap;
|
||||||
|
game_list_item* item = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<gui_game_info> game_info;
|
typedef std::shared_ptr<gui_game_info> game_info;
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
struct gui_save
|
||||||
|
{
|
||||||
|
QString key;
|
||||||
|
QString name;
|
||||||
|
QVariant def;
|
||||||
|
|
||||||
|
gui_save()
|
||||||
|
{
|
||||||
|
key = "";
|
||||||
|
name = "";
|
||||||
|
def = QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_save(const QString& k, const QString& n, const QVariant& d)
|
||||||
|
{
|
||||||
|
key = k;
|
||||||
|
name = n;
|
||||||
|
def = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const gui_save& rhs) const noexcept
|
||||||
|
{
|
||||||
|
return key == rhs.key && name == rhs.name && def == rhs.def;
|
||||||
|
}
|
||||||
|
};
|
|
@ -3,6 +3,24 @@
|
||||||
|
|
||||||
gui_settings::gui_settings(QObject* parent)
|
gui_settings::gui_settings(QObject* parent)
|
||||||
{
|
{
|
||||||
m_settings.reset(new QSettings("shadps4.ini", QSettings::Format::IniFormat, parent));
|
m_settings.reset(new QSettings("shadps4.ini", QSettings::Format::IniFormat, parent)); //TODO make the path configurable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gui_settings::SetGamelistColVisibility(int col, bool val) const
|
||||||
|
{
|
||||||
|
SetValue(GetGuiSaveForColumn(col), val);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gui_settings::GetGamelistColVisibility(int col) const
|
||||||
|
{
|
||||||
|
return GetValue(GetGuiSaveForColumn(col)).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_save gui_settings::GetGuiSaveForColumn(int col)
|
||||||
|
{
|
||||||
|
return gui_save{ gui::game_list, "visibility_" + gui::get_game_list_column_name(static_cast<gui::game_list_columns>(col)), true };
|
||||||
|
}
|
||||||
|
QSize gui_settings::SizeFromSlider(int pos)
|
||||||
|
{
|
||||||
|
return gui::game_list_icon_size_min + (gui::game_list_icon_size_max - gui::game_list_icon_size_min) * (1.f * pos / gui::game_list_max_slider_pos);
|
||||||
|
}
|
|
@ -1,9 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QSettings>
|
#include "settings.h"
|
||||||
|
#include <QColor>
|
||||||
|
|
||||||
namespace gui
|
namespace gui
|
||||||
{
|
{
|
||||||
|
enum custom_roles
|
||||||
|
{
|
||||||
|
game_role = Qt::UserRole + 1337,
|
||||||
|
};
|
||||||
|
|
||||||
enum game_list_columns
|
enum game_list_columns
|
||||||
{
|
{
|
||||||
column_icon,
|
column_icon,
|
||||||
|
@ -17,15 +23,81 @@ namespace gui
|
||||||
column_count
|
column_count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline QString get_game_list_column_name(game_list_columns col)
|
||||||
|
{
|
||||||
|
switch (col)
|
||||||
|
{
|
||||||
|
case column_icon:
|
||||||
|
return "column_icon";
|
||||||
|
case column_name:
|
||||||
|
return "column_name";
|
||||||
|
case column_serial:
|
||||||
|
return "column_serial";
|
||||||
|
case column_firmware:
|
||||||
|
return "column_firmware";
|
||||||
|
case column_version:
|
||||||
|
return "column_version";
|
||||||
|
case column_category:
|
||||||
|
return "column_category";
|
||||||
|
case column_path:
|
||||||
|
return "column_path";
|
||||||
|
case column_count:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::exception("get_game_list_column_name: Invalid column");
|
||||||
|
}
|
||||||
|
|
||||||
|
const QSize game_list_icon_size_min = QSize(40, 22);
|
||||||
|
const QSize game_list_icon_size_small = QSize(80, 44);
|
||||||
|
const QSize game_list_icon_size_medium = QSize(160, 88);
|
||||||
|
const QSize game_list_icon_size_max = QSize(320, 176);
|
||||||
|
|
||||||
|
const int game_list_max_slider_pos = 100;
|
||||||
|
|
||||||
|
inline int get_Index(const QSize& current)
|
||||||
|
{
|
||||||
|
const int size_delta = game_list_icon_size_max.width() - game_list_icon_size_min.width();
|
||||||
|
const int current_delta = current.width() - game_list_icon_size_min.width();
|
||||||
|
return game_list_max_slider_pos * current_delta / size_delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString main_window = "main_window";
|
||||||
|
const QString game_list = "GameList";
|
||||||
|
|
||||||
|
const QColor game_list_icon_color = QColor(240, 240, 240, 255);
|
||||||
|
|
||||||
|
const gui_save main_window_gamelist_visible = gui_save(main_window, "gamelistVisible", true);
|
||||||
|
const gui_save main_window_geometry = gui_save(main_window, "geometry", QByteArray());
|
||||||
|
const gui_save main_window_windowState = gui_save(main_window, "windowState", QByteArray());
|
||||||
|
const gui_save main_window_mwState = gui_save(main_window, "mwState", QByteArray());
|
||||||
|
|
||||||
|
const gui_save game_list_sortAsc = gui_save(game_list, "sortAsc", true);
|
||||||
|
const gui_save game_list_sortCol = gui_save(game_list, "sortCol", 1);
|
||||||
|
const gui_save game_list_state = gui_save(game_list, "state", QByteArray());
|
||||||
|
const gui_save game_list_iconSize = gui_save(game_list, "iconSize", get_Index(game_list_icon_size_small));
|
||||||
|
const gui_save game_list_iconSizeGrid = gui_save(game_list, "iconSizeGrid", get_Index(game_list_icon_size_small));
|
||||||
|
const gui_save game_list_iconColor = gui_save(game_list, "iconColor", game_list_icon_color);
|
||||||
|
const gui_save game_list_listMode = gui_save(game_list, "listMode", true);
|
||||||
|
const gui_save game_list_textFactor = gui_save(game_list, "textFactor", qreal{ 2.0 });
|
||||||
|
const gui_save game_list_marginFactor = gui_save(game_list, "marginFactor", qreal{ 0.09 });
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class gui_settings
|
class gui_settings : public settings
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit gui_settings(QObject* parent = nullptr);
|
explicit gui_settings(QObject* parent = nullptr);
|
||||||
|
|
||||||
private:
|
bool GetGamelistColVisibility(int col) const;
|
||||||
std::unique_ptr<QSettings> m_settings;
|
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void SetGamelistColVisibility(int col, bool val) const;
|
||||||
|
static gui_save GetGuiSaveForColumn(int col);
|
||||||
|
static QSize SizeFromSlider(int pos);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,232 @@
|
||||||
|
#include "game_list_frame.h"
|
||||||
|
#include "main_window.h"
|
||||||
|
#include "gui_settings.h"
|
||||||
|
#include "ui_main_window.h"
|
||||||
|
|
||||||
|
main_window::main_window(std::shared_ptr<gui_settings> gui_settings, QWidget* parent)
|
||||||
|
: QMainWindow(parent)
|
||||||
|
, ui(new Ui::main_window)
|
||||||
|
, m_gui_settings(std::move(gui_settings))
|
||||||
|
{
|
||||||
|
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
}
|
||||||
|
|
||||||
|
main_window::~main_window()
|
||||||
|
{
|
||||||
|
SaveWindowState();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool main_window::Init()
|
||||||
|
{
|
||||||
|
// add toolbar widgets
|
||||||
|
ui->toolBar->setObjectName("mw_toolbar");
|
||||||
|
ui->sizeSlider->setRange(0, gui::game_list_max_slider_pos);
|
||||||
|
ui->toolBar->addWidget(ui->sizeSliderContainer);
|
||||||
|
ui->toolBar->addWidget(ui->mw_searchbar);
|
||||||
|
|
||||||
|
CreateActions();
|
||||||
|
CreateDockWindows();
|
||||||
|
CreateConnects();
|
||||||
|
|
||||||
|
setMinimumSize(350, minimumSizeHint().height());
|
||||||
|
setWindowTitle(QString::fromStdString("ShadPS4 v0.0.2"));
|
||||||
|
|
||||||
|
ConfigureGuiFromSettings();
|
||||||
|
|
||||||
|
show();
|
||||||
|
|
||||||
|
// Fix possible hidden game list columns. The game list has to be visible already. Use this after show()
|
||||||
|
m_game_list_frame->FixNarrowColumns();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_window::CreateActions()
|
||||||
|
{
|
||||||
|
//create action group for icon size
|
||||||
|
m_icon_size_act_group = new QActionGroup(this);
|
||||||
|
m_icon_size_act_group->addAction(ui->setIconSizeTinyAct);
|
||||||
|
m_icon_size_act_group->addAction(ui->setIconSizeSmallAct);
|
||||||
|
m_icon_size_act_group->addAction(ui->setIconSizeMediumAct);
|
||||||
|
m_icon_size_act_group->addAction(ui->setIconSizeLargeAct);
|
||||||
|
|
||||||
|
//create action group for list mode
|
||||||
|
m_list_mode_act_group = new QActionGroup(this);
|
||||||
|
m_list_mode_act_group->addAction(ui->setlistModeListAct);
|
||||||
|
m_list_mode_act_group->addAction(ui->setlistModeGridAct);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_window::CreateDockWindows()
|
||||||
|
{
|
||||||
|
m_main_window = new QMainWindow();
|
||||||
|
m_main_window->setContextMenuPolicy(Qt::PreventContextMenu);
|
||||||
|
|
||||||
|
m_game_list_frame = new game_list_frame(m_gui_settings,m_main_window);
|
||||||
|
m_game_list_frame->setObjectName("gamelist");
|
||||||
|
|
||||||
|
m_main_window->addDockWidget(Qt::LeftDockWidgetArea, m_game_list_frame);
|
||||||
|
|
||||||
|
m_main_window->setDockNestingEnabled(true);
|
||||||
|
|
||||||
|
setCentralWidget(m_main_window);
|
||||||
|
|
||||||
|
connect(m_game_list_frame, &game_list_frame::GameListFrameClosed, this, [this]()
|
||||||
|
{
|
||||||
|
if (ui->showGameListAct->isChecked())
|
||||||
|
{
|
||||||
|
ui->showGameListAct->setChecked(false);
|
||||||
|
m_gui_settings->SetValue(gui::main_window_gamelist_visible, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
void main_window::CreateConnects()
|
||||||
|
{
|
||||||
|
connect(ui->exitAct, &QAction::triggered, this, &QWidget::close);
|
||||||
|
|
||||||
|
connect(ui->showGameListAct, &QAction::triggered, this, [this](bool checked)
|
||||||
|
{
|
||||||
|
checked ? m_game_list_frame->show() : m_game_list_frame->hide();
|
||||||
|
m_gui_settings->SetValue(gui::main_window_gamelist_visible, checked);
|
||||||
|
});
|
||||||
|
connect(ui->refreshGameListAct, &QAction::triggered, this, [this]
|
||||||
|
{
|
||||||
|
m_game_list_frame->Refresh(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_icon_size_act_group, &QActionGroup::triggered, this, [this](QAction* act)
|
||||||
|
{
|
||||||
|
static const int index_small = gui::get_Index(gui::game_list_icon_size_small);
|
||||||
|
static const int index_medium = gui::get_Index(gui::game_list_icon_size_medium);
|
||||||
|
|
||||||
|
int index;
|
||||||
|
|
||||||
|
if (act == ui->setIconSizeTinyAct)
|
||||||
|
index = 0;
|
||||||
|
else if (act == ui->setIconSizeSmallAct)
|
||||||
|
index = index_small;
|
||||||
|
else if (act == ui->setIconSizeMediumAct)
|
||||||
|
index = index_medium;
|
||||||
|
else
|
||||||
|
index = gui::game_list_max_slider_pos;
|
||||||
|
|
||||||
|
m_save_slider_pos = true;
|
||||||
|
ResizeIcons(index);
|
||||||
|
});
|
||||||
|
connect(m_game_list_frame, &game_list_frame::RequestIconSizeChange, this, [this](const int& val)
|
||||||
|
{
|
||||||
|
const int idx = ui->sizeSlider->value() + val;
|
||||||
|
m_save_slider_pos = true;
|
||||||
|
ResizeIcons(idx);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_list_mode_act_group, &QActionGroup::triggered, this, [this](QAction* act)
|
||||||
|
{
|
||||||
|
const bool is_list_act = act == ui->setlistModeListAct;
|
||||||
|
if (is_list_act == m_is_list_mode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const int slider_pos = ui->sizeSlider->sliderPosition();
|
||||||
|
ui->sizeSlider->setSliderPosition(m_other_slider_pos);
|
||||||
|
SetIconSizeActions(m_other_slider_pos);
|
||||||
|
m_other_slider_pos = slider_pos;
|
||||||
|
|
||||||
|
m_is_list_mode = is_list_act;
|
||||||
|
m_game_list_frame->SetListMode(m_is_list_mode);
|
||||||
|
});
|
||||||
|
connect(ui->sizeSlider, &QSlider::valueChanged, this, &main_window::ResizeIcons);
|
||||||
|
connect(ui->sizeSlider, &QSlider::sliderReleased, this, [this]
|
||||||
|
{
|
||||||
|
const int index = ui->sizeSlider->value();
|
||||||
|
m_gui_settings->SetValue(m_is_list_mode ? gui::game_list_iconSize : gui::game_list_iconSizeGrid, index);
|
||||||
|
SetIconSizeActions(index);
|
||||||
|
});
|
||||||
|
connect(ui->sizeSlider, &QSlider::actionTriggered, this, [this](int action)
|
||||||
|
{
|
||||||
|
if (action != QAbstractSlider::SliderNoAction && action != QAbstractSlider::SliderMove)
|
||||||
|
{ // we only want to save on mouseclicks or slider release (the other connect handles this)
|
||||||
|
m_save_slider_pos = true; // actionTriggered happens before the value was changed
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(ui->mw_searchbar, &QLineEdit::textChanged, m_game_list_frame, &game_list_frame::SetSearchText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_window::SetIconSizeActions(int idx) const
|
||||||
|
{
|
||||||
|
static const int threshold_tiny = gui::get_Index((gui::game_list_icon_size_small + gui::game_list_icon_size_min) / 2);
|
||||||
|
static const int threshold_small = gui::get_Index((gui::game_list_icon_size_medium + gui::game_list_icon_size_small) / 2);
|
||||||
|
static const int threshold_medium = gui::get_Index((gui::game_list_icon_size_max + gui::game_list_icon_size_medium) / 2);
|
||||||
|
|
||||||
|
if (idx < threshold_tiny)
|
||||||
|
ui->setIconSizeTinyAct->setChecked(true);
|
||||||
|
else if (idx < threshold_small)
|
||||||
|
ui->setIconSizeSmallAct->setChecked(true);
|
||||||
|
else if (idx < threshold_medium)
|
||||||
|
ui->setIconSizeMediumAct->setChecked(true);
|
||||||
|
else
|
||||||
|
ui->setIconSizeLargeAct->setChecked(true);
|
||||||
|
}
|
||||||
|
void main_window::ResizeIcons(int index)
|
||||||
|
{
|
||||||
|
if (ui->sizeSlider->value() != index)
|
||||||
|
{
|
||||||
|
ui->sizeSlider->setSliderPosition(index);
|
||||||
|
return; // ResizeIcons will be triggered again by setSliderPosition, so return here
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_save_slider_pos)
|
||||||
|
{
|
||||||
|
m_save_slider_pos = false;
|
||||||
|
m_gui_settings->SetValue(m_is_list_mode ? gui::game_list_iconSize : gui::game_list_iconSizeGrid, index);
|
||||||
|
|
||||||
|
// this will also fire when we used the actions, but i didn't want to add another boolean member
|
||||||
|
SetIconSizeActions(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_game_list_frame->ResizeIcons(index);
|
||||||
|
}
|
||||||
|
void main_window::ConfigureGuiFromSettings()
|
||||||
|
{
|
||||||
|
// Restore GUI state if needed. We need to if they exist.
|
||||||
|
if (!restoreGeometry(m_gui_settings->GetValue(gui::main_window_geometry).toByteArray()))
|
||||||
|
{
|
||||||
|
resize(QGuiApplication::primaryScreen()->availableSize() * 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
restoreState(m_gui_settings->GetValue(gui::main_window_windowState).toByteArray());
|
||||||
|
m_main_window->restoreState(m_gui_settings->GetValue(gui::main_window_mwState).toByteArray());
|
||||||
|
|
||||||
|
ui->showGameListAct->setChecked(m_gui_settings->GetValue(gui::main_window_gamelist_visible).toBool());
|
||||||
|
|
||||||
|
m_game_list_frame->setVisible(ui->showGameListAct->isChecked());
|
||||||
|
|
||||||
|
// handle icon size options
|
||||||
|
m_is_list_mode = m_gui_settings->GetValue(gui::game_list_listMode).toBool();
|
||||||
|
if (m_is_list_mode)
|
||||||
|
ui->setlistModeListAct->setChecked(true);
|
||||||
|
else
|
||||||
|
ui->setlistModeGridAct->setChecked(true);
|
||||||
|
|
||||||
|
const int icon_size_index = m_gui_settings->GetValue(m_is_list_mode ? gui::game_list_iconSize : gui::game_list_iconSizeGrid).toInt();
|
||||||
|
m_other_slider_pos = m_gui_settings->GetValue(!m_is_list_mode ? gui::game_list_iconSize : gui::game_list_iconSizeGrid).toInt();
|
||||||
|
ui->sizeSlider->setSliderPosition(icon_size_index);
|
||||||
|
SetIconSizeActions(icon_size_index);
|
||||||
|
|
||||||
|
// Gamelist
|
||||||
|
m_game_list_frame->LoadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_window::SaveWindowState() const
|
||||||
|
{
|
||||||
|
// Save gui settings
|
||||||
|
m_gui_settings->SetValue(gui::main_window_geometry, saveGeometry());
|
||||||
|
m_gui_settings->SetValue(gui::main_window_windowState, saveState());
|
||||||
|
m_gui_settings->SetValue(gui::main_window_mwState, m_main_window->saveState());
|
||||||
|
|
||||||
|
// Save column settings
|
||||||
|
m_game_list_frame->SaveSettings();
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QActionGroup>
|
||||||
|
|
||||||
|
class gui_settings;
|
||||||
|
class game_list_frame;
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class main_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
class main_window : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
std::unique_ptr<Ui::main_window> ui;
|
||||||
|
|
||||||
|
bool m_is_list_mode = true;
|
||||||
|
bool m_save_slider_pos = false;
|
||||||
|
int m_other_slider_pos = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit main_window(std::shared_ptr<gui_settings> gui_settings,QWidget* parent = nullptr);
|
||||||
|
~main_window();
|
||||||
|
bool Init();
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void ConfigureGuiFromSettings();
|
||||||
|
void SetIconSizeActions(int idx) const;
|
||||||
|
void ResizeIcons(int index);
|
||||||
|
void SaveWindowState() const;
|
||||||
|
private:
|
||||||
|
void CreateActions();
|
||||||
|
void CreateDockWindows();
|
||||||
|
void CreateConnects();
|
||||||
|
|
||||||
|
QActionGroup* m_icon_size_act_group = nullptr;
|
||||||
|
QActionGroup* m_list_mode_act_group = nullptr;
|
||||||
|
|
||||||
|
// Dockable widget frames
|
||||||
|
QMainWindow* m_main_window = nullptr;
|
||||||
|
game_list_frame* m_game_list_frame = nullptr;
|
||||||
|
|
||||||
|
std::shared_ptr<gui_settings> m_gui_settings;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,297 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>main_window</class>
|
||||||
|
<widget class="QMainWindow" name="main_window">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1058</width>
|
||||||
|
<height>580</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>4</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>RPCS3</string>
|
||||||
|
</property>
|
||||||
|
<property name="autoFillBackground">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="animated">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="dockNestingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="dockOptions">
|
||||||
|
<set>QMainWindow::AllowNestedDocks|QMainWindow::AllowTabbedDocks|QMainWindow::AnimatedDocks|QMainWindow::GroupedDragging</set>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralWidget">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<widget class="QLineEdit" name="mw_searchbar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>480</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>251</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frame">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Search...</string>
|
||||||
|
</property>
|
||||||
|
<property name="clearButtonEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="sizeSliderContainer" native="true">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>280</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>181</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="sizeSliderContainer_layout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>14</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>14</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="sizeSlider">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="autoFillBackground">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="tickPosition">
|
||||||
|
<enum>QSlider::NoTicks</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenuBar" name="menuBar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1058</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::PreventContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QMenu" name="menuFile">
|
||||||
|
<property name="title">
|
||||||
|
<string>File</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="bootInstallPkgAct"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="exitAct"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuView">
|
||||||
|
<property name="title">
|
||||||
|
<string>View</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QMenu" name="menuGame_List_Icons">
|
||||||
|
<property name="title">
|
||||||
|
<string>Game List Icons</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="setIconSizeTinyAct"/>
|
||||||
|
<addaction name="setIconSizeSmallAct"/>
|
||||||
|
<addaction name="setIconSizeMediumAct"/>
|
||||||
|
<addaction name="setIconSizeLargeAct"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuGame_List_Mode">
|
||||||
|
<property name="title">
|
||||||
|
<string>Game List Mode</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="setlistModeListAct"/>
|
||||||
|
<addaction name="setlistModeGridAct"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="showGameListAct"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="refreshGameListAct"/>
|
||||||
|
<addaction name="menuGame_List_Mode"/>
|
||||||
|
<addaction name="menuGame_List_Icons"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="menuFile"/>
|
||||||
|
<addaction name="menuView"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolBar" name="toolBar">
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>toolBar</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="toolBarArea">
|
||||||
|
<enum>TopToolBarArea</enum>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="toolBarBreak">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<action name="bootInstallPkgAct">
|
||||||
|
<property name="text">
|
||||||
|
<string>Install Packages (PKG)</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Install application from a .pkg file</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="bootInstallPupAct">
|
||||||
|
<property name="text">
|
||||||
|
<string>Install Firmware</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Install firmware from PS3UPDAT.PUP</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="exitAct">
|
||||||
|
<property name="text">
|
||||||
|
<string>Exit</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Exit RPCS3</string>
|
||||||
|
</property>
|
||||||
|
<property name="statusTip">
|
||||||
|
<string>Exit the application.</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="showGameListAct">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Show Game List</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="refreshGameListAct">
|
||||||
|
<property name="text">
|
||||||
|
<string>Game List Refresh</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="setIconSizeTinyAct">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Tiny</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="setIconSizeSmallAct">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Small</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="setIconSizeMediumAct">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Medium</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="setIconSizeLargeAct">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Large</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="setlistModeListAct">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>List View</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="setlistModeGridAct">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Grid View</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
|
<resources>
|
||||||
|
<include location="../../../rpcs3/rpcs3/resources.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QFutureWatcher>
|
||||||
|
|
||||||
|
namespace gui
|
||||||
|
{
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
void stop_future_watcher(QFutureWatcher<T>& watcher, bool cancel)
|
||||||
|
{
|
||||||
|
if (watcher.isStarted() || watcher.isRunning())
|
||||||
|
{
|
||||||
|
if (cancel)
|
||||||
|
{
|
||||||
|
watcher.cancel();
|
||||||
|
}
|
||||||
|
watcher.waitForFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // utils
|
||||||
|
} // gui
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
|
settings::settings(QObject* parent) : QObject(parent),
|
||||||
|
m_settings_dir(ComputeSettingsDir())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
settings::~settings()
|
||||||
|
{
|
||||||
|
if (m_settings)
|
||||||
|
{
|
||||||
|
m_settings->sync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString settings::GetSettingsDir() const
|
||||||
|
{
|
||||||
|
return m_settings_dir.absolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString settings::ComputeSettingsDir()
|
||||||
|
{
|
||||||
|
return ""; //TODO currently we configure same dir , make it configurable
|
||||||
|
}
|
||||||
|
|
||||||
|
void settings::RemoveValue(const QString& key, const QString& name) const
|
||||||
|
{
|
||||||
|
if (m_settings)
|
||||||
|
{
|
||||||
|
m_settings->beginGroup(key);
|
||||||
|
m_settings->remove(name);
|
||||||
|
m_settings->endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void settings::RemoveValue(const gui_save& entry) const
|
||||||
|
{
|
||||||
|
RemoveValue(entry.key, entry.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant settings::GetValue(const QString& key, const QString& name, const QVariant& def) const
|
||||||
|
{
|
||||||
|
return m_settings ? m_settings->value(key + "/" + name, def) : def;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant settings::GetValue(const gui_save& entry) const
|
||||||
|
{
|
||||||
|
return GetValue(entry.key, entry.name, entry.def);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant settings::List2Var(const q_pair_list& list)
|
||||||
|
{
|
||||||
|
QByteArray ba;
|
||||||
|
QDataStream stream(&ba, QIODevice::WriteOnly);
|
||||||
|
stream << list;
|
||||||
|
return QVariant(ba);
|
||||||
|
}
|
||||||
|
|
||||||
|
q_pair_list settings::Var2List(const QVariant& var)
|
||||||
|
{
|
||||||
|
q_pair_list list;
|
||||||
|
QByteArray ba = var.toByteArray();
|
||||||
|
QDataStream stream(&ba, QIODevice::ReadOnly);
|
||||||
|
stream >> list;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void settings::SetValue(const gui_save& entry, const QVariant& value) const
|
||||||
|
{
|
||||||
|
if (m_settings)
|
||||||
|
{
|
||||||
|
m_settings->beginGroup(entry.key);
|
||||||
|
m_settings->setValue(entry.name, value);
|
||||||
|
m_settings->endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void settings::SetValue(const QString& key, const QVariant& value) const
|
||||||
|
{
|
||||||
|
if (m_settings)
|
||||||
|
{
|
||||||
|
m_settings->setValue(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void settings::SetValue(const QString& key, const QString& name, const QVariant& value) const
|
||||||
|
{
|
||||||
|
if (m_settings)
|
||||||
|
{
|
||||||
|
m_settings->beginGroup(key);
|
||||||
|
m_settings->setValue(name, value);
|
||||||
|
m_settings->endGroup();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QSize>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gui_save.h"
|
||||||
|
|
||||||
|
typedef QPair<QString, QString> q_string_pair;
|
||||||
|
typedef QPair<QString, QSize> q_size_pair;
|
||||||
|
typedef QList<q_string_pair> q_pair_list;
|
||||||
|
typedef QList<q_size_pair> q_size_list;
|
||||||
|
|
||||||
|
// Parent Class for GUI settings
|
||||||
|
class settings : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit settings(QObject* parent = nullptr);
|
||||||
|
~settings();
|
||||||
|
|
||||||
|
QString GetSettingsDir() const;
|
||||||
|
|
||||||
|
QVariant GetValue(const QString& key, const QString& name, const QVariant& def) const;
|
||||||
|
QVariant GetValue(const gui_save& entry) const;
|
||||||
|
static QVariant List2Var(const q_pair_list& list);
|
||||||
|
static q_pair_list Var2List(const QVariant& var);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
/** Remove entry */
|
||||||
|
void RemoveValue(const QString& key, const QString& name) const;
|
||||||
|
void RemoveValue(const gui_save& entry) const;
|
||||||
|
|
||||||
|
/** Write value to entry */
|
||||||
|
void SetValue(const gui_save& entry, const QVariant& value) const;
|
||||||
|
void SetValue(const QString& key, const QVariant& value) const;
|
||||||
|
void SetValue(const QString& key, const QString& name, const QVariant& value) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static QString ComputeSettingsDir();
|
||||||
|
|
||||||
|
std::unique_ptr<QSettings> m_settings;
|
||||||
|
QDir m_settings_dir;
|
||||||
|
};
|
|
@ -12,11 +12,15 @@ shadps4gui::shadps4gui(std::shared_ptr<gui_settings> gui_settings, QWidget* pare
|
||||||
, m_gui_settings(std::move(gui_settings))
|
, m_gui_settings(std::move(gui_settings))
|
||||||
{
|
{
|
||||||
ui.setupUi(this);
|
ui.setupUi(this);
|
||||||
game_list = new GameListViewer();
|
//game_list = new GameListViewer();
|
||||||
game_list->SetGamePath(QDir::currentPath() + "/game/");
|
//game_list->SetGamePath(QDir::currentPath() + "/game/");
|
||||||
ui.horizontalLayout->addWidget(game_list);
|
//ui.horizontalLayout->addWidget(game_list);
|
||||||
|
//show();
|
||||||
|
//game_list->PopulateAsync();
|
||||||
|
game_list_frame* game_list2 = new game_list_frame(m_gui_settings);
|
||||||
|
ui.horizontalLayout->addWidget(game_list2);
|
||||||
|
game_list2->LoadSettings();
|
||||||
show();
|
show();
|
||||||
game_list->PopulateAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shadps4gui::~shadps4gui()
|
shadps4gui::~shadps4gui()
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "ui_shadps4gui.h"
|
#include "ui_shadps4gui.h"
|
||||||
#include "GameListViewer.h"
|
#include "GameListViewer.h"
|
||||||
#include "gui_settings.h"
|
#include "gui_settings.h"
|
||||||
|
#include "game_list_frame.h"
|
||||||
|
|
||||||
class shadps4gui : public QMainWindow
|
class shadps4gui : public QMainWindow
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
#include "gui/shadps4gui.h"
|
#include "gui/shadps4gui.h"
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
#include "gui/gui_settings.h"
|
#include "gui/gui_settings.h"
|
||||||
|
#include "gui/main_window.h"
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
std::shared_ptr<gui_settings> m_gui_settings;
|
std::shared_ptr<gui_settings> m_gui_settings;
|
||||||
m_gui_settings.reset(new gui_settings());
|
m_gui_settings.reset(new gui_settings());
|
||||||
shadps4gui w(m_gui_settings,nullptr);
|
main_window* m_main_window = new main_window(m_gui_settings, nullptr);
|
||||||
w.show();
|
m_main_window->Init();
|
||||||
|
|
||||||
return a.exec();
|
return a.exec();
|
||||||
}
|
}
|
|
@ -22,6 +22,8 @@
|
||||||
<ClCompile Include="gui\game_list_grid_delegate.cpp" />
|
<ClCompile Include="gui\game_list_grid_delegate.cpp" />
|
||||||
<ClCompile Include="gui\game_list_table.cpp" />
|
<ClCompile Include="gui\game_list_table.cpp" />
|
||||||
<ClCompile Include="gui\gui_settings.cpp" />
|
<ClCompile Include="gui\gui_settings.cpp" />
|
||||||
|
<ClCompile Include="gui\main_window.cpp" />
|
||||||
|
<ClCompile Include="gui\settings.cpp" />
|
||||||
<ClCompile Include="gui\shadps4gui.cpp" />
|
<ClCompile Include="gui\shadps4gui.cpp" />
|
||||||
<ClCompile Include="main.cpp" />
|
<ClCompile Include="main.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -29,6 +31,7 @@
|
||||||
<QtMoc Include="gui\shadps4gui.h" />
|
<QtMoc Include="gui\shadps4gui.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<QtUic Include="gui\main_window.ui" />
|
||||||
<QtUic Include="gui\shadps4gui.ui" />
|
<QtUic Include="gui\shadps4gui.ui" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -40,12 +43,18 @@
|
||||||
<ClInclude Include="emulator\fileFormat\PSF.h" />
|
<ClInclude Include="emulator\fileFormat\PSF.h" />
|
||||||
<ClInclude Include="emulator\gameInfo.h" />
|
<ClInclude Include="emulator\gameInfo.h" />
|
||||||
<ClInclude Include="emulator\Loader.h" />
|
<ClInclude Include="emulator\Loader.h" />
|
||||||
|
<ClInclude Include="gui\custom_dock_widget.h" />
|
||||||
<ClInclude Include="gui\custom_table_widget_item.h" />
|
<ClInclude Include="gui\custom_table_widget_item.h" />
|
||||||
<QtMoc Include="gui\game_list_grid.h" />
|
<QtMoc Include="gui\game_list_grid.h" />
|
||||||
<ClInclude Include="gui\game_list_frame.h" />
|
<QtMoc Include="gui\game_list_frame.h" />
|
||||||
<ClInclude Include="gui\game_list_grid_delegate.h" />
|
<ClInclude Include="gui\game_list_grid_delegate.h" />
|
||||||
|
<ClInclude Include="gui\game_list_item.h" />
|
||||||
<ClInclude Include="gui\game_list_table.h" />
|
<ClInclude Include="gui\game_list_table.h" />
|
||||||
<ClInclude Include="gui\gui_settings.h" />
|
<ClInclude Include="gui\gui_save.h" />
|
||||||
|
<QtMoc Include="gui\gui_settings.h" />
|
||||||
|
<QtMoc Include="gui\settings.h" />
|
||||||
|
<QtMoc Include="gui\main_window.h" />
|
||||||
|
<ClInclude Include="gui\qt_utils.h" />
|
||||||
<ClInclude Include="Types.h" />
|
<ClInclude Include="Types.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
|
@ -70,12 +79,12 @@
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
|
||||||
<QtInstall>6.4.2</QtInstall>
|
<QtInstall>6.4.2</QtInstall>
|
||||||
<QtModules>core;gui;widgets</QtModules>
|
<QtModules>core;gui;widgets;concurrent</QtModules>
|
||||||
<QtBuildConfig>debug</QtBuildConfig>
|
<QtBuildConfig>debug</QtBuildConfig>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
|
||||||
<QtInstall>6.4.2</QtInstall>
|
<QtInstall>6.4.2</QtInstall>
|
||||||
<QtModules>core;gui;widgets</QtModules>
|
<QtModules>core;gui;widgets;concurrent</QtModules>
|
||||||
<QtBuildConfig>release</QtBuildConfig>
|
<QtBuildConfig>release</QtBuildConfig>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')">
|
<Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')">
|
||||||
|
|
|
@ -33,6 +33,12 @@
|
||||||
<Filter Include="emulator\fileFormat">
|
<Filter Include="emulator\fileFormat">
|
||||||
<UniqueIdentifier>{ed31734c-f010-4590-9f01-18e0b2497ffb}</UniqueIdentifier>
|
<UniqueIdentifier>{ed31734c-f010-4590-9f01-18e0b2497ffb}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="gui\game list">
|
||||||
|
<UniqueIdentifier>{b4b58418-b124-41bb-96ef-610faa1c8812}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="gui\main window">
|
||||||
|
<UniqueIdentifier>{731089fd-7d11-4f10-8f55-4854c2e42e9e}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="main.cpp">
|
<ClCompile Include="main.cpp">
|
||||||
|
@ -59,26 +65,35 @@
|
||||||
<ClCompile Include="gui\gui_settings.cpp">
|
<ClCompile Include="gui\gui_settings.cpp">
|
||||||
<Filter>gui</Filter>
|
<Filter>gui</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="gui\custom_table_widget_item.cpp">
|
<ClCompile Include="gui\settings.cpp">
|
||||||
<Filter>gui</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="gui\game_list_table.cpp">
|
|
||||||
<Filter>gui</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="gui\game_list_grid_delegate.cpp">
|
|
||||||
<Filter>gui</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="gui\game_list_grid.cpp">
|
|
||||||
<Filter>gui</Filter>
|
<Filter>gui</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="gui\game_list_frame.cpp">
|
<ClCompile Include="gui\game_list_frame.cpp">
|
||||||
<Filter>gui</Filter>
|
<Filter>gui\game list</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="gui\game_list_grid.cpp">
|
||||||
|
<Filter>gui\game list</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="gui\game_list_grid_delegate.cpp">
|
||||||
|
<Filter>gui\game list</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="gui\game_list_table.cpp">
|
||||||
|
<Filter>gui\game list</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="gui\custom_table_widget_item.cpp">
|
||||||
|
<Filter>gui\game list</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="gui\main_window.cpp">
|
||||||
|
<Filter>gui\main window</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtUic Include="gui\shadps4gui.ui">
|
<QtUic Include="gui\shadps4gui.ui">
|
||||||
<Filter>Form Files</Filter>
|
<Filter>Form Files</Filter>
|
||||||
</QtUic>
|
</QtUic>
|
||||||
|
<QtUic Include="gui\main_window.ui">
|
||||||
|
<Filter>gui\main window</Filter>
|
||||||
|
</QtUic>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtMoc Include="gui\shadps4gui.h">
|
<QtMoc Include="gui\shadps4gui.h">
|
||||||
|
@ -87,9 +102,21 @@
|
||||||
<QtMoc Include="gui\GameListViewer.h">
|
<QtMoc Include="gui\GameListViewer.h">
|
||||||
<Filter>gui</Filter>
|
<Filter>gui</Filter>
|
||||||
</QtMoc>
|
</QtMoc>
|
||||||
<QtMoc Include="gui\game_list_grid.h">
|
<QtMoc Include="gui\settings.h">
|
||||||
<Filter>gui</Filter>
|
<Filter>gui</Filter>
|
||||||
</QtMoc>
|
</QtMoc>
|
||||||
|
<QtMoc Include="gui\gui_settings.h">
|
||||||
|
<Filter>gui</Filter>
|
||||||
|
</QtMoc>
|
||||||
|
<QtMoc Include="gui\game_list_frame.h">
|
||||||
|
<Filter>gui\game list</Filter>
|
||||||
|
</QtMoc>
|
||||||
|
<QtMoc Include="gui\game_list_grid.h">
|
||||||
|
<Filter>gui\game list</Filter>
|
||||||
|
</QtMoc>
|
||||||
|
<QtMoc Include="gui\main_window.h">
|
||||||
|
<Filter>gui\main window</Filter>
|
||||||
|
</QtMoc>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Types.h">
|
<ClInclude Include="Types.h">
|
||||||
|
@ -107,23 +134,29 @@
|
||||||
<ClInclude Include="emulator\fileFormat\PKG.h">
|
<ClInclude Include="emulator\fileFormat\PKG.h">
|
||||||
<Filter>emulator\fileFormat</Filter>
|
<Filter>emulator\fileFormat</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="gui\gui_settings.h">
|
|
||||||
<Filter>gui</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="emulator\gameInfo.h">
|
<ClInclude Include="emulator\gameInfo.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="gui\custom_table_widget_item.h">
|
<ClInclude Include="gui\gui_save.h">
|
||||||
|
<Filter>gui</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="gui\game_list_item.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="gui\qt_utils.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="gui\custom_dock_widget.h">
|
||||||
<Filter>gui</Filter>
|
<Filter>gui</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="gui\game_list_table.h">
|
<ClInclude Include="gui\game_list_table.h">
|
||||||
<Filter>gui</Filter>
|
<Filter>gui\game list</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="gui\game_list_grid_delegate.h">
|
<ClInclude Include="gui\game_list_grid_delegate.h">
|
||||||
<Filter>gui</Filter>
|
<Filter>gui\game list</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="gui\game_list_frame.h">
|
<ClInclude Include="gui\custom_table_widget_item.h">
|
||||||
<Filter>gui</Filter>
|
<Filter>gui\game list</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue