void CSearchDialog::OnDelete(wxCommandEvent& event) { if (!m_pState->IsRemoteIdle()) return; // Find all selected files and directories std::list<CServerPath> selected_dirs; std::list<int> selected_files; ProcessSelection(selected_files, selected_dirs); if (selected_files.empty() && selected_dirs.empty()) return; if (selected_dirs.size() > 1) { wxMessageBox(_("Deleting multiple unrelated directories is not yet supported"), _("Deleting directories"), wxICON_EXCLAMATION); return; } wxString question; if (selected_dirs.empty()) question.Printf(wxPLURAL("Really delete %d file from the server?", "Really delete %d files from the server?", selected_files.size()), selected_files.size()); else if (selected_files.empty()) question.Printf(wxPLURAL("Really delete %d directory with its contents from the server?", "Really delete %d directories with their contents from the server?", selected_dirs.size()), selected_dirs.size()); else { wxString files = wxString::Format(wxPLURAL("%d file", "%d files", selected_files.size()), selected_files.size()); wxString dirs = wxString::Format(wxPLURAL("%d directory with its contents", "%d directories with their contents", selected_dirs.size()), selected_dirs.size()); question.Printf(_("Really delete %s and %s from the server?"), files.c_str(), dirs.c_str()); } if (wxMessageBox(question, _("Confirm deletion"), wxICON_QUESTION | wxYES_NO) != wxYES) return; for (std::list<int>::const_iterator iter = selected_files.begin(); iter != selected_files.end(); ++iter) { const CDirentry& entry = m_results->m_fileData[*iter].entry; std::list<wxString> files_to_delete; files_to_delete.push_back(entry.name); m_pState->m_pCommandQueue->ProcessCommand(new CDeleteCommand(m_results->m_fileData[*iter].path, files_to_delete)); } for (std::list<CServerPath>::const_iterator iter = selected_dirs.begin(); iter != selected_dirs.end(); ++iter) { CServerPath path = *iter; if (!path.HasParent()) m_pState->GetRecursiveOperationHandler()->AddDirectoryToVisit(path, _T("")); else { m_pState->GetRecursiveOperationHandler()->AddDirectoryToVisit(path.GetParent(), path.GetLastSegment()); path = path.GetParent(); } std::list<CFilter> filters; // Empty, recurse into everything m_pState->GetRecursiveOperationHandler()->StartRecursiveOperation(CRecursiveOperation::recursive_delete, path, filters, !path.HasParent(), m_original_dir); } }
void CRemoteTreeView::OnMkdir(wxCommandEvent& event) { if (!m_pState->IsRemoteIdle()) return; if (!m_contextMenuItem) return; const CServerPath& path = GetPathFromItem(m_contextMenuItem); if (path.IsEmpty()) return; CInputDialog dlg; if (!dlg.Create(this, _("Create directory"), _("Please enter the name of the directory which should be created:"))) return; CServerPath newPath = path; // Append a long segment which does (most likely) not exist in the path and // replace it with "New directory" later. This way we get the exact position of // "New directory" and can preselect it in the dialog. wxString tmpName = _T("25CF809E56B343b5A12D1F0466E3B37A49A9087FDCF8412AA9AF8D1E849D01CF"); if (newPath.AddSegment(tmpName)) { wxString pathName = newPath.GetPath(); int pos = pathName.Find(tmpName); wxASSERT(pos != -1); wxString newName = _("New directory"); pathName.Replace(tmpName, newName); dlg.SetValue(pathName); dlg.SelectText(pos, pos + newName.Length()); } if (dlg.ShowModal() != wxID_OK) return; newPath = path; if (!newPath.ChangePath(dlg.GetValue())) { wxBell(); return; } m_pState->m_pCommandQueue->ProcessCommand(new CMkdirCommand(newPath)); CServerPath listed; if (newPath.HasParent()) { listed = newPath.GetParent(); m_pState->ChangeRemoteDir(listed); } CServerPath currentPath; const wxTreeItemId selected = GetSelection(); if (selected) currentPath = GetPathFromItem(selected); if (!currentPath.IsEmpty() && currentPath != listed) m_pState->ChangeRemoteDir(currentPath); }
void CState::UploadDroppedFiles(const wxFileDataObject* pFileDataObject, const wxString& subdir, bool queueOnly) { if (!m_pServer || !m_pDirectoryListing) return; CServerPath path = m_pDirectoryListing->path; if (subdir == _T("..") && path.HasParent()) path = path.GetParent(); else if (!subdir.empty()) path.AddSegment(subdir); UploadDroppedFiles(pFileDataObject, path, queueOnly); }
bool CUpdater::CreateTransferCommand(wxString const& url, wxString const& local_file) { CFileTransferCommand::t_transferSettings transferSettings; CServer s; CServerPath path; wxString error; if( !s.ParseUrl( url, 0, wxString(), wxString(), error, path ) || (s.GetProtocol() != HTTP && s.GetProtocol() != HTTPS) ) { return false; } wxString file = path.GetLastSegment(); path = path.GetParent(); pending_commands_.emplace_back(new CFileTransferCommand(local_file, path, file, true, transferSettings)); return true; }
CLocalPath CState::GetSynchronizedDirectory(CServerPath remote_path) { std::list<wxString> segments; while (remote_path.HasParent() && remote_path != m_sync_browse.remote_root) { segments.push_front(remote_path.GetLastSegment()); remote_path = remote_path.GetParent(); } if (remote_path != m_sync_browse.remote_root) return CLocalPath(); CLocalPath local_path = m_sync_browse.local_root; for (std::list<wxString>::const_iterator iter = segments.begin(); iter != segments.end(); ++iter) local_path.AddSegment(*iter); return local_path; }
// Create a new Directory void CRemoteTreeView::OnMkdir(wxCommandEvent&) { CServerPath newpath = MenuMkdir(); CServerPath listed; if (newpath.HasParent()) { listed = newpath.GetParent(); m_pState->ChangeRemoteDir(listed); } CServerPath currentPath; const wxTreeItemId selected = GetSelection(); if (selected) currentPath = GetPathFromItem(selected); if (!currentPath.empty() && currentPath != listed) m_pState->ChangeRemoteDir(currentPath); }
int CUpdater::SendTransferCommand(wxString const& url, wxString const& local_file) { CFileTransferCommand::t_transferSettings transferSettings; CServer s; CServerPath path; wxString error; if( !s.ParseUrl( url, 0, _T(""), _T(""), error, path ) || (s.GetProtocol() != HTTP && s.GetProtocol() != HTTPS) ) { return FZ_REPLY_ERROR; } wxString file = path.GetLastSegment(); path = path.GetParent(); CFileTransferCommand cmd(local_file, path, file, true, transferSettings); int res = engine_->Command(cmd); wxASSERT(res != FZ_REPLY_OK); return res; }
void CRemoteTreeView::OnBeginDrag(wxTreeEvent& event) { // Drag could result in recursive operation, don't allow at this point if (!m_pState->IsRemoteIdle()) { wxBell(); return; } const wxTreeItemId& item = event.GetItem(); if (!item) return; CServerPath path = GetPathFromItem(item); if (path.empty() || !path.HasParent()) return; const CServerPath& parent = path.GetParent(); const wxString& lastSegment = path.GetLastSegment(); if (lastSegment.empty()) return; wxDataObjectComposite object; CServer const* pServer = m_pState->GetServer(); if (!pServer) return; CServer const server = *pServer; CRemoteDataObject *pRemoteDataObject = new CRemoteDataObject(*pServer, parent); pRemoteDataObject->AddFile(lastSegment, true, -1, false); pRemoteDataObject->Finalize(); object.Add(pRemoteDataObject, true); #if FZ3_USESHELLEXT std::unique_ptr<CShellExtensionInterface> ext = CShellExtensionInterface::CreateInitialized(); if (ext) { const wxString& file = ext->GetDragDirectory(); wxASSERT(!file.empty()); wxFileDataObject *pFileDataObject = new wxFileDataObject; pFileDataObject->AddFile(file); object.Add(pFileDataObject); } #endif CDragDropManager* pDragDropManager = CDragDropManager::Init(); pDragDropManager->pDragSource = this; pDragDropManager->server = *pServer; pDragDropManager->remoteParent = parent; wxDropSource source(this); source.SetData(object); int res = source.DoDragDrop(); pDragDropManager->Release(); if (res != wxDragCopy) { return; } #if FZ3_USESHELLEXT if (ext) { if (!pRemoteDataObject->DidSendData()) { pServer = m_pState->GetServer(); if (!pServer || !m_pState->IsRemoteIdle() || *pServer != server) { wxBell(); return; } CLocalPath target(ext->GetTarget()); if (target.empty()) { ext.reset(); // Release extension before the modal message box wxMessageBoxEx(_("Could not determine the target of the Drag&Drop operation.\nEither the shell extension is not installed properly or you didn't drop the files into an Explorer window.")); return; } m_pState->DownloadDroppedFiles(pRemoteDataObject, target); } } #endif }
wxTreeItemId CRemoteTreeView::MakeParent(CServerPath path, bool select) { std::vector<wxString> pieces; pieces.reserve(path.SegmentCount() + 1); while (path.HasParent()) { pieces.push_back(path.GetLastSegment()); path = path.GetParent(); } wxASSERT(!path.GetPath().empty()); pieces.push_back(path.GetPath()); const wxTreeItemId root = GetRootItem(); wxTreeItemId parent = root; for (std::vector<wxString>::const_reverse_iterator iter = pieces.rbegin(); iter != pieces.rend(); ++iter) { if (iter != pieces.rbegin()) path.AddSegment(*iter); wxTreeItemIdValue cookie; wxTreeItemId child = GetFirstChild(parent, cookie); if (child && GetItemText(child).empty()) { Delete(child); child = wxTreeItemId(); if (parent != root) ListExpand(parent); } for (child = GetFirstChild(parent, cookie); child; child = GetNextSibling(child)) { const wxString& text = GetItemText(child); if (text == *iter) break; } if (!child) { CDirectoryListing listing; if (m_pState->m_pEngine->CacheLookup(path, listing) == FZ_REPLY_OK) { child = AppendItem(parent, *iter, 0, 2, path.HasParent() ? 0 : new CItemData(path)); SetItemImages(child, false); } else { child = AppendItem(parent, *iter, 1, 3, path.HasParent() ? 0 : new CItemData(path)); SetItemImages(child, true); } SortChildren(parent); auto nextIter = iter; ++nextIter; if (nextIter != pieces.rend()) DisplayItem(child, listing); } if (select && iter != pieces.rbegin()) { #ifndef __WXMSW__ // Prevent CalculatePositions from being called wxGenericTreeItem *anchor = m_anchor; m_anchor = 0; #endif Expand(parent); #ifndef __WXMSW__ m_anchor = anchor; #endif } parent = child; } return parent; }
void CRemoteTreeView::OnEndLabelEdit(wxTreeEvent& event) { if (event.IsEditCancelled()) { event.Veto(); return; } if (!m_pState->IsRemoteIdle()) { event.Veto(); return; } CItemData* const pData = (CItemData*)GetItemData(event.GetItem()); if (pData) { event.Veto(); return; } CServerPath old_path = GetPathFromItem(event.GetItem()); CServerPath parent = old_path.GetParent(); const wxString& oldName = GetItemText(event.GetItem()); const wxString& newName = event.GetLabel(); if (oldName == newName) { event.Veto(); return; } m_pState->m_pCommandQueue->ProcessCommand(new CRenameCommand(parent, oldName, parent, newName)); m_pState->ChangeRemoteDir(parent); CServerPath currentPath; const wxTreeItemId selected = GetSelection(); if (selected) currentPath = GetPathFromItem(selected); if (currentPath.empty()) return; if (currentPath == old_path || currentPath.IsSubdirOf(old_path, false)) { // Previously selected path was below renamed one, list the new one std::list<wxString> subdirs; while (currentPath != old_path) { if (!currentPath.HasParent()) { // Abort just in case return; } subdirs.push_front(currentPath.GetLastSegment()); currentPath = currentPath.GetParent(); } currentPath = parent; currentPath.AddSegment(newName); for (std::list<wxString>::const_iterator iter = subdirs.begin(); iter != subdirs.end(); ++iter) currentPath.AddSegment(*iter); m_pState->ChangeRemoteDir(currentPath); } else if (currentPath != parent) m_pState->ChangeRemoteDir(currentPath); }