Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Save Manager #2951

Merged
merged 19 commits into from Jul 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 22 additions & 21 deletions rpcs3/Emu/Cell/Modules/cellSaveData.cpp
Expand Up @@ -141,11 +141,16 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
save_entry2.atime = entry.atime;
save_entry2.mtime = entry.mtime;
save_entry2.ctime = entry.ctime;
//save_entry2.iconBuf = NULL; // TODO: Here should be the PNG buffer
//save_entry2.iconBufSize = 0; // TODO: Size of the PNG file
if (fs::is_file(base_dir + entry.name + "/ICON0.PNG"))
{
fs::file icon = fs::file(base_dir + entry.name + "/ICON0.PNG");
u32 iconSize = icon.size();
std::vector<uchar> iconData;
icon.read(iconData, iconSize);
save_entry2.iconBuf = iconData;
}
save_entry2.isNew = false;

save_entries.push_back(save_entry2);
save_entries.emplace_back(save_entry2);
}

break;
Expand Down Expand Up @@ -210,6 +215,13 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
return CELL_SAVEDATA_ERROR_CBRESULT;
}

// if the callback has returned ok, lets return OK.
// typically used at game launch when no list is actually required.
if ((result->result == CELL_SAVEDATA_CBRESULT_OK_LAST) || (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM))
{
return CELL_OK;
}

// Clean save data list
save_entries.erase(std::remove_if(save_entries.begin(), save_entries.end(), [&listSet](const SaveDataEntry& entry) -> bool
{
Expand Down Expand Up @@ -293,10 +305,9 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
}
}

// Display Save Data List but do so asynchronously in the GUI thread. For, qTimers only work using main UI thread.
// Display Save Data List but do so asynchronously in the GUI thread.
bool hasNewData = (bool)listSet->newData; // newData
atomic_t<bool> dlg_result(false);
bool hasNewData = (bool) listSet->newData; // Are we saving?


Emu.CallAfter([&]()
{
Expand All @@ -309,28 +320,18 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
thread_ctrl::wait_for(1000);
}

// UI returns -1 for new save games
if (selected == -1)
{
if (hasNewData)
{
save_entry.dirName = listSet->newData->dirName.get_ptr();
}
else
{
// This happens if someone tries to load but there is no data selected. Some games will throw errors (Akiba) if cell_ok is returned
return CELL_CANCEL;
}
save_entry.dirName = listSet->newData->dirName.get_ptr();
}

// Cancel selected in UI
else if (selected == -2)
if (selected == -2)
{
return CELL_CANCEL;
}

if ((result->result == CELL_SAVEDATA_CBRESULT_OK_LAST) || (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM))
{
return CELL_OK;
}
}

if (funcFixed)
Expand Down
3 changes: 1 addition & 2 deletions rpcs3/Emu/Cell/Modules/cellSaveData.h
Expand Up @@ -282,8 +282,7 @@ struct SaveDataEntry
s64 atime;
s64 mtime;
s64 ctime;
//void* iconBuf;
//u32 iconBufSize;
std::vector<uchar> iconBuf;
bool isNew;
};

Expand Down
73 changes: 51 additions & 22 deletions rpcs3/rpcs3qt/save_data_utility.cpp
@@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "save_data_utility.h"

inline QString qstr(const std::string& _in) { return QString::fromUtf8(_in.data(), _in.size()); }
Expand All @@ -9,10 +9,10 @@ save_data_info_dialog::save_data_info_dialog(const SaveDataEntry& save, QWidget*
: QDialog(parent), m_entry(save)
{
setWindowTitle(tr("Save Data Information"));
setMinimumSize(QSize(400, 300));

// Table
m_list = new QTableWidget(this);

//m_list->setItemDelegate(new table_item_delegate(this)); // to get rid of item selection rectangles include "table_item_delegate.h"
m_list->setSelectionBehavior(QAbstractItemView::SelectRows); // enable to only select whole rows instead of items
m_list->setEditTriggers(QAbstractItemView::NoEditTriggers);
Expand All @@ -35,17 +35,26 @@ save_data_info_dialog::save_data_info_dialog(const SaveDataEntry& save, QWidget*
vbox_main->setAlignment(Qt::AlignCenter);
setLayout(vbox_main);

// resize to minimum view size
resize(minimumSize().expandedTo(sizeHint()));

UpdateData();

m_list->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents);
m_list->verticalHeader()->resizeSections(QHeaderView::ResizeToContents);

QSize tableSize = QSize(
m_list->verticalHeader()->width() + m_list->horizontalHeader()->length() + m_list->frameWidth() * 2,
m_list->horizontalHeader()->height() + m_list->verticalHeader()->length() + m_list->frameWidth() * 2);

// no minimum size needed because we always have same table size and row count
resize(sizeHint() - m_list->sizeHint() + tableSize);

}

//This is intended to write the information of save data to QTableView.
void save_data_info_dialog::UpdateData()
{
m_list->clearContents();
m_list->setRowCount(4); // set this to nr of members in struct
int num_entries = 4; // set this to number of members in struct
m_list->setRowCount(num_entries);

//Maybe there should be more details of save data.
m_list->setItem(0, 0, new QTableWidgetItem(tr("User ID")));
Expand All @@ -60,20 +69,28 @@ void save_data_info_dialog::UpdateData()
m_list->setItem(3, 0, new QTableWidgetItem(tr("Detail")));
m_list->setItem(3, 1, new QTableWidgetItem(qstr(m_entry.details)));

m_list->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
m_list->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
QImage img;
if (m_entry.iconBuf.size() > 0 && img.loadFromData((uchar*) &m_entry.iconBuf[0], m_entry.iconBuf.size(), "PNG"))
{
m_list->insertRow(0);
QTableWidgetItem* img_item = new QTableWidgetItem();
img_item->setData(Qt::DecorationRole, QPixmap::fromImage(img));
m_list->setItem(0, 0, new QTableWidgetItem(tr("Icon")));
m_list->setItem(0, 1, img_item);
}
}

//Show up the savedata list, either to choose one to save/load or to manage saves.
//I suggest to use function callbacks to give save data list or get save data entry. (Not implemented or stubbed)
save_data_list_dialog::save_data_list_dialog(const std::vector<SaveDataEntry>& entries, s32 focusedEntry, bool is_saving, QWidget* parent)
: QDialog(parent), m_save_entries(entries), m_selectedEntry(-1), selectedEntryLabel(nullptr)
{
setWindowTitle(tr("Save Data Utility"));
setWindowTitle(tr("Save Data Interface"));
setMinimumSize(QSize(400, 400));

// Table
m_list = new QTableWidget(this);

//m_list->setItemDelegate(new table_item_delegate(this)); // to get rid of cell selection rectangles include "table_item_delegate.h"
m_list->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
m_list->setSelectionBehavior(QAbstractItemView::SelectRows);
Expand All @@ -84,18 +101,18 @@ save_data_list_dialog::save_data_list_dialog(const std::vector<SaveDataEntry>& e

// Button Layout
QHBoxLayout* hbox_action = new QHBoxLayout();
QPushButton *push_cancel = new QPushButton(tr("&Cancel"), this);
push_cancel->setAutoDefault(false);
QPushButton *push_select = new QPushButton(tr("&Select Entry"), this);
push_select->setAutoDefault(true);
push_select->setDefault(true);

connect(push_select, &QAbstractButton::clicked, this, &save_data_list_dialog::accept);
hbox_action->addWidget(push_select);
setWindowTitle(tr("Save Data Chooser"));
if (entries.size() > 0)
{ // If there are no entries, don't add the selection widget or the selection label to the UI.
QPushButton *push_select = new QPushButton(tr("&Select Entry"), this);
connect(push_select, &QAbstractButton::clicked, this, &save_data_list_dialog::accept);
push_select->setAutoDefault(true);
push_select->setDefault(true);
hbox_action->addWidget(push_select);

selectedEntryLabel = new QLabel(this);
UpdateSelectionLabel();
selectedEntryLabel = new QLabel(this);
UpdateSelectionLabel();
}

if (is_saving)
{
Expand All @@ -108,6 +125,9 @@ save_data_list_dialog::save_data_list_dialog(const std::vector<SaveDataEntry>& e
}

hbox_action->addStretch();

QPushButton *push_cancel = new QPushButton(tr("&Cancel"), this);
push_cancel->setAutoDefault(false);
hbox_action->addWidget(push_cancel);

// events
Expand All @@ -120,7 +140,7 @@ save_data_list_dialog::save_data_list_dialog(const std::vector<SaveDataEntry>& e

// TODO: Unstub functions inside of this context menu so it makes sense to show this menu
//connect(m_list, &QTableWidget::customContextMenuRequested, this, &save_data_list_dialog::ShowContextMenu);
connect(m_list->horizontalHeader(), &QHeaderView::sectionClicked, [=](int col){
connect(m_list->horizontalHeader(), &QHeaderView::sectionClicked, [=](int col) {
OnSort(col);
});

Expand All @@ -141,6 +161,7 @@ save_data_list_dialog::save_data_list_dialog(const std::vector<SaveDataEntry>& e
m_list->setCurrentCell(focusedEntry, 0);
}


void save_data_list_dialog::UpdateSelectionLabel()
{
if (selectedEntryLabel != nullptr)
Expand Down Expand Up @@ -279,8 +300,6 @@ void save_data_list_dialog::UpdateList(void)
{
m_list->clearContents();
m_list->setRowCount(m_save_entries.size());
m_list->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
m_list->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);

int row = 0;
for (SaveDataEntry entry: m_save_entries)
Expand All @@ -293,4 +312,14 @@ void save_data_list_dialog::UpdateList(void)

++row;
}

m_list->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents);
m_list->verticalHeader()->resizeSections(QHeaderView::ResizeToContents);

QSize tableSize = QSize(
m_list->verticalHeader()->width() + m_list->horizontalHeader()->length() + m_list->frameWidth() * 2,
m_list->horizontalHeader()->height() + m_list->verticalHeader()->length() + m_list->frameWidth() * 2);

resize(minimumSize().expandedTo(sizeHint() - m_list->sizeHint() + tableSize));

}