Qt: Use proper Show in Finder on macOS

This commit is contained in:
TellowKrinkle 2023-09-09 02:15:41 -05:00 committed by Connor McLaughlin
parent 6b62945632
commit 36e81949e0
5 changed files with 59 additions and 3 deletions

View File

@ -23,6 +23,8 @@ namespace CocoaTools
std::optional<std::string> MoveToTrash(std::string_view file);
/// Launch the given application once this one quits
bool DelayedLaunch(std::string_view file);
/// Open a Finder window to the given URL
bool ShowInFinder(std::string_view file);
}
#endif // __APPLE__

View File

@ -176,3 +176,12 @@ bool CocoaTools::DelayedLaunch(std::string_view file)
return [task launchAndReturnError:nil];
}
}
// MARK: - Directory Services
bool CocoaTools::ShowInFinder(std::string_view file)
{
NSString* str = [[NSString alloc] initWithBytes:file.data() length:file.size() encoding:NSUTF8StringEncoding];
return [[NSWorkspace sharedWorkspace] selectFile:str
inFileViewerRootedAtPath:nil];
}

View File

@ -1318,11 +1318,10 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
});
}
//: Refers to the directory where a game is contained.
action = menu.addAction(tr("Open Containing Directory..."));
action = menu.addAction(QtUtils::GetShowInFileExplorerMessage());
connect(action, &QAction::triggered, [this, entry]() {
const QFileInfo fi(QString::fromStdString(entry->path));
QtUtils::OpenURL(this, QUrl::fromLocalFile(fi.absolutePath()));
QtUtils::ShowInFileExplorer(this, fi);
});
action = menu.addAction(tr("Set Cover Image..."));

View File

@ -4,6 +4,7 @@
#include "QtUtils.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QFileInfo>
#include <QtCore/QMetaObject>
#include <QtGui/QAction>
#include <QtGui/QGuiApplication>
@ -26,10 +27,12 @@
#include <array>
#include <map>
#include "common/CocoaTools.h"
#include "common/Console.h"
#if defined(_WIN32)
#include "common/RedtapeWindows.h"
#include <Shlobj.h>
#elif !defined(APPLE)
#include <qpa/qplatformnativeinterface.h>
#endif
@ -129,6 +132,42 @@ namespace QtUtils
ResizeColumnsForView(view, widths);
}
void ShowInFileExplorer(QWidget* parent, const QFileInfo& file)
{
#if defined(_WIN32)
std::wstring wstr = QDir::toNativeSeparators(file.absoluteFilePath()).toStdWString();
bool ok = false;
if (PIDLIST_ABSOLUTE pidl = ILCreateFromPath(wstr.c_str()))
{
ok = SUCCEEDED(SHOpenFolderAndSelectItems(pidl, 0, nullptr, 0));
ILFree(pidl);
}
#elif defined(__APPLE__)
bool ok = CocoaTools::ShowInFinder(file.absoluteFilePath().toStdString());
#else
bool ok = QDesktopServices::openUrl(QUrl::fromLocalFile(file.absolutePath()));
#endif
if (!ok)
{
QMessageBox::critical(parent, QCoreApplication::translate("FileOperations", "Failed to show file"),
QCoreApplication::translate("FileOperations", "Failed to show file in file explorer.\n\nThe file was: %1").arg(file.absoluteFilePath()));
}
}
QString GetShowInFileExplorerMessage()
{
#if defined(_WIN32)
//: Windows action to show a file in Windows Explorer
return QCoreApplication::translate("FileOperations", "Show in Folder");
#elif defined(__APPLE__)
//: macOS action to show a file in Finder
return QCoreApplication::translate("FileOperations", "Show in Finder");
#else
//: Opens the system file manager to the directory containing a selected file
return QCoreApplication::translate("FileOperations", "Open Containing Directory");
#endif
}
void OpenURL(QWidget* parent, const QUrl& qurl)
{
if (!QDesktopServices::openUrl(qurl))

View File

@ -18,6 +18,7 @@ class ByteStream;
class QAction;
class QComboBox;
class QFileInfo;
class QFrame;
class QKeyEvent;
class QTableView;
@ -49,6 +50,12 @@ namespace QtUtils
/// NOTE: Defined in QtKeyCodes.cpp, not QtUtils.cpp.
u32 KeyEventToCode(const QKeyEvent* ev);
/// Shows a file, or the containing folder if unsupported, with the system file explorer
void ShowInFileExplorer(QWidget* parent, const QFileInfo& file);
/// Get the context menu name for the action performed by ShowInFileExplorer
QString GetShowInFileExplorerMessage();
/// Opens a URL with the default handler.
void OpenURL(QWidget* parent, const QUrl& qurl);