add cut/copy/paste function for local files

This commit is contained in:
Chee Yee
2023-02-11 18:52:36 -08:00
parent 11f7f2eb25
commit d5a850dd10
10 changed files with 417 additions and 49 deletions
+9
View File
@@ -95,3 +95,12 @@ STR_ZIP_FILE_PATH=Zip Filename
STR_COMPRESSING=Compressing
STR_ERROR_CREATE_ZIP=Error occured while creating zip
STR_UNSUPPORTED_FILE_FORMAT=Unsupported compressed file format
STR_CUT=Cut
STR_COPY=Copy
STR_PASTE=Paste
STR_MOVING=Moving
STR_COPYING=Copying
STR_FAIL_MOVE_MSG=Failed to move file
STR_FAIL_MOVE_MSG=Failed to copy file
STR_CANT_MOVE_TO_SUBDIR_MSG=Cannot move parent directory to sub subdirectory
STR_CANT_COPY_TO_SUBDIR_MSG=Cannot copy parent directory to sub subdirectory
+205 -2
View File
@@ -19,6 +19,7 @@
#include "smbclient.h"
#include "webdavclient.h"
#include "zip_util.h"
#include "dbglogger.h"
namespace Actions
{
@@ -52,7 +53,7 @@ namespace Actions
{
local_files = FS::ListDir(local_directory, &err);
}
FS::Sort(local_files);
DirEntry::Sort(local_files);
if (err != 0)
sprintf(status_message, "%s", lang_strings[STR_FAIL_READ_LOCAL_DIR_MSG]);
}
@@ -88,7 +89,7 @@ namespace Actions
{
remote_files = remoteclient->ListDir(remote_directory);
}
FS::Sort(remote_files);
DirEntry::Sort(remote_files);
}
void HandleChangeLocalDirectory(const DirEntry entry)
@@ -1158,4 +1159,206 @@ namespace Actions
}
return NULL;
}
int CopyOrMoveFile(const char *src, const char *dest, bool isCopy)
{
int ret;
if (overwrite_type == OVERWRITE_PROMPT && FS::FileExists(dest))
{
sprintf(confirm_message, "%s %s?", lang_strings[STR_OVERWRITE], dest);
confirm_state = CONFIRM_WAIT;
action_to_take = selected_action;
activity_inprogess = false;
while (confirm_state == CONFIRM_WAIT)
{
sceKernelUsleep(100000);
}
activity_inprogess = true;
selected_action = action_to_take;
}
else if (overwrite_type == OVERWRITE_NONE && FS::FileExists(dest))
{
confirm_state = CONFIRM_NO;
}
else
{
confirm_state = CONFIRM_YES;
}
if (confirm_state == CONFIRM_YES)
{
if (isCopy)
return FS::Copy(src, dest);
else
return FS::Move(src, dest);
}
return 1;
}
int CopyOrMove(const DirEntry &src, const char *dest, bool isCopy)
{
if (stop_activity)
return 1;
int ret;
if (src.isDir)
{
int err;
std::vector<DirEntry> entries = FS::ListDir(src.path, &err);
FS::MkDirs(dest, true);
for (int i = 0; i < entries.size(); i++)
{
if (stop_activity)
return 1;
int path_length = strlen(dest) + strlen(entries[i].name) + 2;
char *new_path = (char *)malloc(path_length);
snprintf(new_path, path_length, "%s%s%s", dest, FS::hasEndSlash(dest) ? "" : "/", entries[i].name);
if (entries[i].isDir)
{
if (strcmp(entries[i].name, "..") == 0)
continue;
FS::MkDirs(new_path, true);
ret = CopyOrMove(entries[i], new_path, isCopy);
if (ret <= 0)
{
free(new_path);
return ret;
}
}
else
{
snprintf(activity_message, 1024, "%s %s", isCopy ? lang_strings[STR_COPYING] : lang_strings[STR_MOVING], entries[i].path);
bytes_to_download = entries[i].file_size;
bytes_transfered = 0;
ret = CopyOrMoveFile(entries[i].path, new_path, isCopy);
if (ret <= 0)
{
sprintf(status_message, "%s %s", isCopy ? lang_strings[STR_FAIL_COPY_MSG] : lang_strings[STR_FAIL_MOVE_MSG], entries[i].path);
free(new_path);
return ret;
}
}
if (!isCopy)
FS::RmDir(src.path);
free(new_path);
}
}
else
{
int path_length = strlen(dest) + strlen(src.name) + 2;
char *new_path = (char *)malloc(path_length);
snprintf(new_path, path_length, "%s%s%s", dest, FS::hasEndSlash(dest) ? "" : "/", src.name);
snprintf(activity_message, 1024, "%s %s", isCopy ? lang_strings[STR_COPYING] : lang_strings[STR_MOVING], src.name);
bytes_to_download = src.file_size;
ret = CopyOrMoveFile(src.path, new_path, isCopy);
if (ret <= 0)
{
free(new_path);
sprintf(status_message, "%s %s", isCopy ? lang_strings[STR_FAIL_COPY_MSG] : lang_strings[STR_FAIL_MOVE_MSG], src.name);
return 0;
}
free(new_path);
}
return 1;
}
void *MoveLocalFilesThread(void *argp)
{
file_transfering = true;
for (std::vector<DirEntry>::iterator it = local_paste_files.begin(); it != local_paste_files.end(); ++it)
{
if (stop_activity)
break;
if (strcmp(it->directory, local_directory) == 0)
continue;
if (it->isDir)
{
if (strncmp(local_directory, it->path, strlen(it->path)) == 0)
{
sprintf(status_message, "%s", lang_strings[STR_CANT_MOVE_TO_SUBDIR_MSG]);
continue;
}
char new_dir[512];
sprintf(new_dir, "%s%s%s", local_directory, FS::hasEndSlash(local_directory) ? "" : "/", it->name);
CopyOrMove(*it, new_dir, false);
}
else
{
CopyOrMove(*it, local_directory, false);
}
}
activity_inprogess = false;
file_transfering = false;
local_paste_files.clear();
Windows::SetModalMode(false);
selected_action = ACTION_REFRESH_LOCAL_FILES;
return NULL;
}
void MoveLocalFiles()
{
sprintf(status_message, "%s", "");
int res = pthread_create(&bk_activity_thid, NULL, MoveLocalFilesThread, NULL);
if (res != 0)
{
file_transfering = false;
activity_inprogess = false;
local_paste_files.clear();
Windows::SetModalMode(false);
}
}
void *CopyLocalFilesThread(void *argp)
{
file_transfering = true;
for (std::vector<DirEntry>::iterator it = local_paste_files.begin(); it != local_paste_files.end(); ++it)
{
if (stop_activity)
break;
if (strcmp(it->directory, local_directory) == 0)
continue;
if (it->isDir)
{
if (strncmp(local_directory, it->path, strlen(it->path)) == 0)
{
sprintf(status_message, "%s", lang_strings[STR_CANT_COPY_TO_SUBDIR_MSG]);
continue;
}
char new_dir[512];
sprintf(new_dir, "%s%s%s", local_directory, FS::hasEndSlash(local_directory) ? "" : "/", it->name);
CopyOrMove(*it, new_dir, true);
}
else
{
CopyOrMove(*it, local_directory, true);
}
}
activity_inprogess = false;
file_transfering = false;
local_paste_files.clear();
Windows::SetModalMode(false);
selected_action = ACTION_REFRESH_LOCAL_FILES;
return NULL;
}
void CopyLocalFiles()
{
sprintf(status_message, "%s", "");
int res = pthread_create(&bk_activity_thid, NULL, CopyLocalFilesThread, NULL);
if (res != 0)
{
file_transfering = false;
activity_inprogess = false;
local_paste_files.clear();
Windows::SetModalMode(false);
}
}
}
+8 -1
View File
@@ -42,7 +42,10 @@ enum ACTIONS
ACTION_CREATE_LOCAL_ZIP,
ACTION_LOCAL_CUT,
ACTION_LOCAL_COPY,
ACTION_LOCAL_PASTE
ACTION_LOCAL_PASTE,
ACTION_REMOTE_CUT,
ACTION_REMOTE_COPY,
ACTION_REMOTE_PASTE
};
enum OverWriteType
@@ -91,6 +94,10 @@ namespace Actions
void ExtractLocalZips();
void *MakeZipThread(void *argp);
void MakeLocalZip();
void *MoveLocalFilesThread(void *argp);
void MoveLocalFiles();
void *CopyLocalFilesThread(void *argp);
void CopyLocalFiles();
}
#endif
+78 -30
View File
@@ -7,11 +7,13 @@
#include <filesystem>
#include <stdio.h>
#include <unistd.h>
#include <vector>
#include "util.h"
#include "lang.h"
#include "rtc.h"
#include "windows.h"
#include "dbglogger.h"
namespace FS
{
@@ -176,7 +178,7 @@ namespace FS
memset(&entry, 0, sizeof(DirEntry));
sprintf(entry.directory, "%s", path.c_str());
sprintf(entry.name, "..");
sprintf(entry.display_size, "%s",lang_strings[STR_FOLDER]);
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
sprintf(entry.path, "%s", path.c_str());
entry.file_size = 0;
entry.isDir = true;
@@ -248,7 +250,7 @@ namespace FS
{
entry.isDir = true;
entry.file_size = 0;
sprintf(entry.display_size, "%s",lang_strings[STR_FOLDER]);
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
}
else
{
@@ -322,7 +324,7 @@ namespace FS
{
if (stop_activity)
return 1;
DIR *dfd = opendir(path.c_str());
if (dfd != NULL)
{
@@ -388,32 +390,6 @@ namespace FS
return 1;
}
int DirEntryComparator(const void *v1, const void *v2)
{
const DirEntry *p1 = (DirEntry *)v1;
const DirEntry *p2 = (DirEntry *)v2;
if (strcasecmp(p1->name, "..") == 0)
return -1;
if (strcasecmp(p2->name, "..") == 0)
return 1;
if (p1->isDir && !p2->isDir)
{
return -1;
}
else if (!p1->isDir && p2->isDir)
{
return 1;
}
return strcasecmp(p1->name, p2->name);
}
void Sort(std::vector<DirEntry> &list)
{
qsort(&list[0], list.size(), sizeof(DirEntry), DirEntryComparator);
}
std::string GetPath(const std::string &ppath1, const std::string &ppath2)
{
std::string path1 = ppath1;
@@ -422,9 +398,11 @@ namespace FS
return path1 + "/" + path2;
}
int Head(const std::string &path, void* buffer, uint16_t len)
int Head(const std::string &path, void *buffer, uint16_t len)
{
FILE *file = OpenRead(path);
if (file == nullptr)
return 0;
int ret = Read(file, buffer, len);
if (ret != len)
{
@@ -434,4 +412,74 @@ namespace FS
Close(file);
return 1;
}
bool Copy(const std::string &from, const std::string &to)
{
dbglogger_log("start copy");
MkDirs(to, true);
FILE *src = fopen(from.c_str(), "rb");
if (!src)
{
return false;
}
struct stat file_stat = {0};
if (stat(from.c_str(), &file_stat) != 0)
{
return false;
}
bytes_to_download = file_stat.st_size;
FILE *dest = fopen(to.c_str(), "wb");
if (!dest)
{
fclose(src);
return false;
}
size_t bytes_read = 0, bytes_transfered = 0;
const size_t buf_size = 0x10000;
unsigned char *buf = new unsigned char[buf_size];
do
{
bytes_read = fread(buf, sizeof(unsigned char), buf_size, src);
if (bytes_read < 0)
{
delete[] buf;
fclose(src);
fclose(dest);
return false;
}
size_t bytes_written = fwrite(buf, sizeof(unsigned char), bytes_read, dest);
if (bytes_written != bytes_read)
{
delete[] buf;
fclose(src);
fclose(dest);
return false;
}
bytes_transfered += bytes_read;
} while (bytes_transfered < bytes_to_download);
delete[] buf;
fclose(src);
fclose(dest);
dbglogger_log("end copy");
return true;
}
bool Move(const std::string &from, const std::string &to)
{
bool res = Copy(from, to);
if (res)
Rm(from);
else
return res;
return true;
}
}
+4 -2
View File
@@ -28,6 +28,10 @@ namespace FS
void Rename(const std::string &from, const std::string &to);
bool Copy(const std::string &from, const std::string &to);
bool Move(const std::string &from, const std::string &to);
// creates file (if it exists, truncates size to 0)
FILE *Create(const std::string &path);
@@ -52,8 +56,6 @@ namespace FS
std::vector<std::string> ListFiles(const std::string &path);
std::vector<DirEntry> ListDir(const std::string &path, int *err);
void Sort(std::vector<DirEntry> &list);
int hasEndSlash(const char *path);
int Head(const std::string &path, void* buffer, uint16_t len);
+10 -1
View File
@@ -106,7 +106,16 @@ char lang_strings[LANG_STRINGS_NUM][LANG_STR_SIZE] = {
"Zip Filename", // STR_ZIP_FILE_PATH
"Compressing", // STR_COMPRESSING
"Error occured while creating zip" // STR_ERROR_CREATE_ZIP
"Unsupported compressed file format" // STR_UNSUPPORTED_FILE_FORMAT
"Unsupported compressed file format", // STR_UNSUPPORTED_FILE_FORMAT
"Cut", // STR_CUT
"Copy", // STR_COPY
"Paste", // STR_PASTE
"Moving", // STR_MOVING
"Copying", // STR_COPYING
"Failed to move file", // STR_FAIL_MOVE_MSG
"Failed to copy file", // STR_FAIL_MOVE_MSG
"Cannot move parent directory to sub subdirectory", // STR_CANT_MOVE_TO_SUBDIR_MSG
"Cannot copy parent directory to sub subdirectory", // STR_CANT_COPY_TO_SUBDIR_MSG
};
bool needs_extended_font = false;
+11 -2
View File
@@ -100,7 +100,16 @@
FUNC(STR_ZIP_FILE_PATH) \
FUNC(STR_COMPRESSING) \
FUNC(STR_ERROR_CREATE_ZIP) \
FUNC(STR_UNSUPPORTED_FILE_FORMAT)
FUNC(STR_UNSUPPORTED_FILE_FORMAT) \
FUNC(STR_CUT) \
FUNC(STR_COPY) \
FUNC(STR_PASTE) \
FUNC(STR_MOVING) \
FUNC(STR_COPYING) \
FUNC(STR_FAIL_MOVE_MSG) \
FUNC(STR_FAIL_COPY_MSG) \
FUNC(STR_CANT_MOVE_TO_SUBDIR_MSG) \
FUNC(STR_CANT_COPY_TO_SUBDIR_MSG)
#define GET_VALUE(x) x,
#define GET_STRING(x) #x,
@@ -110,7 +119,7 @@ enum
FOREACH_STR(GET_VALUE)
};
#define LANG_STRINGS_NUM 97
#define LANG_STRINGS_NUM 106
#define LANG_ID_SIZE LANG_STRINGS_NUM
#define LANG_STR_SIZE 256
extern char lang_identifiers[LANG_STRINGS_NUM][LANG_ID_SIZE];
+87 -4
View File
@@ -40,9 +40,12 @@ std::vector<DirEntry> local_files;
std::vector<DirEntry> remote_files;
std::set<DirEntry> multi_selected_local_files;
std::set<DirEntry> multi_selected_remote_files;
std::vector<DirEntry> local_paste_files;
std::vector<DirEntry> remote_paste_files;
DirEntry selected_local_file;
DirEntry selected_remote_file;
ACTIONS selected_action;
ACTIONS paste_action;
char status_message[1024];
char local_file_to_select[256];
char remote_file_to_select[256];
@@ -92,6 +95,8 @@ namespace Windows
confirm_transfer_state = -1;
dont_prompt_overwrite_cb = false;
overwrite_type = OVERWRITE_PROMPT;
local_paste_files.clear();
remote_paste_files.clear();
Actions::RefreshLocalFiles(false);
}
@@ -678,7 +683,8 @@ namespace Windows
ImVec2 pos = ImGui::GetCursorPos();
ImGui::Dummy(ImVec2(1880, 30));
ImGui::SetCursorPos(pos);
ImGui::PushTextWrapPos(1880);
ImGui::SetCursorPosX(pos.x + 10);
ImGui::PushTextWrapPos(1870);
if (strncmp(status_message, "4", 1) == 0 || strncmp(status_message, "3", 1) == 0)
{
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "%s", status_message);
@@ -729,13 +735,13 @@ namespace Windows
bool remote_browser_selected = saved_selected_browser & REMOTE_BROWSER;
if (local_browser_selected)
{
ImGui::SetNextWindowPos(ImVec2(410, 350));
ImGui::SetNextWindowPos(ImVec2(410, 300));
}
else if (remote_browser_selected)
{
ImGui::SetNextWindowPos(ImVec2(1330, 350));
ImGui::SetNextWindowPos(ImVec2(1330, 300));
}
ImGui::SetNextWindowSizeConstraints(ImVec2(230, 150), ImVec2(230, 450), NULL, NULL);
ImGui::SetNextWindowSizeConstraints(ImVec2(230, 150), ImVec2(230, 550), NULL, NULL);
if (ImGui::BeginPopupModal(lang_strings[STR_ACTIONS], NULL, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::PushID("Select All##settings");
@@ -764,6 +770,42 @@ namespace Windows
ImGui::PopID();
ImGui::Separator();
ImGui::PushID("Cut##settings");
if (ImGui::Selectable(lang_strings[STR_CUT], false, getSelectableFlag() | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
selected_action = local_browser_selected ? ACTION_LOCAL_CUT : ACTION_REMOTE_CUT;
SetModalMode(false);
ImGui::CloseCurrentPopup();
}
ImGui::PopID();
ImGui::Separator();
ImGui::PushID("Copy##settings");
if (ImGui::Selectable(lang_strings[STR_COPY], false, getSelectableFlag() | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
selected_action = local_browser_selected ? ACTION_LOCAL_COPY : ACTION_REMOTE_COPY;
SetModalMode(false);
ImGui::CloseCurrentPopup();
}
ImGui::PopID();
ImGui::Separator();
ImGui::PushID("Paste##settings");
flags = ImGuiSelectableFlags_None;
if ((local_browser_selected && local_paste_files.size() == 0) ||
(remote_browser_selected && remote_paste_files.size() == 0))
flags = ImGuiSelectableFlags_Disabled;
if (ImGui::Selectable(lang_strings[STR_PASTE], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
SetModalMode(false);
selected_action = ACTION_LOCAL_PASTE;
file_transfering = true;
confirm_transfer_state = 0;
dont_prompt_overwrite_cb = dont_prompt_overwrite;
ImGui::CloseCurrentPopup();
}
ImGui::PopID();
ImGui::Separator();
ImGui::PushID("Delete##settings");
if (ImGui::Selectable(lang_strings[STR_DELETE], false, getSelectableFlag() | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
@@ -1422,6 +1464,47 @@ namespace Windows
Actions::InstallUrlPkg();
selected_action = ACTION_NONE;
break;
case ACTION_LOCAL_CUT:
case ACTION_LOCAL_COPY:
paste_action = selected_action;
local_paste_files.clear();
if (multi_selected_local_files.size()>0)
std::copy(multi_selected_local_files.begin(), multi_selected_local_files.end(), std::back_inserter(local_paste_files));
else
local_paste_files.push_back(selected_local_file);
multi_selected_local_files.clear();
selected_action = ACTION_NONE;
break;
case ACTION_REMOTE_CUT:
case ACTION_REMOTE_COPY:
paste_action = selected_action;
remote_paste_files.clear();
if (multi_selected_remote_files.size()>0)
std::copy(multi_selected_remote_files.begin(), multi_selected_remote_files.end(), std::back_inserter(remote_paste_files));
else
remote_paste_files.push_back(selected_remote_file);
multi_selected_remote_files.clear();
selected_action = ACTION_NONE;
break;
case ACTION_LOCAL_PASTE:
sprintf(status_message, "%s", "");
sprintf(activity_message, "%s", "");
if (dont_prompt_overwrite || (!dont_prompt_overwrite && confirm_transfer_state == 1))
{
activity_inprogess = true;
stop_activity = false;
confirm_transfer_state = -1;
if (paste_action == ACTION_LOCAL_CUT)
Actions::MoveLocalFiles();
else if (paste_action == ACTION_LOCAL_COPY)
Actions::CopyLocalFiles();
else
{
activity_inprogess = false;
}
selected_action = ACTION_NONE;
}
break;
default:
break;
}
+3
View File
@@ -20,6 +20,9 @@ extern std::vector<DirEntry> local_files;
extern std::vector<DirEntry> remote_files;
extern std::set<DirEntry> multi_selected_local_files;
extern std::set<DirEntry> multi_selected_remote_files;
extern std::vector<DirEntry> local_paste_files;
extern std::vector<DirEntry> remote_paste_files;
extern ACTIONS paste_action;
extern DirEntry selected_local_file;
extern DirEntry selected_remote_file;
extern ACTIONS selected_action;
+2 -7
View File
@@ -220,14 +220,9 @@ namespace ZipUtil
{
char buf[8];
FILE *f = FS::OpenRead(file);
if (f == nullptr)
return COMPRESS_FILE_TYPE_UNKNOWN;
memset(buf, 0, 8);
int ret = FS::Read(f, buf, 8);
FS::Close(f);
if (ret < 0)
int ret = FS::Head(file, buf, 8);
if (ret == 0)
return COMPRESS_FILE_TYPE_UNKNOWN;
if (strncmp(buf, (const char *)MAGIC_7Z_1, 6) == 0)