265 lines
8.9 KiB
C++
265 lines
8.9 KiB
C++
#include "stdafx.h"
|
|
#include "FileBrowserWindow.h"
|
|
#include "SandMan.h"
|
|
#include "../MiscHelpers/Common/Settings.h"
|
|
#include "../MiscHelpers/Common/TreeItemModel.h"
|
|
#include "../MiscHelpers/Common/OtherFunctions.h"
|
|
#include "../QSbieAPI/SbieUtils.h"
|
|
|
|
CFileBrowserWindow::CFileBrowserWindow(const CSandBoxPtr& pBox, QWidget *parent)
|
|
: QDialog(parent)
|
|
{
|
|
Qt::WindowFlags flags = windowFlags();
|
|
flags |= Qt::CustomizeWindowHint;
|
|
//flags &= ~Qt::WindowContextHelpButtonHint;
|
|
//flags &= ~Qt::WindowSystemMenuHint;
|
|
//flags &= ~Qt::WindowMinMaxButtonsHint;
|
|
flags |= Qt::WindowMinimizeButtonHint;
|
|
//flags &= ~Qt::WindowCloseButtonHint;
|
|
setWindowFlags(flags);
|
|
|
|
bool bAlwaysOnTop = theConf->GetBool("Options/AlwaysOnTop", false);
|
|
this->setWindowFlag(Qt::WindowStaysOnTopHint, bAlwaysOnTop);
|
|
|
|
ui.setupUi(this);
|
|
this->setWindowTitle(tr("%1 - Files").arg(pBox->GetName()));
|
|
|
|
m_pBox = pBox;
|
|
|
|
m_pFileModel = new QFileSystemModel(this);
|
|
m_pFileModel->setFilter(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files | QDir::Hidden | QDir::System);
|
|
m_pFileModel->setRootPath(pBox->GetFileRoot());
|
|
ui.treeFiles->setModel(m_pFileModel);
|
|
ui.treeFiles->setRootIndex(m_pFileModel->setRootPath(pBox->GetFileRoot()));
|
|
ui.treeFiles->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
|
|
#ifdef WIN32
|
|
QStyle* pStyle = QStyleFactory::create("windows");
|
|
ui.treeFiles->setStyle(pStyle);
|
|
#endif
|
|
ui.treeFiles->setExpandsOnDoubleClick(false);
|
|
|
|
ui.treeFiles->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
connect(ui.treeFiles, SIGNAL(customContextMenuRequested( const QPoint& )), this, SLOT(OnFileMenu(const QPoint &)));
|
|
connect(ui.treeFiles, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(OnFileDblClick(const QModelIndex &)));
|
|
|
|
//statusBar();
|
|
|
|
restoreGeometry(theConf->GetBlob("FileBrowserWindow/Window_Geometry"));
|
|
QByteArray Columns = theConf->GetBlob("FileBrowserWindow/FileTree_Columns");
|
|
if (!Columns.isEmpty())
|
|
ui.treeFiles->header()->restoreState(Columns);
|
|
}
|
|
|
|
CFileBrowserWindow::~CFileBrowserWindow()
|
|
{
|
|
theConf->SetBlob("FileBrowserWindow/Window_Geometry",saveGeometry());
|
|
theConf->SetBlob("FileBrowserWindow/FileTree_Columns", ui.treeFiles->header()->saveState());
|
|
}
|
|
|
|
void CFileBrowserWindow::closeEvent(QCloseEvent *e)
|
|
{
|
|
emit Closed();
|
|
this->deleteLater();
|
|
}
|
|
|
|
|
|
#include <windows.h>
|
|
#include <Shlobj.h>
|
|
#include <atlbase.h>
|
|
|
|
#define MENU_RECOVER 1
|
|
#define MENU_RECOVER_TO_ANY 2
|
|
#define MENU_CREATE_SHORTCUT 3
|
|
|
|
void addSeparatorToShellContextMenu(HMENU hMenu)
|
|
{
|
|
MENUITEMINFO menu_item_info;
|
|
memset(&menu_item_info, 0, sizeof(MENUITEMINFO));
|
|
menu_item_info.cbSize = sizeof(MENUITEMINFO);
|
|
menu_item_info.fType = MFT_SEPARATOR;
|
|
menu_item_info.wID = 0;
|
|
InsertMenuItem(hMenu, 0, TRUE, &menu_item_info);
|
|
}
|
|
|
|
void addItemToShellContextMenu(HMENU hMenu, const wchar_t *name, int ID)
|
|
{
|
|
MENUITEMINFO menu_item_info;
|
|
memset(&menu_item_info, 0, sizeof(MENUITEMINFO));
|
|
menu_item_info.cbSize = sizeof(MENUITEMINFO);
|
|
menu_item_info.fMask = MIIM_ID | MIIM_STRING | MIIM_DATA;
|
|
menu_item_info.wID = 0xF000 + ID;
|
|
menu_item_info.dwTypeData = (wchar_t*)name;
|
|
InsertMenuItem(hMenu, 0, TRUE, &menu_item_info);
|
|
}
|
|
|
|
int openShellContextMenu(const QStringList& Files, void * parentWindow)
|
|
{
|
|
std::list<CComHeapPtr<ITEMIDLIST_ABSOLUTE>> items;
|
|
items.resize(Files.count());
|
|
auto IT = items.begin();
|
|
foreach(QString File, Files) {
|
|
CComPtr<IShellItem> item;
|
|
SHCreateItemFromParsingName(File.toStdWString().c_str(), NULL, IID_PPV_ARGS(&item));
|
|
CComQIPtr<IPersistIDList> idl(item);
|
|
idl->GetIDList(&*IT++);
|
|
}
|
|
|
|
std::vector<LPCITEMIDLIST> list;
|
|
list.resize(items.size());
|
|
LPCITEMIDLIST* listPtr = &list.front();
|
|
for (auto I = items.begin(); I != items.end(); I++)
|
|
*listPtr++ = *I;
|
|
CComPtr<IShellItemArray> array;
|
|
SHCreateShellItemArrayFromIDLists(list.size(), &list.front(), &array);
|
|
|
|
|
|
CComPtr<IContextMenu> menu;
|
|
array->BindToHandler(NULL, BHID_SFUIObject, IID_PPV_ARGS(&menu));
|
|
if (!menu)
|
|
return 0;
|
|
|
|
HMENU hMenu = CreatePopupMenu();
|
|
if (!hMenu)
|
|
return 0;
|
|
if (SUCCEEDED(menu->QueryContextMenu(hMenu, 0, 1, 0x7FFF, CMF_NORMAL)))
|
|
{
|
|
addSeparatorToShellContextMenu(hMenu);
|
|
|
|
std::wstring Str1 = CFileBrowserWindow::tr("Create Shortcut").toStdWString();
|
|
if (Files.count() == 1) {
|
|
addItemToShellContextMenu(hMenu, Str1.c_str(), MENU_CREATE_SHORTCUT);
|
|
addSeparatorToShellContextMenu(hMenu);
|
|
}
|
|
|
|
std::wstring Str2 = CFileBrowserWindow::tr("Recover to Any Folder").toStdWString();
|
|
addItemToShellContextMenu(hMenu, Str2.c_str(), MENU_RECOVER_TO_ANY);
|
|
std::wstring Str3 = CFileBrowserWindow::tr("Recover to Same Folder").toStdWString();
|
|
addItemToShellContextMenu(hMenu, Str3.c_str(), MENU_RECOVER);
|
|
|
|
POINT point;
|
|
GetCursorPos(&point);
|
|
int iCmd = TrackPopupMenuEx(hMenu, TPM_RETURNCMD, point.x, point.y, (HWND)parentWindow, NULL);
|
|
if (iCmd > 0)
|
|
{
|
|
if ((iCmd & 0xF000) == 0xF000) {
|
|
DestroyMenu(hMenu);
|
|
return iCmd & 0x0FFF;
|
|
}
|
|
|
|
CMINVOKECOMMANDINFOEX info = { 0 };
|
|
info.cbSize = sizeof(info);
|
|
info.fMask = CMIC_MASK_UNICODE;
|
|
info.hwnd = (HWND)parentWindow;
|
|
info.lpVerb = MAKEINTRESOURCEA(iCmd - 1);
|
|
info.lpVerbW = MAKEINTRESOURCEW(iCmd - 1);
|
|
info.nShow = SW_SHOWNORMAL;
|
|
menu->InvokeCommand((LPCMINVOKECOMMANDINFO)&info);
|
|
}
|
|
}
|
|
DestroyMenu(hMenu);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void CFileBrowserWindow::OnFileMenu(const QPoint&)
|
|
{
|
|
QStringList Files;
|
|
foreach(const QModelIndex & Index, ui.treeFiles->selectionModel()->selectedIndexes()) {
|
|
QString BoxedPath = m_pFileModel->fileInfo(Index).absoluteFilePath().replace("/", "\\");
|
|
if (m_pFileModel->fileInfo(Index).isDir())
|
|
BoxedPath += "\\";
|
|
|
|
bool bFound = false;
|
|
foreach(const QString & File, Files) {
|
|
if (BoxedPath.contains(File))
|
|
bFound = true;
|
|
else if (File.contains(BoxedPath))
|
|
Files.removeOne(File);
|
|
}
|
|
|
|
if(!bFound)
|
|
Files.append(BoxedPath);
|
|
}
|
|
|
|
if (Files.isEmpty())
|
|
return;
|
|
|
|
int iCmd = openShellContextMenu(Files, (void*)this->winId());
|
|
if (iCmd == 0)
|
|
return;
|
|
|
|
QString RecoveryFolder;
|
|
switch (iCmd)
|
|
{
|
|
case MENU_RECOVER_TO_ANY:
|
|
RecoveryFolder = QFileDialog::getExistingDirectory(this, CFileBrowserWindow::tr("Select Directory")).replace("/", "\\");
|
|
if (RecoveryFolder.isEmpty())
|
|
break;
|
|
case MENU_RECOVER:
|
|
{
|
|
QStringList AllFiles;
|
|
foreach(const QString& File, Files)
|
|
{
|
|
if (File.right(1) == "\\") {
|
|
foreach(QString SubFile, ListDir(File))
|
|
AllFiles.append(File + SubFile.replace("/", "\\"));
|
|
}
|
|
else
|
|
AllFiles.append(File);
|
|
}
|
|
|
|
QList<QPair<QString, QString>> FileList;
|
|
foreach(QString BoxedPath, AllFiles)
|
|
{
|
|
if (!RecoveryFolder.isEmpty()) {
|
|
QString FileName = BoxedPath.mid(BoxedPath.lastIndexOf("\\") + 1);
|
|
FileList.append(qMakePair(BoxedPath, RecoveryFolder + "\\" + FileName));
|
|
}
|
|
else {
|
|
QString RealPath = theAPI->GetRealPath(m_pBox, BoxedPath);
|
|
FileList.append(qMakePair(BoxedPath, RealPath));
|
|
}
|
|
}
|
|
|
|
SB_PROGRESS Status = theGUI->RecoverFiles(FileList, 0);
|
|
if (Status.GetStatus() == OP_ASYNC)
|
|
theGUI->AddAsyncOp(Status.GetValue());
|
|
|
|
break;
|
|
}
|
|
case MENU_CREATE_SHORTCUT:
|
|
{
|
|
QString BoxName = m_pBox->GetName();
|
|
QString LinkPath = Files.first();
|
|
QString LinkName = LinkPath.mid(LinkPath.lastIndexOf("\\") + 1);
|
|
|
|
QString Path = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).replace("/", "\\");
|
|
//Path = QFileDialog::getExistingDirectory(this, tr("Select Directory to create Shorcut in"), Path).replace("/", "\\");
|
|
//if (Path.isEmpty())
|
|
// return;
|
|
|
|
if (Path.right(1) != "\\")
|
|
Path.append("\\");
|
|
Path += "[" + BoxName + "] " + LinkName;
|
|
|
|
Path = QFileDialog::getSaveFileName(this, tr("Create Shortcut to sandbox %1").arg(BoxName), Path, QString("Shortcut files (*.lnk)")).replace("/", "\\");
|
|
if (Path.isEmpty())
|
|
return;
|
|
|
|
CSbieUtils::CreateShortcut(theAPI, Path, LinkName, BoxName, LinkPath, LinkPath);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void CFileBrowserWindow::OnFileDblClick(const QModelIndex &)
|
|
{
|
|
QString BoxedPath = m_pFileModel->fileInfo(ui.treeFiles->currentIndex()).absoluteFilePath();
|
|
|
|
ShellExecute(NULL, NULL, BoxedPath.toStdWString().c_str(), NULL, m_pBox->GetFileRoot().toStdWString().c_str(), SW_SHOWNORMAL);
|
|
}
|