mirror of https://github.com/PCSX2/pcsx2.git
Qt: Implement drag/drop to main window
This commit is contained in:
parent
25fa70fe9e
commit
ce53b7adb1
|
@ -990,26 +990,12 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
|
||||||
|
|
||||||
void MainWindow::onStartFileActionTriggered()
|
void MainWindow::onStartFileActionTriggered()
|
||||||
{
|
{
|
||||||
QString filename =
|
QString path =
|
||||||
QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Select Disc Image"), QString(), tr(DISC_IMAGE_FILTER), nullptr));
|
QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Select Disc Image"), QString(), tr(DISC_IMAGE_FILTER), nullptr));
|
||||||
if (filename.isEmpty())
|
if (path.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::shared_ptr<VMBootParameters> params = std::make_shared<VMBootParameters>();
|
doStartDisc(path);
|
||||||
params->filename = filename.toStdString();
|
|
||||||
|
|
||||||
// we might still be saving a resume state...
|
|
||||||
VMManager::WaitForSaveStateFlush();
|
|
||||||
|
|
||||||
const std::optional<bool> resume(
|
|
||||||
promptForResumeState(
|
|
||||||
QString::fromStdString(VMManager::GetSaveStateFileName(params->filename.c_str(), -1))));
|
|
||||||
if (!resume.has_value())
|
|
||||||
return;
|
|
||||||
else if (resume.value())
|
|
||||||
params->state_index = -1;
|
|
||||||
|
|
||||||
g_emu_thread->startVM(std::move(params));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onStartBIOSActionTriggered()
|
void MainWindow::onStartBIOSActionTriggered()
|
||||||
|
@ -1392,6 +1378,59 @@ void MainWindow::closeEvent(QCloseEvent* event)
|
||||||
QMainWindow::closeEvent(event);
|
QMainWindow::closeEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QString getFilenameFromMimeData(const QMimeData* md)
|
||||||
|
{
|
||||||
|
QString filename;
|
||||||
|
if (md->hasUrls())
|
||||||
|
{
|
||||||
|
// only one url accepted
|
||||||
|
const QList<QUrl> urls(md->urls());
|
||||||
|
if (urls.size() == 1)
|
||||||
|
filename = urls.front().toLocalFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::dragEnterEvent(QDragEnterEvent* event)
|
||||||
|
{
|
||||||
|
const std::string filename(getFilenameFromMimeData(event->mimeData()).toStdString());
|
||||||
|
|
||||||
|
// allow save states being dragged in
|
||||||
|
if (!VMManager::IsLoadableFileName(filename) && !VMManager::IsSaveStateFileName(filename))
|
||||||
|
return;
|
||||||
|
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::dropEvent(QDropEvent* event)
|
||||||
|
{
|
||||||
|
const QString filename(getFilenameFromMimeData(event->mimeData()));
|
||||||
|
const std::string filename_str(filename.toStdString());
|
||||||
|
if (VMManager::IsSaveStateFileName(filename_str))
|
||||||
|
{
|
||||||
|
// can't load a save state without a current VM
|
||||||
|
if (m_vm_valid)
|
||||||
|
{
|
||||||
|
event->acceptProposedAction();
|
||||||
|
g_emu_thread->loadState(filename);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("Load State Failed"), tr("Cannot load a save state without a running VM."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (VMManager::IsLoadableFileName(filename_str))
|
||||||
|
{
|
||||||
|
// if we're already running, do a disc change, otherwise start
|
||||||
|
event->acceptProposedAction();
|
||||||
|
if (m_vm_valid)
|
||||||
|
doDiscChange(filename);
|
||||||
|
else
|
||||||
|
doStartDisc(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
|
DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
|
||||||
{
|
{
|
||||||
DevCon.WriteLn("createDisplay(%u, %u)", static_cast<u32>(fullscreen), static_cast<u32>(render_to_main));
|
DevCon.WriteLn("createDisplay(%u, %u)", static_cast<u32>(fullscreen), static_cast<u32>(render_to_main));
|
||||||
|
@ -2013,6 +2052,28 @@ void MainWindow::updateSaveStateMenus(const QString& filename, const QString& se
|
||||||
populateSaveStateMenu(m_ui.menuSaveState, serial, crc);
|
populateSaveStateMenu(m_ui.menuSaveState, serial, crc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::doStartDisc(const QString& path)
|
||||||
|
{
|
||||||
|
if (m_vm_valid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::shared_ptr<VMBootParameters> params = std::make_shared<VMBootParameters>();
|
||||||
|
params->filename = path.toStdString();
|
||||||
|
|
||||||
|
// we might still be saving a resume state...
|
||||||
|
VMManager::WaitForSaveStateFlush();
|
||||||
|
|
||||||
|
const std::optional<bool> resume(
|
||||||
|
promptForResumeState(
|
||||||
|
QString::fromStdString(VMManager::GetSaveStateFileName(params->filename.c_str(), -1))));
|
||||||
|
if (!resume.has_value())
|
||||||
|
return;
|
||||||
|
else if (resume.value())
|
||||||
|
params->state_index = -1;
|
||||||
|
|
||||||
|
g_emu_thread->startVM(std::move(params));
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::doDiscChange(const QString& path)
|
void MainWindow::doDiscChange(const QString& path)
|
||||||
{
|
{
|
||||||
bool reset_system = false;
|
bool reset_system = false;
|
||||||
|
|
|
@ -157,6 +157,8 @@ private Q_SLOTS:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void closeEvent(QCloseEvent* event) override;
|
void closeEvent(QCloseEvent* event) override;
|
||||||
|
void dragEnterEvent(QDragEnterEvent* event) override;
|
||||||
|
void dropEvent(QDropEvent* event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum : s32
|
enum : s32
|
||||||
|
@ -206,6 +208,7 @@ private:
|
||||||
void populateLoadStateMenu(QMenu* menu, const QString& filename, const QString& serial, quint32 crc);
|
void populateLoadStateMenu(QMenu* menu, const QString& filename, const QString& serial, quint32 crc);
|
||||||
void populateSaveStateMenu(QMenu* menu, const QString& serial, quint32 crc);
|
void populateSaveStateMenu(QMenu* menu, const QString& serial, quint32 crc);
|
||||||
void updateSaveStateMenus(const QString& filename, const QString& serial, quint32 crc);
|
void updateSaveStateMenus(const QString& filename, const QString& serial, quint32 crc);
|
||||||
|
void doStartDisc(const QString& path);
|
||||||
void doDiscChange(const QString& path);
|
void doDiscChange(const QString& path);
|
||||||
|
|
||||||
Ui::MainWindow m_ui;
|
Ui::MainWindow m_ui;
|
||||||
|
|
|
@ -110,17 +110,13 @@ const char* GameList::EntryCompatibilityRatingToString(CompatibilityRating ratin
|
||||||
// clang-format on
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameList::IsScannableFilename(const std::string& path)
|
bool GameList::IsScannableFilename(const std::string_view& path)
|
||||||
{
|
{
|
||||||
static const char* extensions[] = {".iso", ".mdf", ".nrg", ".bin", ".img", ".gz", ".cso", ".chd", ".elf", ".irx"};
|
static const char* extensions[] = {".iso", ".mdf", ".nrg", ".bin", ".img", ".gz", ".cso", ".chd", ".elf", ".irx"};
|
||||||
|
|
||||||
const std::string::size_type pos = path.rfind('.');
|
|
||||||
if (pos == std::string::npos)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (const char* test_extension : extensions)
|
for (const char* test_extension : extensions)
|
||||||
{
|
{
|
||||||
if (StringUtil::Strcasecmp(&path[pos], test_extension) == 0)
|
if (StringUtil::EndsWithNoCase(path, test_extension))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ namespace GameList
|
||||||
const char* RegionToString(Region region);
|
const char* RegionToString(Region region);
|
||||||
const char* EntryCompatibilityRatingToString(CompatibilityRating rating);
|
const char* EntryCompatibilityRatingToString(CompatibilityRating rating);
|
||||||
|
|
||||||
bool IsScannableFilename(const std::string& path);
|
bool IsScannableFilename(const std::string_view& path);
|
||||||
|
|
||||||
/// Fills in boot parameters (iso or elf) based on the game list entry.
|
/// Fills in boot parameters (iso or elf) based on the game list entry.
|
||||||
void FillBootParametersForEntry(VMBootParameters* params, const Entry* entry);
|
void FillBootParametersForEntry(VMBootParameters* params, const Entry* entry);
|
||||||
|
|
|
@ -1208,18 +1208,28 @@ bool VMManager::ChangeDisc(std::string path)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VMManager::IsElfFileName(const std::string& path)
|
bool VMManager::IsElfFileName(const std::string_view& path)
|
||||||
{
|
{
|
||||||
return StringUtil::EndsWithNoCase(path, ".elf");
|
return StringUtil::EndsWithNoCase(path, ".elf");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VMManager::IsGSDumpFileName(const std::string& path)
|
bool VMManager::IsGSDumpFileName(const std::string_view& path)
|
||||||
{
|
{
|
||||||
return (StringUtil::EndsWithNoCase(path, ".gs") ||
|
return (StringUtil::EndsWithNoCase(path, ".gs") ||
|
||||||
StringUtil::EndsWithNoCase(path, ".gs.xz") ||
|
StringUtil::EndsWithNoCase(path, ".gs.xz") ||
|
||||||
StringUtil::EndsWithNoCase(path, ".gs.zst"));
|
StringUtil::EndsWithNoCase(path, ".gs.zst"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VMManager::IsSaveStateFileName(const std::string_view& path)
|
||||||
|
{
|
||||||
|
return StringUtil::EndsWithNoCase(path, ".p2s");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VMManager::IsLoadableFileName(const std::string_view& path)
|
||||||
|
{
|
||||||
|
return IsElfFileName(path) || IsGSDumpFileName(path) || GameList::IsScannableFilename(path);
|
||||||
|
}
|
||||||
|
|
||||||
void VMManager::Execute()
|
void VMManager::Execute()
|
||||||
{
|
{
|
||||||
// Check for interpreter<->recompiler switches.
|
// Check for interpreter<->recompiler switches.
|
||||||
|
|
|
@ -135,10 +135,16 @@ namespace VMManager
|
||||||
bool ChangeDisc(std::string path);
|
bool ChangeDisc(std::string path);
|
||||||
|
|
||||||
/// Returns true if the specified path is an ELF.
|
/// Returns true if the specified path is an ELF.
|
||||||
bool IsElfFileName(const std::string& path);
|
bool IsElfFileName(const std::string_view& path);
|
||||||
|
|
||||||
/// Returns true if the specified path is a GS Dump.
|
/// Returns true if the specified path is a GS Dump.
|
||||||
bool IsGSDumpFileName(const std::string& path);
|
bool IsGSDumpFileName(const std::string_view& path);
|
||||||
|
|
||||||
|
/// Returns true if the specified path is a save state.
|
||||||
|
bool IsSaveStateFileName(const std::string_view& path);
|
||||||
|
|
||||||
|
/// Returns true if the specified path is a disc/elf/etc.
|
||||||
|
bool IsLoadableFileName(const std::string_view& path);
|
||||||
|
|
||||||
/// Returns the path for the game settings ini file for the specified CRC.
|
/// Returns the path for the game settings ini file for the specified CRC.
|
||||||
std::string GetGameSettingsPath(const std::string_view& game_serial, u32 game_crc);
|
std::string GetGameSettingsPath(const std::string_view& game_serial, u32 game_crc);
|
||||||
|
|
Loading…
Reference in New Issue