Qt: Add memory card settings
|
@ -55,6 +55,9 @@ target_sources(pcsx2-qt PRIVATE
|
|||
Settings/ControllerSettingsDialog.cpp
|
||||
Settings/ControllerSettingsDialog.h
|
||||
Settings/ControllerSettingsDialog.ui
|
||||
Settings/CreateMemoryCardDialog.cpp
|
||||
Settings/CreateMemoryCardDialog.h
|
||||
Settings/CreateMemoryCardDialog.ui
|
||||
Settings/EmulationSettingsWidget.cpp
|
||||
Settings/EmulationSettingsWidget.h
|
||||
Settings/EmulationSettingsWidget.ui
|
||||
|
|
|
@ -145,7 +145,7 @@ void MainWindow::connectSignals()
|
|||
connect(m_ui.actionSystemSettings, &QAction::triggered, [this]() { doSettings("System"); });
|
||||
connect(m_ui.actionGraphicsSettings, &QAction::triggered, [this]() { doSettings("Graphics"); });
|
||||
connect(m_ui.actionAudioSettings, &QAction::triggered, [this]() { doSettings("Audio"); });
|
||||
connect(m_ui.actionMemoryCardSettings, &QAction::triggered, [this]() { doSettings("Memory Card"); });
|
||||
connect(m_ui.actionMemoryCardSettings, &QAction::triggered, [this]() { doSettings("Memory Cards"); });
|
||||
connect(
|
||||
m_ui.actionControllerSettings, &QAction::triggered, [this]() { doControllerSettings(ControllerSettingsDialog::Category::GlobalSettings); });
|
||||
connect(m_ui.actionHotkeySettings, &QAction::triggered, [this]() { doControllerSettings(ControllerSettingsDialog::Category::HotkeySettings); });
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
#include "Settings/CreateMemoryCardDialog.h"
|
||||
|
||||
#include "pcsx2/MemoryCardFile.h"
|
||||
#include "pcsx2/System.h"
|
||||
|
||||
CreateMemoryCardDialog::CreateMemoryCardDialog(QWidget* parent /* = nullptr */)
|
||||
: QDialog(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
connect(m_ui.name, &QLineEdit::textChanged, this, &CreateMemoryCardDialog::nameTextChanged);
|
||||
|
||||
connect(m_ui.size8MB, &QRadioButton::clicked, this, [this]() { setType(MemoryCardType::File, MemoryCardFileType::PS2_8MB); });
|
||||
connect(m_ui.size16MB, &QRadioButton::clicked, this, [this]() { setType(MemoryCardType::File, MemoryCardFileType::PS2_16MB); });
|
||||
connect(m_ui.size32MB, &QRadioButton::clicked, this, [this]() { setType(MemoryCardType::File, MemoryCardFileType::PS2_32MB); });
|
||||
connect(m_ui.size64MB, &QRadioButton::clicked, this, [this]() { setType(MemoryCardType::File, MemoryCardFileType::PS2_64MB); });
|
||||
connect(m_ui.size128KB, &QRadioButton::clicked, this, [this]() { setType(MemoryCardType::File, MemoryCardFileType::PS1); });
|
||||
connect(m_ui.sizeFolder, &QRadioButton::clicked, this, [this]() { setType(MemoryCardType::Folder, MemoryCardFileType::Unknown); });
|
||||
|
||||
disconnect(m_ui.buttonBox, &QDialogButtonBox::accepted, this, nullptr);
|
||||
|
||||
connect(m_ui.buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &CreateMemoryCardDialog::createCard);
|
||||
connect(m_ui.buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &CreateMemoryCardDialog::close);
|
||||
connect(m_ui.buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, this, &CreateMemoryCardDialog::restoreDefaults);
|
||||
|
||||
updateState();
|
||||
}
|
||||
|
||||
CreateMemoryCardDialog::~CreateMemoryCardDialog() = default;
|
||||
|
||||
void CreateMemoryCardDialog::nameTextChanged()
|
||||
{
|
||||
const QString controlName(m_ui.name->text());
|
||||
const int cursorPos = m_ui.name->cursorPosition();
|
||||
|
||||
QString nameWithoutExtension;
|
||||
if (controlName.endsWith(QStringLiteral(".ps2")))
|
||||
nameWithoutExtension = controlName.left(controlName.size() - 4);
|
||||
else
|
||||
nameWithoutExtension = controlName;
|
||||
|
||||
QSignalBlocker sb(m_ui.name);
|
||||
if (nameWithoutExtension.isEmpty())
|
||||
m_ui.name->setText(QString());
|
||||
else
|
||||
m_ui.name->setText(nameWithoutExtension + QStringLiteral(".ps2"));
|
||||
|
||||
m_ui.name->setCursorPosition(cursorPos);
|
||||
updateState();
|
||||
}
|
||||
|
||||
void CreateMemoryCardDialog::setType(MemoryCardType type, MemoryCardFileType fileType)
|
||||
{
|
||||
m_type = type;
|
||||
m_fileType = fileType;
|
||||
updateState();
|
||||
}
|
||||
|
||||
void CreateMemoryCardDialog::restoreDefaults()
|
||||
{
|
||||
setType(MemoryCardType::File, MemoryCardFileType::PS2_8MB);
|
||||
m_ui.size8MB->setChecked(true);
|
||||
m_ui.size16MB->setChecked(false);
|
||||
m_ui.size32MB->setChecked(false);
|
||||
m_ui.size64MB->setChecked(false);
|
||||
m_ui.size128KB->setChecked(false);
|
||||
m_ui.sizeFolder->setChecked(false);
|
||||
}
|
||||
|
||||
void CreateMemoryCardDialog::updateState()
|
||||
{
|
||||
const bool okay = (m_ui.name->text().length() > 4);
|
||||
|
||||
m_ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(okay);
|
||||
m_ui.ntfsCompression->setEnabled(m_type == MemoryCardType::File);
|
||||
}
|
||||
|
||||
void CreateMemoryCardDialog::createCard()
|
||||
{
|
||||
const QString name(m_ui.name->text());
|
||||
const std::string nameStr(name.toStdString());
|
||||
if (FileMcd_GetCardInfo(nameStr).has_value())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Create Memory Card"),
|
||||
tr("Failed to create the memory card, because another card with the name '%1' already exists.").arg(name));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FileMcd_CreateNewCard(nameStr, m_type, m_fileType))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Create Memory Card"),
|
||||
tr("Failed to create the memory card, the log may contain more information."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ui.ntfsCompression->isChecked() && m_type == MemoryCardType::File)
|
||||
{
|
||||
const std::string fullPath(Path::CombineStdString(EmuFolders::MemoryCards, nameStr));
|
||||
NTFS_CompressFile(StringUtil::UTF8StringToWxString(fullPath), true);
|
||||
}
|
||||
|
||||
QMessageBox::information(this, tr("Create Memory Card"), tr("Memory card '%1' created.").arg(name));
|
||||
accept();
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets/QDialog>
|
||||
|
||||
#include "ui_CreateMemoryCardDialog.h"
|
||||
|
||||
#include "pcsx2/Config.h"
|
||||
|
||||
class CreateMemoryCardDialog final : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CreateMemoryCardDialog(QWidget* parent = nullptr);
|
||||
~CreateMemoryCardDialog();
|
||||
|
||||
private Q_SLOTS:
|
||||
void nameTextChanged();
|
||||
void createCard();
|
||||
|
||||
private:
|
||||
void setType(MemoryCardType type, MemoryCardFileType fileType);
|
||||
void restoreDefaults();
|
||||
void updateState();
|
||||
|
||||
Ui::CreateMemoryCardDialog m_ui;
|
||||
|
||||
MemoryCardType m_type = MemoryCardType::File;
|
||||
MemoryCardFileType m_fileType = MemoryCardFileType::PS2_8MB;
|
||||
};
|
|
@ -0,0 +1,312 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CreateMemoryCardDialog</class>
|
||||
<widget class="QDialog" name="CreateMemoryCardDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>593</width>
|
||||
<height>545</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Create Memory Card</string>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="bottomMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../resources/resources.qrc">:/icons/black/48/sd-card-line.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-weight:700;">Create Memory Card</span><br />Enter the name of the memory card you wish to create, and choose a size. We recommend either using 8MB memory cards, or folder memory cards for best compatibility.</p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Memory Card Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="name"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="size8MB">
|
||||
<property name="text">
|
||||
<string>8 MB [Most Compatible]</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>This is the standard Sony-provisioned size, and is supported by all games and BIOS versions.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="size16MB">
|
||||
<property name="text">
|
||||
<string>16 MB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>A typical size for third-party memory cards which should work with most games.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="size32MB">
|
||||
<property name="text">
|
||||
<string>32 MB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>A typical size for third-party memory cards which should work with most games.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="size64MB">
|
||||
<property name="text">
|
||||
<string>64 MB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Low compatiblity warning: yes, it's very big, but may not work with many games.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="sizeFolder">
|
||||
<property name="text">
|
||||
<string>Folder [Recommended]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Store memory card contents in the host filesystem instead of a file.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="size128KB">
|
||||
<property name="text">
|
||||
<string>128 KB (PS1)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>This is the standard Sony-provisioned size PS1 memory card, and only compatible with PS1 games.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ntfsCompression">
|
||||
<property name="text">
|
||||
<string>Use NTFS Compression</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>NTFS compression is built-in, fast, and completely reliable. Typically compresses memory cards (highly recommended).</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>CreateMemoryCardDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>CreateMemoryCardDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -60,7 +60,8 @@
|
|||
<string>Add</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="folder-add-line" />
|
||||
<iconset theme="folder-add-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -76,7 +77,8 @@
|
|||
<string>Remove</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="folder-reduce-line" />
|
||||
<iconset theme="folder-reduce-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -130,7 +132,8 @@
|
|||
<string>Add</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="file-add-line" />
|
||||
<iconset theme="file-add-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -146,7 +149,8 @@
|
|||
<string>Remove</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="file-reduce-line" />
|
||||
<iconset theme="file-reduce-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -182,7 +186,8 @@
|
|||
<string>Scan For New Games</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="file-search-line" />
|
||||
<iconset theme="file-search-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -198,7 +203,8 @@
|
|||
<string>Rescan All Games</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="refresh-line" />
|
||||
<iconset theme="refresh-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -207,7 +213,7 @@
|
|||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="resources/resources.qrc"/>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -15,21 +15,450 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include <QtGui/QDrag>
|
||||
#include <QtWidgets/QInputDialog>
|
||||
#include <QtWidgets/QMenu>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <algorithm>
|
||||
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include "MemoryCardSettingsWidget.h"
|
||||
#include "CreateMemoryCardDialog.h"
|
||||
#include "EmuThread.h"
|
||||
#include "QtUtils.h"
|
||||
#include "SettingWidgetBinder.h"
|
||||
#include "SettingsDialog.h"
|
||||
|
||||
#include "pcsx2/MemoryCardFile.h"
|
||||
|
||||
static std::string getSlotFilenameKey(u32 slot)
|
||||
{
|
||||
return StringUtil::StdStringFromFormat("Slot%u_Filename", slot + 1);
|
||||
}
|
||||
|
||||
MemoryCardSettingsWidget::MemoryCardSettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_dialog(dialog)
|
||||
{
|
||||
// SettingsInterface* sif = dialog->getSettingsInterface();
|
||||
SettingsInterface* sif = m_dialog->getSettingsInterface();
|
||||
|
||||
m_ui.setupUi(this);
|
||||
|
||||
// this is a bit lame, but resizeEvent() isn't good enough to autosize our columns,
|
||||
// since the group box hasn't been resized at that point.
|
||||
m_ui.cardGroupBox->installEventFilter(this);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.autoEject, "EmuCore", "McdEnableEjection", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.automaticManagement, "EmuCore", "McdFolderAutoManage", true);
|
||||
|
||||
for (u32 i = 0; i < static_cast<u32>(m_slots.size()); i++)
|
||||
createSlotWidgets(&m_slots[i], i);
|
||||
|
||||
m_ui.cardList->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(m_ui.cardList, &MemoryCardListWidget::itemSelectionChanged, this, &MemoryCardSettingsWidget::updateCardActions);
|
||||
connect(m_ui.cardList, &MemoryCardListWidget::customContextMenuRequested, this, &MemoryCardSettingsWidget::listContextMenuRequested);
|
||||
|
||||
connect(m_ui.refreshCard, &QPushButton::clicked, this, &MemoryCardSettingsWidget::refresh);
|
||||
connect(m_ui.createCard, &QPushButton::clicked, this, &MemoryCardSettingsWidget::createCard);
|
||||
connect(m_ui.duplicateCard, &QPushButton::clicked, this, &MemoryCardSettingsWidget::duplicateCard);
|
||||
connect(m_ui.renameCard, &QPushButton::clicked, this, &MemoryCardSettingsWidget::renameCard);
|
||||
connect(m_ui.convertCard, &QPushButton::clicked, this, &MemoryCardSettingsWidget::convertCard);
|
||||
connect(m_ui.deleteCard, &QPushButton::clicked, this, &MemoryCardSettingsWidget::deleteCard);
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
MemoryCardSettingsWidget::~MemoryCardSettingsWidget() = default;
|
||||
|
||||
void MemoryCardSettingsWidget::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
autoSizeUI();
|
||||
}
|
||||
|
||||
bool MemoryCardSettingsWidget::eventFilter(QObject* watched, QEvent* event)
|
||||
{
|
||||
if (watched == m_ui.cardGroupBox && event->type() == QEvent::Resize)
|
||||
autoSizeUI();
|
||||
|
||||
return QWidget::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
void MemoryCardSettingsWidget::createSlotWidgets(SlotGroup* port, u32 slot)
|
||||
{
|
||||
port->root = new QWidget(m_ui.portGroupBox);
|
||||
|
||||
SettingsInterface* sif = m_dialog->getSettingsInterface();
|
||||
port->enable = new QCheckBox(tr("Port %1").arg(slot + 1), port->root);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, port->enable, "MemoryCards", StringUtil::StdStringFromFormat("Slot%u_Enable", slot + 1), true);
|
||||
connect(port->enable, &QCheckBox::stateChanged, this, &MemoryCardSettingsWidget::refresh);
|
||||
|
||||
port->eject = new QToolButton(port->root);
|
||||
port->eject->setIcon(QIcon::fromTheme("eject-line"));
|
||||
port->eject->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
||||
connect(port->eject, &QToolButton::clicked, this, [this, slot]() { ejectSlot(slot); });
|
||||
|
||||
port->slot = new MemoryCardSlotWidget(port->root);
|
||||
connect(port->slot, &MemoryCardSlotWidget::cardDropped, this, [this, slot](const QString& card) { tryInsertCard(slot, card); });
|
||||
|
||||
QHBoxLayout* bottom_layout = new QHBoxLayout();
|
||||
bottom_layout->setContentsMargins(0, 0, 0, 0);
|
||||
bottom_layout->addWidget(port->slot, 1);
|
||||
bottom_layout->addWidget(port->eject, 0);
|
||||
|
||||
QVBoxLayout* vert_layout = new QVBoxLayout(port->root);
|
||||
vert_layout->setContentsMargins(0, 0, 0, 0);
|
||||
vert_layout->addWidget(port->enable, 0);
|
||||
vert_layout->addLayout(bottom_layout, 1);
|
||||
|
||||
static_cast<QGridLayout*>(m_ui.portGroupBox->layout())->addWidget(port->root, 0, slot);
|
||||
}
|
||||
|
||||
void MemoryCardSettingsWidget::autoSizeUI()
|
||||
{
|
||||
QtUtils::ResizeColumnsForTreeView(m_ui.cardList, {-1, 100, 80, 150});
|
||||
}
|
||||
|
||||
void MemoryCardSettingsWidget::tryInsertCard(u32 slot, const QString& newCard)
|
||||
{
|
||||
// handle where the card is dragged in from explorer or something
|
||||
const int lastSlashPos = std::max(newCard.lastIndexOf('/'), newCard.lastIndexOf('\\'));
|
||||
const std::string newCardStr((lastSlashPos >= 0) ? newCard.mid(0, lastSlashPos).toStdString() : newCard.toStdString());
|
||||
if (newCardStr.empty())
|
||||
return;
|
||||
|
||||
// make sure it's a card in the directory
|
||||
const std::vector<AvailableMcdInfo> mcds(FileMcd_GetAvailableCards(true));
|
||||
if (std::none_of(mcds.begin(), mcds.end(), [&newCardStr](const AvailableMcdInfo& mcd) { return mcd.name == newCardStr; }))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("This memory card is unknown."));
|
||||
return;
|
||||
}
|
||||
|
||||
m_dialog->setStringSettingValue("MemoryCards", getSlotFilenameKey(slot).c_str(), newCardStr.c_str());
|
||||
refresh();
|
||||
}
|
||||
|
||||
void MemoryCardSettingsWidget::ejectSlot(u32 slot)
|
||||
{
|
||||
m_dialog->setStringSettingValue("MemoryCards", getSlotFilenameKey(slot).c_str(), m_dialog->isPerGameSettings() ? nullptr : "");
|
||||
refresh();
|
||||
}
|
||||
|
||||
void MemoryCardSettingsWidget::createCard()
|
||||
{
|
||||
CreateMemoryCardDialog dialog(QtUtils::GetRootWidget(this));
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
refresh();
|
||||
}
|
||||
|
||||
QString MemoryCardSettingsWidget::getSelectedCard() const
|
||||
{
|
||||
QString ret;
|
||||
|
||||
const QList<QTreeWidgetItem*> selection(m_ui.cardList->selectedItems());
|
||||
if (!selection.empty())
|
||||
ret = selection[0]->text(0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MemoryCardSettingsWidget::updateCardActions()
|
||||
{
|
||||
const bool hasSelection = !getSelectedCard().isEmpty();
|
||||
|
||||
m_ui.convertCard->setEnabled(hasSelection);
|
||||
m_ui.duplicateCard->setEnabled(hasSelection);
|
||||
m_ui.renameCard->setEnabled(hasSelection);
|
||||
m_ui.deleteCard->setEnabled(hasSelection);
|
||||
}
|
||||
|
||||
void MemoryCardSettingsWidget::duplicateCard()
|
||||
{
|
||||
const QString selectedCard(getSelectedCard());
|
||||
if (selectedCard.isEmpty())
|
||||
return;
|
||||
|
||||
QMessageBox::critical(this, tr("Error"), tr("Not yet implemented."));
|
||||
}
|
||||
|
||||
void MemoryCardSettingsWidget::deleteCard()
|
||||
{
|
||||
const QString selectedCard(getSelectedCard());
|
||||
if (selectedCard.isEmpty())
|
||||
return;
|
||||
|
||||
if (QMessageBox::question(QtUtils::GetRootWidget(this), tr("Delete Memory Card"),
|
||||
tr("Are you sure you wish to delete the memory card '%1'?\n\n"
|
||||
"This action cannot be reversed, and you will lose any saves on the card.")
|
||||
.arg(selectedCard)) != QMessageBox::Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FileMcd_DeleteCard(selectedCard.toStdString()))
|
||||
{
|
||||
QMessageBox::critical(QtUtils::GetRootWidget(this), tr("Delete Memory Card"),
|
||||
tr("Failed to delete the memory card. The log may have more information."));
|
||||
return;
|
||||
}
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
void MemoryCardSettingsWidget::renameCard()
|
||||
{
|
||||
const QString selectedCard(getSelectedCard());
|
||||
if (selectedCard.isEmpty())
|
||||
return;
|
||||
|
||||
const QString newName(QInputDialog::getText(QtUtils::GetRootWidget(this),
|
||||
tr("Rename Memory Card"), tr("New Card Name"), QLineEdit::Normal, selectedCard));
|
||||
if (newName.isEmpty() || newName == selectedCard)
|
||||
return;
|
||||
|
||||
if (!newName.endsWith(QStringLiteral(".ps2")) || newName.length() <= 4)
|
||||
{
|
||||
QMessageBox::critical(QtUtils::GetRootWidget(this), tr("Rename Memory Card"),
|
||||
tr("New name is invalid, it must end with .ps2"));
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string newNameStr(newName.toStdString());
|
||||
if (FileMcd_GetCardInfo(newNameStr).has_value())
|
||||
{
|
||||
QMessageBox::critical(QtUtils::GetRootWidget(this), tr("Rename Memory Card"),
|
||||
tr("New name is invalid, a card with this name already exists."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FileMcd_RenameCard(selectedCard.toStdString(), newNameStr))
|
||||
{
|
||||
QMessageBox::critical(QtUtils::GetRootWidget(this), tr("Rename Memory Card"),
|
||||
tr("Failed to rename memory card. The log may contain more information."));
|
||||
return;
|
||||
}
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
void MemoryCardSettingsWidget::convertCard()
|
||||
{
|
||||
const QString selectedCard(getSelectedCard());
|
||||
if (selectedCard.isEmpty())
|
||||
return;
|
||||
|
||||
QMessageBox::critical(this, tr("Error"), tr("Not yet implemented."));
|
||||
}
|
||||
|
||||
void MemoryCardSettingsWidget::listContextMenuRequested(const QPoint& pos)
|
||||
{
|
||||
QMenu menu(this);
|
||||
|
||||
const QString selectedCard(getSelectedCard());
|
||||
if (!selectedCard.isEmpty())
|
||||
{
|
||||
for (u32 slot = 0; slot < MAX_SLOTS; slot++)
|
||||
{
|
||||
connect(menu.addAction(tr("Use for Port %1").arg(slot + 1)), &QAction::triggered,
|
||||
this, [this, &selectedCard, slot]() { tryInsertCard(slot, selectedCard); });
|
||||
}
|
||||
menu.addSeparator();
|
||||
|
||||
connect(menu.addAction(tr("Duplicate")), &QAction::triggered, this, &MemoryCardSettingsWidget::duplicateCard);
|
||||
connect(menu.addAction(tr("Rename")), &QAction::triggered, this, &MemoryCardSettingsWidget::renameCard);
|
||||
connect(menu.addAction(tr("Convert")), &QAction::triggered, this, &MemoryCardSettingsWidget::convertCard);
|
||||
connect(menu.addAction(tr("Delete")), &QAction::triggered, this, &MemoryCardSettingsWidget::deleteCard);
|
||||
menu.addSeparator();
|
||||
}
|
||||
|
||||
connect(menu.addAction("Create"), &QAction::triggered, this, &MemoryCardSettingsWidget::createCard);
|
||||
|
||||
menu.exec(m_ui.cardList->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void MemoryCardSettingsWidget::refresh()
|
||||
{
|
||||
for (u32 slot = 0; slot < static_cast<u32>(m_slots.size()); slot++)
|
||||
{
|
||||
const bool enabled = m_slots[slot].enable->isChecked();
|
||||
const std::optional<std::string> name(
|
||||
m_dialog->getStringValue("MemoryCards", getSlotFilenameKey(slot).c_str(),
|
||||
FileMcd_GetDefaultName(slot).c_str()));
|
||||
|
||||
m_slots[slot].slot->setCard(name);
|
||||
m_slots[slot].slot->setEnabled(enabled);
|
||||
m_slots[slot].eject->setEnabled(enabled);
|
||||
}
|
||||
|
||||
m_ui.cardList->refresh(m_dialog);
|
||||
updateCardActions();
|
||||
}
|
||||
|
||||
static QString getSizeSummary(const AvailableMcdInfo& mcd)
|
||||
{
|
||||
if (mcd.type == MemoryCardType::File)
|
||||
{
|
||||
switch (mcd.file_type)
|
||||
{
|
||||
case MemoryCardFileType::PS2_8MB:
|
||||
return qApp->translate("MemoryCardSettingsWidget", "PS2 (8MB)");
|
||||
|
||||
case MemoryCardFileType::PS2_16MB:
|
||||
return qApp->translate("MemoryCardSettingsWidget", "PS2 (16MB)");
|
||||
|
||||
case MemoryCardFileType::PS2_32MB:
|
||||
return qApp->translate("MemoryCardSettingsWidget", "PS2 (32MB)");
|
||||
|
||||
case MemoryCardFileType::PS2_64MB:
|
||||
return qApp->translate("MemoryCardSettingsWidget", "PS2 (64MB)");
|
||||
|
||||
case MemoryCardFileType::PS1:
|
||||
return qApp->translate("MemoryCardSettingsWidget", "PS1 (128KB)");
|
||||
|
||||
case MemoryCardFileType::Unknown:
|
||||
default:
|
||||
return qApp->translate("MemoryCardSettingsWidget", "Unknown");
|
||||
}
|
||||
}
|
||||
else if (mcd.type == MemoryCardType::Folder)
|
||||
{
|
||||
return qApp->translate("MemoryCardSettingsWidget", "PS2 (Folder)");
|
||||
}
|
||||
else
|
||||
{
|
||||
return qApp->translate("MemoryCardSettingsWidget", "Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
static QIcon getCardIcon(const AvailableMcdInfo& mcd)
|
||||
{
|
||||
if (mcd.type == MemoryCardType::File)
|
||||
return QIcon::fromTheme(QStringLiteral("sd-card-line"));
|
||||
else
|
||||
return QIcon::fromTheme(QStringLiteral("folder-open-line"));
|
||||
}
|
||||
|
||||
MemoryCardListWidget::MemoryCardListWidget(QWidget* parent)
|
||||
: QTreeWidget(parent)
|
||||
{
|
||||
}
|
||||
|
||||
MemoryCardListWidget::~MemoryCardListWidget() = default;
|
||||
|
||||
void MemoryCardListWidget::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
m_dragStartPos = event->pos();
|
||||
|
||||
QTreeWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void MemoryCardListWidget::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
if (!(event->buttons() & Qt::LeftButton) ||
|
||||
(event->pos() - m_dragStartPos).manhattanLength() < QApplication::startDragDistance())
|
||||
{
|
||||
QTreeWidget::mouseMoveEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
const QList<QTreeWidgetItem*> selection(selectedItems());
|
||||
if (selection.empty())
|
||||
return;
|
||||
|
||||
QDrag* drag = new QDrag(this);
|
||||
QMimeData* mimeData = new QMimeData();
|
||||
mimeData->setText(selection[0]->text(0));
|
||||
drag->setMimeData(mimeData);
|
||||
drag->exec(Qt::CopyAction);
|
||||
}
|
||||
|
||||
void MemoryCardListWidget::refresh(SettingsDialog* dialog)
|
||||
{
|
||||
clear();
|
||||
|
||||
// we can't use the in use flag here anyway, because the config may not be in line with per game settings.
|
||||
const std::vector<AvailableMcdInfo> mcds(FileMcd_GetAvailableCards(true));
|
||||
if (mcds.empty())
|
||||
return;
|
||||
|
||||
std::array<std::string, MemoryCardSettingsWidget::MAX_SLOTS> currentCards;
|
||||
for (u32 i = 0; i < static_cast<u32>(currentCards.size()); i++)
|
||||
{
|
||||
const std::optional<std::string> filename = dialog->getStringValue("MemoryCards",
|
||||
getSlotFilenameKey(i).c_str(), FileMcd_GetDefaultName(i).c_str());
|
||||
if (filename.has_value())
|
||||
currentCards[i] = std::move(filename.value());
|
||||
}
|
||||
|
||||
for (const AvailableMcdInfo& mcd : mcds)
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
const QDateTime mtime(QDateTime::fromSecsSinceEpoch(static_cast<qint64>(mcd.modified_time)));
|
||||
const bool inUse = (std::find(currentCards.begin(), currentCards.end(), mcd.name) != currentCards.end());
|
||||
|
||||
item->setDisabled(inUse);
|
||||
item->setIcon(0, getCardIcon(mcd));
|
||||
item->setText(0, QString::fromStdString(mcd.name));
|
||||
item->setText(1, getSizeSummary(mcd));
|
||||
item->setText(2, mcd.formatted ? tr("Yes") : tr("No"));
|
||||
item->setText(3, mtime.toString(QLocale::system().dateTimeFormat(QLocale::ShortFormat)));
|
||||
addTopLevelItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
MemoryCardSlotWidget::MemoryCardSlotWidget(QWidget* parent)
|
||||
: QListWidget(parent)
|
||||
{
|
||||
setAcceptDrops(true);
|
||||
setSelectionMode(NoSelection);
|
||||
}
|
||||
|
||||
MemoryCardSlotWidget::~MemoryCardSlotWidget() = default;
|
||||
|
||||
void MemoryCardSlotWidget::dragEnterEvent(QDragEnterEvent* event)
|
||||
{
|
||||
if (event->mimeData()->hasFormat("text/plain"))
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void MemoryCardSlotWidget::dragMoveEvent(QDragMoveEvent* event)
|
||||
{
|
||||
}
|
||||
|
||||
void MemoryCardSlotWidget::dropEvent(QDropEvent* event)
|
||||
{
|
||||
const QMimeData* data = event->mimeData();
|
||||
const QString text(data ? data->text() : QString());
|
||||
if (text.isEmpty())
|
||||
{
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
event->acceptProposedAction();
|
||||
emit cardDropped(text);
|
||||
}
|
||||
|
||||
void MemoryCardSlotWidget::setCard(const std::optional<std::string>& name)
|
||||
{
|
||||
clear();
|
||||
if (!name.has_value() || name->empty())
|
||||
return;
|
||||
|
||||
const std::optional<AvailableMcdInfo> mcd(FileMcd_GetCardInfo(name.value()));
|
||||
QListWidgetItem* item = new QListWidgetItem(this);
|
||||
|
||||
if (mcd.has_value())
|
||||
{
|
||||
item->setIcon(getCardIcon(mcd.value()));
|
||||
item->setText(tr("%1 [%2]").arg(QString::fromStdString(mcd->name)).arg(getSizeSummary(mcd.value())));
|
||||
}
|
||||
else
|
||||
{
|
||||
item->setIcon(QIcon::fromTheme("close-line"));
|
||||
item->setText(tr("%1 [Missing]").arg(QString::fromStdString(name.value())));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,20 +15,106 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "ui_MemoryCardSettingsWidget.h"
|
||||
#include <QtGui/QResizeEvent>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <QtWidgets/QTreeWidget>
|
||||
#include <QtWidgets/QToolButton>
|
||||
#include <QtWidgets/QListWidget>
|
||||
|
||||
class SettingsDialog;
|
||||
|
||||
struct AvailableMcdInfo;
|
||||
|
||||
class MemoryCardListWidget final : public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MemoryCardListWidget(QWidget* parent);
|
||||
~MemoryCardListWidget() override;
|
||||
|
||||
void refresh(SettingsDialog* dialog);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
void mouseMoveEvent(QMouseEvent* event);
|
||||
|
||||
private:
|
||||
QPoint m_dragStartPos = {};
|
||||
};
|
||||
|
||||
class MemoryCardSlotWidget final : public QListWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MemoryCardSlotWidget(QWidget* parent);
|
||||
~MemoryCardSlotWidget() override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void cardDropped(const QString& newCard);
|
||||
|
||||
public:
|
||||
void setCard(const std::optional<std::string>& name);
|
||||
|
||||
protected:
|
||||
void dragEnterEvent(QDragEnterEvent* event);
|
||||
void dragMoveEvent(QDragMoveEvent* event);
|
||||
void dropEvent(QDropEvent* event);
|
||||
};
|
||||
|
||||
// Must be included *after* the custom widgets.
|
||||
#include "ui_MemoryCardSettingsWidget.h"
|
||||
|
||||
class MemoryCardSettingsWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum : u32
|
||||
{
|
||||
MAX_SLOTS = 2
|
||||
};
|
||||
|
||||
MemoryCardSettingsWidget(SettingsDialog* dialog, QWidget* parent);
|
||||
~MemoryCardSettingsWidget();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* event);
|
||||
bool eventFilter(QObject* watched, QEvent* event);
|
||||
|
||||
private Q_SLOTS:
|
||||
void listContextMenuRequested(const QPoint& pos);
|
||||
void refresh();
|
||||
|
||||
private:
|
||||
struct SlotGroup
|
||||
{
|
||||
QWidget* root;
|
||||
QCheckBox* enable;
|
||||
QToolButton* eject;
|
||||
MemoryCardSlotWidget* slot;
|
||||
};
|
||||
|
||||
void createSlotWidgets(SlotGroup* port, u32 slot);
|
||||
void autoSizeUI();
|
||||
|
||||
void tryInsertCard(u32 slot, const QString& newCard);
|
||||
void ejectSlot(u32 slot);
|
||||
|
||||
void createCard();
|
||||
|
||||
QString getSelectedCard() const;
|
||||
void updateCardActions();
|
||||
void duplicateCard();
|
||||
void deleteCard();
|
||||
void renameCard();
|
||||
void convertCard();
|
||||
|
||||
SettingsDialog* m_dialog;
|
||||
Ui::MemoryCardSettingsWidget m_ui;
|
||||
|
||||
std::array<SlotGroup, MAX_SLOTS> m_slots;
|
||||
};
|
||||
|
|
|
@ -6,14 +6,179 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
<width>796</width>
|
||||
<height>443</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="portGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Console Ports</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="cardGroupBox">
|
||||
<property name="title">
|
||||
<string>Memory Cards</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="MemoryCardListWidget" name="cardList">
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Formatted</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Last Modified</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="refreshCard">
|
||||
<property name="text">
|
||||
<string>Refresh</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="createCard">
|
||||
<property name="text">
|
||||
<string>Create</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="duplicateCard">
|
||||
<property name="text">
|
||||
<string>Duplicate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="renameCard">
|
||||
<property name="text">
|
||||
<string>Rename</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="convertCard">
|
||||
<property name="text">
|
||||
<string>Convert</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteCard">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="settingsGroupBox">
|
||||
<property name="title">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="automaticManagement">
|
||||
<property name="text">
|
||||
<string>Automatically manage saves based on running game</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="autoEject">
|
||||
<property name="text">
|
||||
<string>Auto-eject memory cards when loading save states</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>MemoryCardListWidget</class>
|
||||
<extends>QTreeWidget</extends>
|
||||
<header>MemoryCardSettingsWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "GraphicsSettingsWidget.h"
|
||||
#include "HotkeySettingsWidget.h"
|
||||
#include "InterfaceSettingsWidget.h"
|
||||
#include "MemoryCardSettingsWidget.h"
|
||||
#include "SystemSettingsWidget.h"
|
||||
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
@ -118,8 +119,13 @@ void SettingsDialog::setupUi(const GameList::Entry* game)
|
|||
addWidget(m_audio_settings = new AudioSettingsWidget(this, m_ui.settingsContainer), tr("Audio"), QStringLiteral("volume-up-line"),
|
||||
tr("<strong>Audio Settings</strong><hr>These options control the audio output of the console. Mouse over an option for additional "
|
||||
"information."));
|
||||
addWidget(
|
||||
new QWidget(m_ui.settingsContainer), tr("Memory Cards"), QStringLiteral("sd-card-line"), tr("<strong>Memory Card Settings</strong><hr>"));
|
||||
|
||||
// for now, memory cards aren't settable per-game
|
||||
if (!isPerGameSettings())
|
||||
{
|
||||
addWidget(m_memory_card_settings = new MemoryCardSettingsWidget(this, m_ui.settingsContainer), tr("Memory Cards"),
|
||||
QStringLiteral("sd-card-line"), tr("<strong>Memory Card Settings</strong><hr>"));
|
||||
}
|
||||
|
||||
m_ui.settingsCategory->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
m_ui.settingsCategory->setCurrentRow(0);
|
||||
|
|
|
@ -152,6 +152,7 @@
|
|||
<ClCompile Include="Settings\BIOSSettingsWidget.cpp" />
|
||||
<ClCompile Include="Settings\ControllerBindingWidgets.cpp" />
|
||||
<ClCompile Include="Settings\ControllerGlobalSettingsWidget.cpp" />
|
||||
<ClCompile Include="Settings\CreateMemoryCardDialog.cpp" />
|
||||
<ClCompile Include="Settings\EmulationSettingsWidget.cpp" />
|
||||
<ClCompile Include="Settings\GameListSettingsWidget.cpp" />
|
||||
<ClCompile Include="Settings\GraphicsSettingsWidget.cpp" />
|
||||
|
@ -199,6 +200,7 @@
|
|||
<QtMoc Include="Settings\AudioSettingsWidget.h" />
|
||||
<QtMoc Include="Settings\MemoryCardSettingsWidget.h" />
|
||||
<QtMoc Include="Settings\GameSummaryWidget.h" />
|
||||
<QtMoc Include="Settings\CreateMemoryCardDialog.h" />
|
||||
<QtMoc Include="GameList\GameListModel.h" />
|
||||
<QtMoc Include="GameList\GameListWidget.h" />
|
||||
<QtMoc Include="GameList\GameListRefreshThread.h" />
|
||||
|
@ -223,6 +225,7 @@
|
|||
<ClCompile Include="$(IntDir)Settings\moc_ControllerBindingWidgets.cpp" />
|
||||
<ClCompile Include="$(IntDir)Settings\moc_ControllerGlobalSettingsWidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)Settings\moc_ControllerSettingsDialog.cpp" />
|
||||
<ClCompile Include="$(IntDir)Settings\moc_CreateMemoryCardDialog.cpp" />
|
||||
<ClCompile Include="$(IntDir)Settings\moc_EmulationSettingsWidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)Settings\moc_GameListSettingsWidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)Settings\moc_GraphicsSettingsWidget.cpp" />
|
||||
|
@ -294,6 +297,9 @@
|
|||
<QtUi Include="Settings\ControllerGlobalSettingsWidget.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\CreateMemoryCardDialog.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\AudioSettingsWidget.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
|
|
|
@ -194,6 +194,12 @@
|
|||
<ClCompile Include="Settings\AudioSettingsWidget.cpp">
|
||||
<Filter>Settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(IntDir)Settings\moc_CreateMemoryCardDialog.cpp">
|
||||
<Filter>moc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Settings\CreateMemoryCardDialog.cpp">
|
||||
<Filter>Settings</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="..\pcsx2\windows\PCSX2.manifest">
|
||||
|
@ -274,6 +280,9 @@
|
|||
<QtMoc Include="Settings\AudioSettingsWidget.h">
|
||||
<Filter>Settings</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="Settings\CreateMemoryCardDialog.h">
|
||||
<Filter>Settings</Filter>
|
||||
</QtMoc>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtResource Include="resources\resources.qrc">
|
||||
|
@ -333,5 +342,8 @@
|
|||
<QtUi Include="Settings\AudioSettingsWidget.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\CreateMemoryCardDialog.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</QtUi>
|
||||
</ItemGroup>
|
||||
</Project>
|
After Width: | Height: | Size: 252 B |
After Width: | Height: | Size: 296 B |
After Width: | Height: | Size: 369 B |
After Width: | Height: | Size: 487 B |
After Width: | Height: | Size: 640 B |
After Width: | Height: | Size: 261 B |
After Width: | Height: | Size: 311 B |
After Width: | Height: | Size: 390 B |
After Width: | Height: | Size: 509 B |
After Width: | Height: | Size: 645 B |
|
@ -17,6 +17,7 @@
|
|||
<file>icons/black/16/door-open-line.png</file>
|
||||
<file>icons/black/16/download-2-line.png</file>
|
||||
<file>icons/black/16/dvd-line.png</file>
|
||||
<file>icons/black/16/eject-line.png</file>
|
||||
<file>icons/black/16/file-add-line.png</file>
|
||||
<file>icons/black/16/file-line.png</file>
|
||||
<file>icons/black/16/file-list-line.png</file>
|
||||
|
@ -56,6 +57,7 @@
|
|||
<file>icons/black/24/door-open-line.png</file>
|
||||
<file>icons/black/24/download-2-line.png</file>
|
||||
<file>icons/black/24/dvd-line.png</file>
|
||||
<file>icons/black/24/eject-line.png</file>
|
||||
<file>icons/black/24/file-add-line.png</file>
|
||||
<file>icons/black/24/file-line.png</file>
|
||||
<file>icons/black/24/file-list-line.png</file>
|
||||
|
@ -94,6 +96,7 @@
|
|||
<file>icons/black/32/door-open-line.png</file>
|
||||
<file>icons/black/32/download-2-line.png</file>
|
||||
<file>icons/black/32/dvd-line.png</file>
|
||||
<file>icons/black/32/eject-line.png</file>
|
||||
<file>icons/black/32/file-add-line.png</file>
|
||||
<file>icons/black/32/file-line.png</file>
|
||||
<file>icons/black/32/file-list-line.png</file>
|
||||
|
@ -133,6 +136,7 @@
|
|||
<file>icons/black/48/door-open-line.png</file>
|
||||
<file>icons/black/48/download-2-line.png</file>
|
||||
<file>icons/black/48/dvd-line.png</file>
|
||||
<file>icons/black/48/eject-line.png</file>
|
||||
<file>icons/black/48/file-add-line.png</file>
|
||||
<file>icons/black/48/file-line.png</file>
|
||||
<file>icons/black/48/file-list-line.png</file>
|
||||
|
@ -171,6 +175,7 @@
|
|||
<file>icons/black/64/door-open-line.png</file>
|
||||
<file>icons/black/64/download-2-line.png</file>
|
||||
<file>icons/black/64/dvd-line.png</file>
|
||||
<file>icons/black/64/eject-line.png</file>
|
||||
<file>icons/black/64/file-add-line.png</file>
|
||||
<file>icons/black/64/file-line.png</file>
|
||||
<file>icons/black/64/file-list-line.png</file>
|
||||
|
@ -239,6 +244,7 @@
|
|||
<file>icons/white/16/door-open-line.png</file>
|
||||
<file>icons/white/16/download-2-line.png</file>
|
||||
<file>icons/white/16/dvd-line.png</file>
|
||||
<file>icons/white/16/eject-line.png</file>
|
||||
<file>icons/white/16/file-add-line.png</file>
|
||||
<file>icons/white/16/file-line.png</file>
|
||||
<file>icons/white/16/file-list-line.png</file>
|
||||
|
@ -278,6 +284,7 @@
|
|||
<file>icons/white/24/door-open-line.png</file>
|
||||
<file>icons/white/24/download-2-line.png</file>
|
||||
<file>icons/white/24/dvd-line.png</file>
|
||||
<file>icons/white/24/eject-line.png</file>
|
||||
<file>icons/white/24/file-add-line.png</file>
|
||||
<file>icons/white/24/file-line.png</file>
|
||||
<file>icons/white/24/file-list-line.png</file>
|
||||
|
@ -317,6 +324,7 @@
|
|||
<file>icons/white/32/door-open-line.png</file>
|
||||
<file>icons/white/32/download-2-line.png</file>
|
||||
<file>icons/white/32/dvd-line.png</file>
|
||||
<file>icons/white/32/eject-line.png</file>
|
||||
<file>icons/white/32/file-add-line.png</file>
|
||||
<file>icons/white/32/file-line.png</file>
|
||||
<file>icons/white/32/file-list-line.png</file>
|
||||
|
@ -356,6 +364,7 @@
|
|||
<file>icons/white/48/door-open-line.png</file>
|
||||
<file>icons/white/48/download-2-line.png</file>
|
||||
<file>icons/white/48/dvd-line.png</file>
|
||||
<file>icons/white/48/eject-line.png</file>
|
||||
<file>icons/white/48/file-add-line.png</file>
|
||||
<file>icons/white/48/file-line.png</file>
|
||||
<file>icons/white/48/file-list-line.png</file>
|
||||
|
@ -395,6 +404,7 @@
|
|||
<file>icons/white/64/door-open-line.png</file>
|
||||
<file>icons/white/64/download-2-line.png</file>
|
||||
<file>icons/white/64/dvd-line.png</file>
|
||||
<file>icons/white/64/eject-line.png</file>
|
||||
<file>icons/white/64/file-add-line.png</file>
|
||||
<file>icons/white/64/file-line.png</file>
|
||||
<file>icons/white/64/file-list-line.png</file>
|
||||
|
|