QtUtils: Add ShowFileInFolder function and make GameList right-click menu actions use it.
This commit is contained in:
@@ -65,6 +65,7 @@
|
|||||||
#include "DolphinQt/QtUtils/DoubleClickEventFilter.h"
|
#include "DolphinQt/QtUtils/DoubleClickEventFilter.h"
|
||||||
#include "DolphinQt/QtUtils/ModalMessageBox.h"
|
#include "DolphinQt/QtUtils/ModalMessageBox.h"
|
||||||
#include "DolphinQt/QtUtils/NonAutodismissibleMenu.h"
|
#include "DolphinQt/QtUtils/NonAutodismissibleMenu.h"
|
||||||
|
#include "DolphinQt/QtUtils/QtUtils.h"
|
||||||
#include "DolphinQt/Resources.h"
|
#include "DolphinQt/Resources.h"
|
||||||
#include "DolphinQt/Settings.h"
|
#include "DolphinQt/Settings.h"
|
||||||
#include "DolphinQt/WiiUpdate.h"
|
#include "DolphinQt/WiiUpdate.h"
|
||||||
@@ -722,19 +723,7 @@ void GameList::OpenContainingFolder()
|
|||||||
if (!game)
|
if (!game)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Remove everything after the last separator in the game's path, resulting in the parent
|
QtUtils::ShowFileInFolder(game->GetFilePath());
|
||||||
// directory path with a trailing separator. Keeping the trailing separator prevents Windows from
|
|
||||||
// mistakenly opening a .bat or .exe file in the grandparent folder when that file has the same
|
|
||||||
// base name as the folder (See https://bugs.dolphin-emu.org/issues/12411).
|
|
||||||
std::string parent_directory_path;
|
|
||||||
SplitPath(game->GetFilePath(), &parent_directory_path, nullptr, nullptr);
|
|
||||||
if (parent_directory_path.empty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QUrl url = QUrl::fromLocalFile(QString::fromStdString(parent_directory_path));
|
|
||||||
QDesktopServices::openUrl(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameList::OpenWiiSaveFolder()
|
void GameList::OpenWiiSaveFolder()
|
||||||
@@ -766,45 +755,44 @@ void GameList::OpenGCSaveFolder()
|
|||||||
|
|
||||||
for (Slot slot : ExpansionInterface::MEMCARD_SLOTS)
|
for (Slot slot : ExpansionInterface::MEMCARD_SLOTS)
|
||||||
{
|
{
|
||||||
QUrl url;
|
|
||||||
const ExpansionInterface::EXIDeviceType current_exi_device =
|
const ExpansionInterface::EXIDeviceType current_exi_device =
|
||||||
Config::Get(Config::GetInfoForEXIDevice(slot));
|
Config::Get(Config::GetInfoForEXIDevice(slot));
|
||||||
switch (current_exi_device)
|
switch (current_exi_device)
|
||||||
{
|
{
|
||||||
case ExpansionInterface::EXIDeviceType::MemoryCardFolder:
|
case ExpansionInterface::EXIDeviceType::MemoryCardFolder:
|
||||||
{
|
{
|
||||||
std::string override_path = Config::Get(Config::GetInfoForGCIPathOverride(slot));
|
namespace fs = std::filesystem;
|
||||||
QDir dir(QString::fromStdString(override_path.empty() ?
|
|
||||||
Config::GetGCIFolderPath(slot, game->GetRegion()) :
|
|
||||||
override_path));
|
|
||||||
|
|
||||||
if (!dir.entryList({QStringLiteral("%1-%2-*.gci")
|
std::string override_path = Config::Get(Config::GetInfoForGCIPathOverride(slot));
|
||||||
.arg(QString::fromStdString(game->GetMakerID()))
|
const auto dir =
|
||||||
.arg(QString::fromStdString(game->GetGameID().substr(0, 4)))})
|
override_path.empty() ? Config::GetGCIFolderPath(slot, game->GetRegion()) : override_path;
|
||||||
.empty())
|
|
||||||
|
const auto gci_filename_prefix =
|
||||||
|
fs::path{fmt::format("{}-{}-", game->GetMakerID(), game->GetGameID().substr(0, 4))}
|
||||||
|
.native();
|
||||||
|
const auto gci_extension = fs::path{".gci"}.native();
|
||||||
|
|
||||||
|
for (const auto& entry : fs::directory_iterator(dir))
|
||||||
{
|
{
|
||||||
url = QUrl::fromLocalFile(dir.absolutePath());
|
if (entry.path().filename().native().starts_with(gci_filename_prefix) &&
|
||||||
|
entry.path().extension() == gci_extension)
|
||||||
|
{
|
||||||
|
QtUtils::ShowFileInFolder(entry.path().generic_string());
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ExpansionInterface::EXIDeviceType::MemoryCard:
|
case ExpansionInterface::EXIDeviceType::MemoryCard:
|
||||||
{
|
{
|
||||||
const std::string memcard_path = Config::GetMemcardPath(slot, game->GetRegion());
|
QtUtils::ShowFileInFolder(Config::GetMemcardPath(slot, game->GetRegion()));
|
||||||
|
found = true;
|
||||||
std::string memcard_dir;
|
|
||||||
|
|
||||||
SplitPath(memcard_path, &memcard_dir, nullptr, nullptr);
|
|
||||||
url = QUrl::fromLocalFile(QString::fromStdString(memcard_dir));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
found |= !url.isEmpty();
|
|
||||||
|
|
||||||
if (!url.isEmpty())
|
|
||||||
QDesktopServices::openUrl(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
|
|||||||
@@ -4,10 +4,43 @@
|
|||||||
#include "DolphinQt/QtUtils/QtUtils.h"
|
#include "DolphinQt/QtUtils/QtUtils.h"
|
||||||
|
|
||||||
#include <QDateTimeEdit>
|
#include <QDateTimeEdit>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QDir>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QProcess>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
|
|
||||||
|
#if defined(QT_DBUS_LIB)
|
||||||
|
#include <QDBusConnectionInterface>
|
||||||
|
#include <QDBusInterface>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "Common/Logging/Log.h"
|
||||||
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
void ShowFolderOfFile(std::string_view file_path)
|
||||||
|
{
|
||||||
|
// Remove everything after the last separator in the game's path, resulting in the parent
|
||||||
|
// directory path with a trailing separator. Keeping the trailing separator prevents Windows from
|
||||||
|
// mistakenly opening a .bat or .exe file in the grandparent folder when that file has the same
|
||||||
|
// base name as the folder (See https://bugs.dolphin-emu.org/issues/12411).
|
||||||
|
std::string parent_directory_path;
|
||||||
|
SplitPath(file_path, &parent_directory_path, nullptr, nullptr);
|
||||||
|
if (parent_directory_path.empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QUrl url = QUrl::fromLocalFile(QString::fromStdString(parent_directory_path));
|
||||||
|
QDesktopServices::openUrl(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace QtUtils
|
namespace QtUtils
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -68,4 +101,54 @@ void CenterOnParentWindow(QWidget* const widget)
|
|||||||
widget->setGeometry(QRect(pos, size));
|
widget->setGeometry(QRect(pos, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShowFileInFolder(std::string_view file_path)
|
||||||
|
{
|
||||||
|
#if defined(QT_DBUS_LIB)
|
||||||
|
QDBusInterface dbus{QString::fromLatin1("org.freedesktop.DBus"),
|
||||||
|
QString::fromLatin1("/org/freedesktop/DBus"),
|
||||||
|
QString::fromLatin1("org.freedesktop.DBus")};
|
||||||
|
|
||||||
|
dbus.call(QString::fromLatin1("StartServiceByName"),
|
||||||
|
QString::fromLatin1("org.freedesktop.FileManager1"), 0u);
|
||||||
|
|
||||||
|
QDBusInterface iface{QString::fromLatin1("org.freedesktop.FileManager1"),
|
||||||
|
QString::fromLatin1("/org/freedesktop/FileManager1"),
|
||||||
|
QString::fromLatin1("org.freedesktop.FileManager1")};
|
||||||
|
if (iface.isValid())
|
||||||
|
{
|
||||||
|
QStringList urls;
|
||||||
|
urls << QUrl::fromLocalFile(QString::fromUtf8(file_path)).toString();
|
||||||
|
|
||||||
|
const QDBusReply<void> reply = iface.call(QString::fromLatin1("ShowItems"), urls, QString{});
|
||||||
|
if (reply.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto& err = reply.error();
|
||||||
|
WARN_LOG_FMT(COMMON, "DBus call failed: {} - {}", err.name().toStdString(),
|
||||||
|
err.message().toStdString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WARN_LOG_FMT(COMMON, "Invalid DBus interface: {}", iface.lastError().message().toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
if (QProcess{}.startDetached(QString::fromLatin1("explorer.exe"),
|
||||||
|
{QString::fromLatin1("/select"), QString::fromLatin1(","),
|
||||||
|
QDir::toNativeSeparators(QString::fromUtf8(file_path))}))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
if (QProcess{}.startDetached(QString::fromLatin1("open"),
|
||||||
|
{QString::fromLatin1("-R"), QString::fromUtf8(file_path)}))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Fall back on failure or unsupported platforms.
|
||||||
|
ShowFolderOfFile(file_path);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QtUtils
|
} // namespace QtUtils
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include <QStyle>
|
#include <QStyle>
|
||||||
|
|
||||||
class QDateTimeEdit;
|
class QDateTimeEdit;
|
||||||
@@ -37,4 +39,7 @@ public:
|
|||||||
QSize sizeHint() const override { return Widget::minimumSizeHint(); }
|
QSize sizeHint() const override { return Widget::minimumSizeHint(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Opens the folder of the given file (and also selects the file on supported platforms).
|
||||||
|
void ShowFileInFolder(std::string_view file_path);
|
||||||
|
|
||||||
} // namespace QtUtils
|
} // namespace QtUtils
|
||||||
|
|||||||
Reference in New Issue
Block a user