From b7f6bd4c9121deba08f590a174522840962efe63 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 6 Oct 2017 21:13:59 +0200 Subject: [PATCH] Qt: extend drag and drop to mainwindow --- rpcs3/rpcs3qt/game_list_frame.cpp | 179 ---------------------------- rpcs3/rpcs3qt/game_list_frame.h | 18 --- rpcs3/rpcs3qt/main_window.cpp | 192 ++++++++++++++++++++++++++++-- rpcs3/rpcs3qt/main_window.h | 17 +++ 4 files changed, 199 insertions(+), 207 deletions(-) diff --git a/rpcs3/rpcs3qt/game_list_frame.cpp b/rpcs3/rpcs3qt/game_list_frame.cpp index b3d6acc5e9..3db80303ff 100644 --- a/rpcs3/rpcs3qt/game_list_frame.cpp +++ b/rpcs3/rpcs3qt/game_list_frame.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include inline std::string sstr(const QString& _in) { return _in.toUtf8().toStdString(); } @@ -32,8 +31,6 @@ inline QSize sizeFromSlider(const int& pos) { return GUI::gl_icon_size_min + (GU game_list_frame::game_list_frame(std::shared_ptr guiSettings, std::shared_ptr emuSettings, QWidget *parent) : QDockWidget(tr("Game List"), parent), xgui_settings(guiSettings), xemu_settings(emuSettings) { - setAcceptDrops(true); - m_isListLayout = xgui_settings->GetValue(GUI::gl_listMode).toBool(); m_icon_size_index = xgui_settings->GetValue(GUI::gl_iconSize).toInt(); m_Margin_Factor = xgui_settings->GetValue(GUI::gl_marginFactor).toReal(); @@ -1169,179 +1166,3 @@ std::string game_list_frame::GetStringFromU32(const u32& key, const std::map list = md.urls(); // get list of all the dropped file urls - - for (auto&& url : list) // check each file in url list for valid type - { - const QString path = url.toLocalFile(); // convert url to filepath - - const QFileInfo info = path; - - // check for directories first, only valid if all other paths led to directories until now. - if (info.isDir()) - { - if (dropType != DROP_DIR && dropType != DROP_ERROR) - { - return DROP_ERROR; - } - - dropType = DROP_DIR; - } - else if (info.fileName() == "PS3UPDAT.PUP") - { - if (list.size() != 1) - { - return DROP_ERROR; - } - - dropType = DROP_PUP; - } - else if (info.suffix().toLower() == "pkg") - { - if (dropType != DROP_PKG && dropType != DROP_ERROR) - { - return DROP_ERROR; - } - - dropType = DROP_PKG; - } - else if (info.suffix() == "rap") - { - if (dropType != DROP_RAP && dropType != DROP_ERROR) - { - return DROP_ERROR; - } - - dropType = DROP_RAP; - } - else if (list.size() == 1) - { - dropType = DROP_GAME; - } - else - { - return DROP_ERROR; - } - - if (dropPaths) // we only need to know the paths on drop - { - dropPaths->append(path); - } - } - - return dropType; -} - -void game_list_frame::dropEvent(QDropEvent* event) -{ - QStringList dropPaths; - - switch (IsValidFile(*event->mimeData(), &dropPaths)) // get valid file paths and drop type - { - case DROP_ERROR: - break; - case DROP_PKG: // install the package - Q_EMIT RequestPackageInstall(dropPaths); - break; - case DROP_PUP: // install the firmware - Q_EMIT RequestFirmwareInstall(dropPaths.first()); - break; - case DROP_RAP: // import rap files to exdata dir - for (const auto& rap : dropPaths) - { - const std::string rapname = sstr(QFileInfo(rap).fileName()); - - // TODO: use correct user ID once User Manager is implemented - if (!fs::copy_file(sstr(rap), fmt::format("%s/home/%s/exdata/%s", Emu.GetHddDir(), "00000001", rapname), false)) - { - LOG_WARNING(GENERAL, "Could not copy rap file by drop: %s", rapname); - } - else - { - LOG_SUCCESS(GENERAL, "Successfully copied rap file by drop: %s", rapname); - } - } - break; - case DROP_DIR: // import valid games to gamelist (games.yaml) - for (const auto& path : dropPaths) - { - AddGamesFromDir(path); - } - Refresh(true); - break; - case DROP_GAME: // import valid games to gamelist (games.yaml) - if (Emu.BootGame(sstr(dropPaths.first()), true)) - { - LOG_SUCCESS(GENERAL, "Elf Boot from drag and drop done: %s", sstr(dropPaths.first())); - } - Refresh(true); - break; - default: - LOG_WARNING(GENERAL, "Invalid dropType in gamelist dropEvent"); - break; - } -} - -void game_list_frame::dragEnterEvent(QDragEnterEvent* event) -{ - if (IsValidFile(*event->mimeData())) - { - event->accept(); - } -} - -void game_list_frame::dragMoveEvent(QDragMoveEvent* event) -{ - if (IsValidFile(*event->mimeData())) - { - event->accept(); - } -} - -void game_list_frame::dragLeaveEvent(QDragLeaveEvent* event) -{ - event->accept(); -} diff --git a/rpcs3/rpcs3qt/game_list_frame.h b/rpcs3/rpcs3qt/game_list_frame.h index 7ecb36f551..7f42022fde 100644 --- a/rpcs3/rpcs3qt/game_list_frame.h +++ b/rpcs3/rpcs3qt/game_list_frame.h @@ -178,16 +178,6 @@ struct Tool_Bar_Button bool isActive; }; -enum -{ - DROP_ERROR, - DROP_PKG, - DROP_PUP, - DROP_RAP, - DROP_DIR, - DROP_GAME -}; - class game_list_frame : public QDockWidget { Q_OBJECT @@ -242,16 +232,10 @@ Q_SIGNALS: void RequestListModeActSet(const bool& isList); void RequestCategoryActSet(const int& id); void RequestSaveSliderPos(const bool& save); - void RequestPackageInstall(const QStringList& paths); - void RequestFirmwareInstall(const QString& path); protected: /** Override inherited method from Qt to allow signalling when close happened.*/ void closeEvent(QCloseEvent* event) override; void resizeEvent(QResizeEvent *event) override; - void dropEvent(QDropEvent* event) override; - void dragEnterEvent(QDragEnterEvent* event) override; - void dragMoveEvent(QDragMoveEvent* event) override; - void dragLeaveEvent(QDragLeaveEvent* event) override; private: QPixmap PaintedPixmap(const QImage& img, bool paintConfigIcon = false); bool Boot(const GameInfo& info); @@ -261,8 +245,6 @@ private: int PopulateGameList(); bool SearchMatchesApp(const std::string& name, const std::string& serial); - int IsValidFile(const QMimeData& md, QStringList* dropPaths = nullptr); - void AddGamesFromDir(const QString& path); std::string CurrentSelectionIconPath(); std::string GetStringFromU32(const u32& key, const std::map& map, bool combined = false); diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index 73e1049bc0..aa96d9fc5f 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "vfs_dialog.h" #include "save_manager_dialog.h" @@ -72,6 +73,8 @@ void main_window::Init() { ui->setupUi(this); + setAcceptDrops(true); + m_appIcon = QIcon(":/rpcs3.ico"); // hide utilities from the average user @@ -1488,16 +1491,6 @@ void main_window::CreateDockWindows() connect(m_gameListFrame, &game_list_frame::RequestIconPathSet, this, &main_window::SetAppIconFromPath); connect(m_gameListFrame, &game_list_frame::RequestAddRecentGame, this, &main_window::AddRecentAction); - - connect(m_gameListFrame, &game_list_frame::RequestPackageInstall, [this](const QStringList& paths) - { - for (const auto& path : paths) - { - InstallPkg(path); - } - }); - - connect(m_gameListFrame, &game_list_frame::RequestFirmwareInstall, this, &main_window::InstallPup); } void main_window::ConfigureGuiFromSettings(bool configureAll) @@ -1642,3 +1635,182 @@ void main_window::closeEvent(QCloseEvent* closeEvent) // It's possible to have other windows open, like games. So, force the application to die. QApplication::quit(); } + +/** +Add valid disc games to gamelist (games.yml) +@param path = dir path to scan for game +*/ +void main_window::AddGamesFromDir(const QString& path) +{ + if (!QFileInfo(path).isDir()) return; + + const std::string s_path = sstr(path); + + // search dropped path first or else the direct parent to an elf is wrongly skipped + if (Emu.BootGame(s_path, false, true)) + { + LOG_NOTICE(GENERAL, "Returned from game addition by drag and drop: %s", s_path); + } + + // search direct subdirectories, that way we can drop one folder containing all games + for (const auto& entry : fs::dir(s_path)) + { + if (entry.name == "." || entry.name == "..") continue; + + const std::string pth = s_path + "/" + entry.name; + + if (!QFileInfo(qstr(pth)).isDir()) continue; + + if (Emu.BootGame(pth, false, true)) + { + LOG_NOTICE(GENERAL, "Returned from game addition by drag and drop: %s", pth); + } + } +} + +/** +Check data for valid file types and cache their paths if necessary +@param md = data containing file urls +@param savePaths = flag for path caching +@returns validity of file type +*/ +int main_window::IsValidFile(const QMimeData& md, QStringList* dropPaths) +{ + int dropType = DROP_ERROR; + + const QList list = md.urls(); // get list of all the dropped file urls + + for (auto&& url : list) // check each file in url list for valid type + { + const QString path = url.toLocalFile(); // convert url to filepath + + const QFileInfo info = path; + + // check for directories first, only valid if all other paths led to directories until now. + if (info.isDir()) + { + if (dropType != DROP_DIR && dropType != DROP_ERROR) + { + return DROP_ERROR; + } + + dropType = DROP_DIR; + } + else if (info.fileName() == "PS3UPDAT.PUP") + { + if (list.size() != 1) + { + return DROP_ERROR; + } + + dropType = DROP_PUP; + } + else if (info.suffix().toLower() == "pkg") + { + if (dropType != DROP_PKG && dropType != DROP_ERROR) + { + return DROP_ERROR; + } + + dropType = DROP_PKG; + } + else if (info.suffix() == "rap") + { + if (dropType != DROP_RAP && dropType != DROP_ERROR) + { + return DROP_ERROR; + } + + dropType = DROP_RAP; + } + else if (list.size() == 1) + { + dropType = DROP_GAME; + } + else + { + return DROP_ERROR; + } + + if (dropPaths) // we only need to know the paths on drop + { + dropPaths->append(path); + } + } + + return dropType; +} + +void main_window::dropEvent(QDropEvent* event) +{ + QStringList dropPaths; + + switch (IsValidFile(*event->mimeData(), &dropPaths)) // get valid file paths and drop type + { + case DROP_ERROR: + break; + case DROP_PKG: // install the packages + for (const auto& path : dropPaths) + { + InstallPkg(path); + } + break; + case DROP_PUP: // install the firmware + InstallPup(dropPaths.first()); + break; + case DROP_RAP: // import rap files to exdata dir + for (const auto& rap : dropPaths) + { + const std::string rapname = sstr(QFileInfo(rap).fileName()); + + // TODO: use correct user ID once User Manager is implemented + if (!fs::copy_file(sstr(rap), fmt::format("%s/home/%s/exdata/%s", Emu.GetHddDir(), "00000001", rapname), false)) + { + LOG_WARNING(GENERAL, "Could not copy rap file by drop: %s", rapname); + } + else + { + LOG_SUCCESS(GENERAL, "Successfully copied rap file by drop: %s", rapname); + } + } + break; + case DROP_DIR: // import valid games to gamelist (games.yaml) + for (const auto& path : dropPaths) + { + AddGamesFromDir(path); + } + m_gameListFrame->Refresh(true); + break; + case DROP_GAME: // import valid games to gamelist (games.yaml) + if (Emu.BootGame(sstr(dropPaths.first()), true)) + { + LOG_SUCCESS(GENERAL, "Elf Boot from drag and drop done: %s", sstr(dropPaths.first())); + } + m_gameListFrame->Refresh(true); + break; + default: + LOG_WARNING(GENERAL, "Invalid dropType in gamelist dropEvent"); + break; + } +} + +void main_window::dragEnterEvent(QDragEnterEvent* event) +{ + if (IsValidFile(*event->mimeData())) + { + event->accept(); + } +} + +void main_window::dragMoveEvent(QDragMoveEvent* event) +{ + if (IsValidFile(*event->mimeData())) + { + event->accept(); + } +} + +void main_window::dragLeaveEvent(QDragLeaveEvent* event) +{ + event->accept(); +} diff --git a/rpcs3/rpcs3qt/main_window.h b/rpcs3/rpcs3qt/main_window.h index a831b7abbf..b64b28e30b 100644 --- a/rpcs3/rpcs3qt/main_window.h +++ b/rpcs3/rpcs3qt/main_window.h @@ -55,6 +55,16 @@ class main_window : public QMainWindow QStringList m_d3d12_adapters; #endif + enum + { + DROP_ERROR, + DROP_PKG, + DROP_PUP, + DROP_RAP, + DROP_DIR, + DROP_GAME + }; + public: explicit main_window(std::shared_ptr guiSettings, std::shared_ptr emuSettings, QWidget *parent = 0); void Init(); @@ -85,6 +95,10 @@ protected: void closeEvent(QCloseEvent *event) override; void keyPressEvent(QKeyEvent *keyEvent) override; void mouseDoubleClickEvent(QMouseEvent *event) override; + void dropEvent(QDropEvent* event) override; + void dragEnterEvent(QDragEnterEvent* event) override; + void dragMoveEvent(QDragMoveEvent* event) override; + void dragLeaveEvent(QDragLeaveEvent* event) override; void SetAppIconFromPath(const std::string path); private: void RepaintToolbar(); @@ -98,6 +112,9 @@ private: void InstallPkg(const QString& dropPath = ""); void InstallPup(const QString& dropPath = ""); + int IsValidFile(const QMimeData& md, QStringList* dropPaths = nullptr); + void AddGamesFromDir(const QString& path); + QAction* CreateRecentAction(const q_string_pair& entry, const uint& sc_idx); void BootRecentAction(const QAction* act); void AddRecentAction(const q_string_pair& entry);