From d0be8a0d3b8c021e3efda0041ebb55eae25dbfde Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Tue, 21 Jan 2020 23:51:08 -0500 Subject: ShellMenu class --- src/envshell.cpp | 123 +++++++++++++++++++++++++++---------------------------- src/envshell.h | 26 +++++++++--- src/filetree.cpp | 6 +-- 3 files changed, 85 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/envshell.cpp b/src/envshell.cpp index dcf337c5..1f9c4032 100644 --- a/src/envshell.cpp +++ b/src/envshell.cpp @@ -1,5 +1,4 @@ #include "envshell.h" -#include "env.h" #include #include #include @@ -209,7 +208,56 @@ private: -QMainWindow* getMainWindow(QWidget* w) +void ShellMenu::addFile(QFileInfo fi) +{ + m_files.emplace_back(std::move(fi)); +} + +void ShellMenu::exec(QWidget* parent, const QPoint& pos) +{ + if (m_files.empty()) { + log::warn("showShellMenu(): no files given"); + return; + } + + try + { + auto* mw = getMainWindow(parent); + auto idls = createIdls(m_files); + + if (idls.empty()) { + log::error("no idls, can't create context menu"); + return; + } + + IdlsFreer freer(idls); + + auto array = createItemArray(idls); + auto cm = createContextMenu(array.get()); + auto hmenu = createMenu(cm.get()); + + const int cmd = runMenu(mw, cm.get(), hmenu.get(), pos); + if (cmd <= 0) { + return; + } + + invoke(mw, pos, cmd - QCM_FIRST, cm.get()); + } + catch(MenuFailed& e) + { + if (m_files.size() == 1) { + log::error( + "can't create shell menu for '{}': {}", + QDir::toNativeSeparators(m_files[0].absoluteFilePath()), e.what()); + } else { + log::error( + "can't create shell menu for {} files: {}", + m_files.size(), e.what()); + } + } +} + +QMainWindow* ShellMenu::getMainWindow(QWidget* w) { QWidget* p = w; @@ -224,7 +272,7 @@ QMainWindow* getMainWindow(QWidget* w) return nullptr; } -COMPtr createShellItem(const std::wstring& path) +COMPtr ShellMenu::createShellItem(const std::wstring& path) { IShellItem* item = nullptr; @@ -238,7 +286,7 @@ COMPtr createShellItem(const std::wstring& path) return COMPtr(item); } -COMPtr getPersistIDList(IShellItem* item) +COMPtr ShellMenu::getPersistIDList(IShellItem* item) { IPersistIDList* idl = nullptr; auto r = item->QueryInterface(IID_IPersistIDList, (void**)&idl); @@ -250,7 +298,7 @@ COMPtr getPersistIDList(IShellItem* item) return COMPtr(idl); } -CoTaskMemPtr getIDList(IPersistIDList* pidlist) +CoTaskMemPtr ShellMenu::getIDList(IPersistIDList* pidlist) { LPITEMIDLIST absIdl = nullptr; auto r = pidlist->GetIDList(&absIdl); @@ -262,7 +310,7 @@ CoTaskMemPtr getIDList(IPersistIDList* pidlist) return CoTaskMemPtr(absIdl); } -std::vector createIdls( +std::vector ShellMenu::createIdls( const std::vector& files) { std::vector idls; @@ -280,7 +328,7 @@ std::vector createIdls( return idls; } -COMPtr createItemArray( +COMPtr ShellMenu::createItemArray( std::vector& idls) { IShellItemArray* array = nullptr; @@ -294,7 +342,7 @@ COMPtr createItemArray( return COMPtr(array); } -COMPtr createContextMenu(IShellItemArray* array) +COMPtr ShellMenu::createContextMenu(IShellItemArray* array) { IContextMenu* cm = nullptr; @@ -308,7 +356,7 @@ COMPtr createContextMenu(IShellItemArray* array) return COMPtr(cm); } -HMenuPtr createMenu(IContextMenu* cm) +HMenuPtr ShellMenu::createMenu(IContextMenu* cm) { HMENU hmenu = CreatePopupMenu(); if (!hmenu) { @@ -326,7 +374,8 @@ HMenuPtr createMenu(IContextMenu* cm) return HMenuPtr(hmenu); } -int runMenu(QMainWindow* mw, IContextMenu* cm, HMENU menu, const QPoint& p) +int ShellMenu::runMenu( + QMainWindow* mw, IContextMenu* cm, HMENU menu, const QPoint& p) { const auto hwnd = (HWND)mw->winId(); @@ -336,7 +385,8 @@ int runMenu(QMainWindow* mw, IContextMenu* cm, HMENU menu, const QPoint& p) return TrackPopupMenuEx(menu, TPM_RETURNCMD, p.x(), p.y(), hwnd, nullptr); } -void invoke(QMainWindow* mw, const QPoint& p, int cmd, IContextMenu* cm) +void ShellMenu::invoke( + QMainWindow* mw, const QPoint& p, int cmd, IContextMenu* cm) { const auto hwnd = (HWND)mw->winId(); @@ -369,55 +419,4 @@ void invoke(QMainWindow* mw, const QPoint& p, int cmd, IContextMenu* cm) } } - -void showShellMenu( - QWidget* parent, const std::vector& files, const QPoint& pos) -{ - if (files.empty()) { - log::warn("showShellMenu(): no files given"); - return; - } - - try - { - auto* mw = getMainWindow(parent); - auto idls = createIdls(files); - - if (idls.empty()) { - log::error("no idls, can't create context menu"); - return; - } - - IdlsFreer freer(idls); - - auto array = createItemArray(idls); - auto cm = createContextMenu(array.get()); - auto hmenu = createMenu(cm.get()); - - const int cmd = runMenu(mw, cm.get(), hmenu.get(), pos); - if (cmd <= 0) { - return; - } - - invoke(mw, pos, cmd - QCM_FIRST, cm.get()); - } - catch(MenuFailed& e) - { - if (files.size() == 1) { - log::error( - "can't create shell menu for '{}': {}", - QDir::toNativeSeparators(files[0].absoluteFilePath()), e.what()); - } else { - log::error( - "can't create shell menu for {} files: {}", - files.size(), e.what()); - } - } -} - -void showShellMenu(QWidget* parent, const QFileInfo& file, const QPoint& pos) -{ - showShellMenu(parent, std::vector{file}, pos); -} - } // namespace diff --git a/src/envshell.h b/src/envshell.h index 3be53841..3e694562 100644 --- a/src/envshell.h +++ b/src/envshell.h @@ -1,18 +1,34 @@ #ifndef ENV_SHELL_H #define ENV_SHELL_H +#include "env.h" #include #include namespace env { -void showShellMenu( - QWidget* parent, const QFileInfo& file, const QPoint& pos); +class ShellMenu +{ +public: + void addFile(QFileInfo fi); + void exec(QWidget* parent, const QPoint& pos); + +private: + std::vector m_files; -void showShellMenu( - QWidget* parent, const std::vector& files, const QPoint& pos); + QMainWindow* getMainWindow(QWidget* w); + COMPtr createShellItem(const std::wstring& path); + COMPtr getPersistIDList(IShellItem* item); + CoTaskMemPtr getIDList(IPersistIDList* pidlist); + std::vector createIdls(const std::vector& files); + COMPtr createItemArray(std::vector& idls); + COMPtr createContextMenu(IShellItemArray* array); + HMenuPtr createMenu(IContextMenu* cm); + int runMenu(QMainWindow* mw, IContextMenu* cm, HMENU menu, const QPoint& p); + void invoke(QMainWindow* mw, const QPoint& p, int cmd, IContextMenu* cm); +}; -} +} // namespace #endif // ENV_SHELL_H diff --git a/src/filetree.cpp b/src/filetree.cpp index d7dbc6e6..404c994b 100644 --- a/src/filetree.cpp +++ b/src/filetree.cpp @@ -468,7 +468,7 @@ void FileTree::onContextMenu(const QPoint &pos) void FileTree::showShellMenu(QPoint pos) { - std::vector files; + env::ShellMenu menu; for (auto&& index : m_tree->selectionModel()->selectedRows()) { auto* item = m_model->itemFromIndex(index); @@ -476,10 +476,10 @@ void FileTree::showShellMenu(QPoint pos) continue; } - files.push_back(item->realPath()); + menu.addFile(item->realPath()); } - env::showShellMenu(m_tree, files, m_tree->viewport()->mapToGlobal(pos)); + menu.exec(m_tree, m_tree->viewport()->mapToGlobal(pos)); } void FileTree::addDirectoryMenus(QMenu&, FileTreeItem&) -- cgit v1.3.1