diff --git a/src/RemoteFS.cpp b/src/RemoteFS.cpp --- a/src/RemoteFS.cpp +++ b/src/RemoteFS.cpp @@ -1,404 +1,409 @@ #include "FtpApp.h" #include "lgi/common/Edit.h" LRemoteFS::LRemoteFS(AppWnd *Wnd, LImageList *ImageList) : LFileSystemView(Wnd, ImageList, false) { SetId(IDC_REMOTE_VIEW); Name("LRemoteFS"); } void LRemoteFS::OnCreate() { SetWindow(this); } int LRemoteFS::WillAccept(LDragFormats &Formats, LPoint Pt, int KeyState) { return Wnd->WillAccept(Formats, Pt, KeyState); } int LRemoteFS::OnDrop(LArray &Data, LPoint Pt, int KeyState) { return Wnd->OnDrop(Data, Pt, KeyState); } void LRemoteFS::OnFilter(char *f) { Filter = f; // auto Int = Entries.Length(); // auto Ext = Lst->Length(); List Items; Lst->GetAll(Items); List Del; LItemMap Map(Lst); for (auto &e : Entries) { DirListItem *Vis = Map.Find(e->Name); if (!f || stristr(e->Name, f) != 0) { // show if (!Vis) { Lst->Insert(Vis = new DirListItem(e, this), (e->IsDir()) ? 0 : -1); } } else { // hide if (Vis) { Vis->SetEntry(NULL); Lst->Remove(Vis); Del.Insert(Vis); } } } Del.DeleteObjects(); Lst->Sort(FtpItemCompare, (NativeInt)this); LVariant Resize = 0; if (Wnd->GetOptions()->GetValue(OPT_ResizeToContent, Resize) && Resize.CastInt32()) { Lst->ResizeColumnsToContent(); } } void LRemoteFS::EnableCommands(bool Enabled) { if (!InThread()) { PostEvent(M_ENABLE_CMDS, Enabled); } else { CmdCreateDir.Enabled(Enabled); CmdDelete.Enabled(Enabled); CmdRenameFile.Enabled(Enabled); CmdSetPerms.Enabled(Enabled); CmdExecute.Enabled(false); CmdViewText.Enabled(false); CmdTransfer.Enabled(Enabled); CmdRefresh.Enabled(Enabled); CmdCdup.Enabled(Enabled); } } bool LRemoteFS::IsCmdLocal(int Cmd) { return false; // Cmd == TASK_ProcessClick; } void LRemoteFS::OnItemSelect(LListItem *Item) { } bool LRemoteFS::RefreshList() { LAutoPtr c(new FtpCmd(_FL, TASK_List, this)); if (!c) return false; c->Str[LIST_REMOTE_PATH] = GetDir(); c->Int[LIST_SHOW_HIDDEN] = Wnd->ShowHiddenFiles(); return PostCmd(c); } bool LRemoteFS::Cd(const char *Dir, bool RefreshList) { LString Tmp = "/"; if (Dir) { char *Slash; while ((Slash = strchr(Dir, '\\'))) { *Slash = '/'; } } else { LString Sep = "/"; auto Cur = GetDir(); LString::Array c = Cur.Split(Sep); if (c.Length() > 0) c.PopLast(); Tmp += Sep.Join(c); Dir = Tmp; } LAutoPtr c(new FtpCmd(_FL, Dir ? TASK_List : TASK_ParentFolder, this)); if (!c) return false; c->Source = this; if (Dir) c->Str[LIST_REMOTE_PATH] = Dir; c->Int[LIST_SHOW_HIDDEN] = Wnd->ShowHiddenFiles(); Wnd->OnFolder(IsLocal(), Dir); return PostCmd(c); } bool LRemoteFS::CreateDir(char *Dir) { LAutoPtr c(new FtpCmd(_FL, TASK_CreateFolder, this)); if (!c) return false; c->Str[CREATE_FOLDER_PARENT] = GetDir().Get(); c->Str[CREATE_FOLDER_NAME] = Dir; return PostCmd(c); } bool LRemoteFS::Delete(IFtpEntry *e) { LAutoPtr c(new FtpCmd(_FL, TASK_Delete, this)); if (!c) return false; c->Str[DELETE_DIR] = GetDir().Get(); c->Str[DELETE_NAME] = e->Name.Get(); c->Int[DELETE_RECURSIVELY] = true; c->Int[DELETE_IS_FOLDER] = e->IsDir(); return PostCmd(c); } bool LRemoteFS::SetPerms(IFtpEntry *e, LPermissions Perms) { if (!e || !e->Name) { LAssert(!"No entry."); return false; } if (Perms.IsWindows) { LAssert(!"Wrong type."); return false; } LAutoPtr c(new FtpCmd(_FL, TASK_SetPerms, this)); if (!c) return false; c->Str[PERMS_FILE] = e->Name; c->Int[PERMS_ACCESS] = Perms.u32; c->Source = this; return PostCmd(c); } bool LRemoteFS::Transfer(LString::Array &Files, int Mode) { // Download file if (Files.Length() == 0) return Wnd->OnError("No files to transfer (%s:%i)", _FL); LAutoPtr c(new FtpCmd(_FL, TASK_Download, Opposite)); if (!c) return Wnd->OnError("Alloc memory (%s:%i)", _FL); // Return to initial folders FtpCmd *cmd = new FtpCmd(_FL, TASK_Folder, Opposite); if (cmd) { cmd->Process = Opposite; cmd->Str[LIST_REMOTE_PATH] = Opposite->GetDir(); cmd->Int[LIST_SHOW_HIDDEN] = Wnd->ShowHiddenFiles(); c->OnSuccess.Add(cmd); } cmd = new FtpCmd(_FL, TASK_Folder, this); if (cmd) { cmd->Process = this; cmd->Str[LIST_REMOTE_PATH] = GetDir().Get(); cmd->Int[LIST_SHOW_HIDDEN] = Wnd->ShowHiddenFiles(); c->OnSuccess.Add(cmd); } EntryMap RemoteMap; GetMap(RemoteMap); LString LocalPath = Opposite->GetDir(); c->Source = this; c->Str[DOWNLOAD_SOURCE_PATH] = GetDir().Get(); // Make copies for thread safety c->Str[DOWNLOAD_DEST_PATH] = LocalPath.Get(); for (unsigned i=0; iName = Files[i]; } bool Exists = e->IsDir() ? LDirExists(p) : LFileExists(p); if (Exists) { // File exists already.. ResumeDlg::OverwriteEntry *Oe = new ResumeDlg::OverwriteEntry(c->Cmd); if (Oe) { Oe->Local = p.GetFull(); if (Oe->Remote.Reset(new IFtpEntry(e))) { int64 Sz = LFileSize(Oe->Local); if (Sz >= 0 && Oe->Remote->Size > Sz) Oe->Resumable = true; } Wnd->PostEvent(M_OVERWRITE_DLG, (LMessage::Param)Oe); } } else { c->AddEntry(e); } } if (c->EntryLength() == 0) return true; return PostCmd(c); } class LinkDlg : public LDialog { public: int Dir; LinkDlg(LView *p, int d) { Dir = d; SetParent(p); if (LoadFromResource(IDD_LINK)) { MoveToCenter(); SetCtrlValue(IDC_TYPE, Dir); } } int OnNotify(LViewI *c, LNotification n) { switch (c->GetId()) { case IDOK: { Dir = (int)GetCtrlValue(IDC_TYPE); } case IDCANCEL: { EndModal(c->GetId() == IDOK); break; } } return 0; } }; void LRemoteFS::ProcessClick(IFtpEntry *e, LMouse *m, std::function callback) { if (!e || !e->Name || !m->Left() || !m->Double()) { if (callback) callback(false); return; } bool IsDir = e->IsDir(); auto ProcessDir = [this, e]() { // dir LString Sep = "/"; LString::Array a = LString(Edit->Name()).Split(Sep); a.SetFixedLength(false); auto Arr = e->Name.Split(Sep); a.Add(Arr); LString Path = Sep + Sep.Join(a); LAutoPtr Cmd(new FtpCmd(_FL, TASK_List, this)); if (Cmd) { Cmd->Str[LIST_REMOTE_PATH] = Path; Cmd->Int[LIST_SHOW_HIDDEN] = Wnd->ShowHiddenFiles(); PostCmd(Cmd); } else Wnd->OnError("Allocation error (%s:%i)", _FL); }; auto ProcessFile = [this, e]() { LString::Array Files; Files.New() = e->Name; Transfer(Files, 0); }; if (e->Attributes & IFTP_SYM_LINK) { // Make a guess IsDir = !strchr(e->Name, '.'); LVariant Confirm = 0; if (Wnd->GetOptions()->GetValue(OPT_ConfirmLinks, Confirm) && Confirm.CastInt32()) { auto d = new LinkDlg(this, IsDir); - d->DoModal([this, d, ProcessDir, ProcessFile](auto dlg, auto code) + d->DoModal([this, d, ProcessDir, ProcessFile, callback](auto dlg, auto code) { if (code) { if (d->Dir != 0) ProcessDir(); else ProcessFile(); } + delete d; + + if (callback) + callback(code); }); - return false; + + return; } } if (IsDir) ProcessDir(); else ProcessFile(); if (callback) callback(true); } bool LRemoteFS::RenameFile(const char *From, const char *To) { if (Strcmp(From, To) == 0) return true; LAutoPtr c(new FtpCmd(_FL, TASK_Rename, this)); if (!c) return false; c->Str[RENAME_DIR] = GetDir(); c->Str[RENAME_OLD] = From; c->Str[RENAME_NEW] = To; return PostCmd(c); }