void CPathCache::InvalidatePath(tServerCache & serverCache, CServerPath const& path, wxString const& subdir) { CSourcePath sourcePath; sourcePath.source = path; sourcePath.subdir = subdir; CServerPath target; tServerCacheIterator serverIter = serverCache.find(sourcePath); if (serverIter != serverCache.end()) { target = serverIter->second; serverCache.erase(serverIter); } if (target.empty() && !subdir.empty()) { target = path; if (!target.AddSegment(subdir)) return; } if (!target.empty()) { // Unfortunately O(n), don't know of a faster way. for (auto serverIter = serverCache.begin(); serverIter != serverCache.end(); ) { if (serverIter->second == target || target.IsParentOf(serverIter->second, false)) serverCache.erase(serverIter++); else if (serverIter->first.source == target || target.IsParentOf(serverIter->first.source, false)) serverCache.erase(serverIter++); else ++serverIter; } } }
void CRecursiveOperation::StartRecursiveOperation(enum OperationMode mode, const CServerPath& startDir, const std::list<CFilter>& filters, bool allowParent /*=false*/, const CServerPath& finalDir /*=CServerPath()*/) { wxCHECK_RET(m_operationMode == recursive_none, _T("StartRecursiveOperation called with m_operationMode != recursive_none")); wxCHECK_RET(m_pState->IsRemoteConnected(), _T("StartRecursiveOperation while disconnected")); wxCHECK_RET(!startDir.empty(), _T("Empty startDir in StartRecursiveOperation")); if (mode == recursive_chmod && !m_pChmodDlg) return; if ((mode == recursive_download || mode == recursive_addtoqueue || mode == recursive_download_flatten || mode == recursive_addtoqueue_flatten) && !m_pQueue) return; if (m_dirsToVisit.empty()) { // Nothing to do in this case return; } m_operationMode = mode; m_pState->NotifyHandlers(STATECHANGE_REMOTE_IDLE); m_startDir = startDir; if (finalDir.empty()) m_finalDir = startDir; else m_finalDir = finalDir; m_allowParent = allowParent; m_filters = filters; NextOperation(); }
bool CBookmarksDialog::AddBookmark(const wxString &name, const wxString &local_dir, const CServerPath &remote_dir, bool sync) { if (local_dir.empty() && remote_dir.empty()) return false; if ((local_dir.empty() || remote_dir.empty()) && sync) return false; CInterProcessMutex mutex(MUTEX_GLOBALBOOKMARKS); CXmlFile file(wxGetApp().GetSettingsFile(_T("bookmarks"))); TiXmlElement* pDocument = file.Load(); if (!pDocument) { wxString msg = file.GetError() + _T("\n\n") + _("The bookmark could not be added."); wxMessageBoxEx(msg, _("Error loading xml file"), wxICON_ERROR); return false; } TiXmlElement *pInsertBefore = 0; TiXmlElement *pBookmark; for (pBookmark = pDocument->FirstChildElement("Bookmark"); pBookmark; pBookmark = pBookmark->NextSiblingElement("Bookmark")) { wxString remote_dir_raw; wxString old_name = GetTextElement(pBookmark, "Name"); if (!name.CmpNoCase(old_name)) { wxMessageBoxEx(_("Name of bookmark already exists."), _("New bookmark"), wxICON_EXCLAMATION); return false; } if (name < old_name && !pInsertBefore) pInsertBefore = pBookmark; } if (pInsertBefore) pBookmark = pDocument->InsertBeforeChild(pInsertBefore, TiXmlElement("Bookmark"))->ToElement(); else pBookmark = pDocument->LinkEndChild(new TiXmlElement("Bookmark"))->ToElement(); AddTextElement(pBookmark, "Name", name); if (!local_dir.empty()) AddTextElement(pBookmark, "LocalDir", local_dir); if (!remote_dir.empty()) AddTextElement(pBookmark, "RemoteDir", remote_dir.GetSafePath()); if (sync) AddTextElementRaw(pBookmark, "SyncBrowsing", "1"); if (!file.Save(false)) { wxString msg = wxString::Format(_("Could not write \"%s\", the bookmark could not be added: %s"), file.GetFileName(), file.GetError()); wxMessageBoxEx(msg, _("Error writing xml file"), wxICON_ERROR); return false; } return true; }
// Create a new Directory and enter the new Directory void CRemoteTreeView::OnMenuMkdirChgDir(wxCommandEvent&) { CServerPath newpath = MenuMkdir(); if (!newpath.empty()) { m_pState->ChangeRemoteDir(newpath); } }
void CRemoteRecursiveOperation::StartRecursiveOperation(OperationMode mode, std::vector<CFilter> const& filters, CServerPath const& finalDir) { wxCHECK_RET(m_operationMode == recursive_none, _T("StartRecursiveOperation called with m_operationMode != recursive_none")); wxCHECK_RET(m_state.IsRemoteConnected(), _T("StartRecursiveOperation while disconnected")); wxCHECK_RET(!finalDir.empty(), _T("Empty final dir in recursive operation")); if (mode == recursive_chmod && !m_pChmodDlg) return; if ((mode == recursive_transfer || mode == recursive_addtoqueue || mode == recursive_transfer_flatten || mode == recursive_addtoqueue_flatten) && !m_pQueue) return; if (recursion_roots_.empty()) { // Nothing to do in this case return; } m_processedFiles = 0; m_processedDirectories = 0; m_operationMode = mode; m_state.NotifyHandlers(STATECHANGE_REMOTE_IDLE); m_state.NotifyHandlers(STATECHANGE_REMOTE_RECURSION_STATUS); m_filters = filters; NextOperation(); }
int CServerPath::CmpNoCase(const CServerPath &op) const { if (empty() != op.empty()) return 1; else if (m_data->m_prefix != op.m_data->m_prefix) return 1; else if (m_type != op.m_type) return 1; if (m_data->m_segments.size() > op.m_data->m_segments.size()) return 1; else if (m_data->m_segments.size() < op.m_data->m_segments.size()) return -1; tConstSegmentIter iter = m_data->m_segments.begin(); tConstSegmentIter iter2 = op.m_data->m_segments.begin(); while (iter != m_data->m_segments.end()) { int res = fz::stricmp(*(iter++), *(iter2++)); if (res) { return res; } } return 0; }
bool CState::SetSyncBrowse(bool enable, const CServerPath& assumed_remote_root /*=CServerPath()*/) { if (enable != m_sync_browse.local_root.empty()) return enable; if (!enable) { wxASSERT(assumed_remote_root.empty()); m_sync_browse.local_root.clear(); m_sync_browse.remote_root.clear(); m_sync_browse.is_changing = false; NotifyHandlers(STATECHANGE_SYNC_BROWSE); return false; } if (!m_pDirectoryListing && assumed_remote_root.empty()) { NotifyHandlers(STATECHANGE_SYNC_BROWSE); return false; } m_sync_browse.is_changing = false; m_sync_browse.local_root = m_localDir; if (assumed_remote_root.empty()) m_sync_browse.remote_root = m_pDirectoryListing->path; else { m_sync_browse.remote_root = assumed_remote_root; m_sync_browse.is_changing = true; m_sync_browse.compare = false; } while (m_sync_browse.local_root.HasParent() && m_sync_browse.remote_root.HasParent() && m_sync_browse.local_root.GetLastSegment() == m_sync_browse.remote_root.GetLastSegment()) { m_sync_browse.local_root.MakeParent(); m_sync_browse.remote_root = m_sync_browse.remote_root.GetParent(); } NotifyHandlers(STATECHANGE_SYNC_BROWSE); return true; }
bool CServerPath::operator<(const CServerPath &op) const { if (empty()) { if (!op.empty()) { return false; } } else if (op.empty()) { return true; } if (m_data->m_prefix || op.m_data->m_prefix) { if (m_data->m_prefix < op.m_data->m_prefix) { return true; } else if (op.m_data->m_prefix < m_data->m_prefix) { return false; } } if (m_type > op.m_type) { return false; } else if (m_type < op.m_type) { return true; } tConstSegmentIter iter1, iter2; for (iter1 = m_data->m_segments.begin(), iter2 = op.m_data->m_segments.begin(); iter1 != m_data->m_segments.end(); ++iter1, ++iter2) { if (iter2 == op.m_data->m_segments.end()) { return false; } const int cmp = std::wcscmp(iter1->c_str(), iter2->c_str()); if (cmp < 0) { return true; } if (cmp > 0) { return false; } } return iter2 != op.m_data->m_segments.end(); }
bool CServerPath::IsSubdirOf(const CServerPath &path, bool cmpNoCase) const { if (empty() || path.empty()) { return false; } if (m_type != path.m_type) { return false; } if (!HasParent()) { return false; } if (traits[m_type].prefixmode != 1) { if (cmpNoCase ) { if( m_data->m_prefix && !path.m_data->m_prefix ) { return false; } else if( !m_data->m_prefix && path.m_data->m_prefix ) { return false; } else if( m_data->m_prefix && path.m_data->m_prefix && fz::stricmp(*m_data->m_prefix, *path.m_data->m_prefix) ) { return false; } } if (!cmpNoCase && m_data->m_prefix != path.m_data->m_prefix) return false; } // On MVS, dirs like 'FOO.BAR' without trailing dot cannot have // subdirectories if (traits[m_type].prefixmode == 1 && !path.m_data->m_prefix) return false; tConstSegmentIter iter1 = m_data->m_segments.begin(); tConstSegmentIter iter2 = path.m_data->m_segments.begin(); while (iter1 != m_data->m_segments.end()) { if (iter2 == path.m_data->m_segments.end()) { return true; } if (cmpNoCase) { if (fz::stricmp(*iter1, *iter2)) { return false; } } else if (*iter1 != *iter2) { return false; } ++iter1; ++iter2; } return false; }
bool CServerPath::operator==(const CServerPath &op) const { if (empty() != op.empty()) return false; else if (m_type != op.m_type) return false; else if (m_data != op.m_data) return false; return true; }
bool CRemoteTreeView::ListExpand(wxTreeItemId item) { const CServerPath path = GetPathFromItem(item); wxASSERT(!path.empty()); if (path.empty()) return false; CDirectoryListing listing; if (m_pState->m_pEngine->CacheLookup(path, listing) == FZ_REPLY_OK) RefreshItem(item, listing, false); else { SetItemImages(item, true); wxTreeItemId child = GetLastChild(item); if (!child || GetItemText(child).empty()) return false; } return true; }
void CPathCache::Store(CServer const& server, CServerPath const& target, CServerPath const& source, wxString const& subdir) { scoped_lock lock(mutex_); wxASSERT(!target.empty() && !source.empty()); tCacheIterator iter = m_cache.find(server); if (iter == m_cache.cend()) #if HAVE_MAP_EMPLACE iter = m_cache.emplace(std::make_pair(server, tServerCache())).first; #else iter = m_cache.insert(std::make_pair(server, tServerCache())).first; #endif tServerCache &serverCache = iter->second; CSourcePath sourcePath; sourcePath.source = source; sourcePath.subdir = subdir; serverCache[sourcePath] = target; }
int CNewBookmarkDialog::Run(const wxString &local_path, const CServerPath &remote_path) { if (!Load(m_parent, _T("ID_NEWBOOKMARK"))) return wxID_CANCEL; XRCCTRL(*this, "ID_LOCALPATH", wxTextCtrl)->ChangeValue(local_path); if (!remote_path.empty()) XRCCTRL(*this, "ID_REMOTEPATH", wxTextCtrl)->ChangeValue(remote_path.GetPath()); if (!m_server) XRCCTRL(*this, "ID_TYPE_SITE", wxRadioButton)->Enable(false); return ShowModal(); }
void CControlSocket::InvalidateCurrentWorkingDir(const CServerPath& path) { wxASSERT(!path.empty()); if (m_CurrentPath.empty()) return; if (m_CurrentPath == path || path.IsParentOf(m_CurrentPath, false)) { if (m_pCurOpData) m_invalidateCurrentPath = true; else m_CurrentPath.clear(); } }
void CRemoteTreeView::OnSelectionChanged(wxTreeEvent& event) { if (event.GetItem() != m_ExpandAfterList) m_ExpandAfterList = wxTreeItemId(); if (m_busy) return; if (!m_pState->IsRemoteIdle()) { wxBell(); return; } wxTreeItemId item = event.GetItem(); if (!item) return; const CServerPath path = GetPathFromItem(item); wxASSERT(!path.empty()); if (path.empty()) return; m_pState->ChangeRemoteDir(path); }
bool CControlSocket::ParsePwdReply(wxString reply, bool unquoted /*=false*/, const CServerPath& defaultPath /*=CServerPath()*/) { if (!unquoted) { int pos1 = reply.Find('"'); int pos2 = reply.Find('"', true); if (pos1 == -1 || pos1 >= pos2) { pos1 = reply.Find('\''); pos2 = reply.Find('\'', true); if (pos1 != -1 && pos1 < pos2) LogMessage(__TFILE__, __LINE__, this, MessageType::Debug_Info, _T("Broken server sending single-quoted path instead of double-quoted path.")); } if (pos1 == -1 || pos1 >= pos2) { LogMessage(__TFILE__, __LINE__, this, MessageType::Debug_Info, _T("Broken server, no quoted path found in pwd reply, trying first token as path")); pos1 = reply.Find(' '); if (pos1 != -1) { reply = reply.Mid(pos1 + 1); pos2 = reply.Find(' '); if (pos2 != -1) reply = reply.Left(pos2); } else reply.clear(); } else { reply = reply.Mid(pos1 + 1, pos2 - pos1 - 1); reply.Replace(_T("\"\""), _T("\"")); } } m_CurrentPath.SetType(m_pCurrentServer->GetType()); if (reply.empty() || !m_CurrentPath.SetPath(reply)) { if (reply.empty()) LogMessage(MessageType::Error, _("Server returned empty path.")); else LogMessage(MessageType::Error, _("Failed to parse returned path.")); if (!defaultPath.empty()) { LogMessage(MessageType::Debug_Warning, _T("Assuming path is '%s'."), defaultPath.GetPath()); m_CurrentPath = defaultPath; return true; } return false; } return true; }
CServerPath CPathCache::Lookup(CServer const& server, CServerPath const& source, wxString const& subdir) { scoped_lock lock(mutex_); const tCacheConstIterator iter = m_cache.find(server); if (iter == m_cache.end()) return CServerPath(); CServerPath result = Lookup(iter->second, source, subdir); if (result.empty()) m_misses++; else m_hits++; return result; }
// 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); }
void CRemoteTreeView::OnMenuDelete(wxCommandEvent&) { if (!m_pState->IsRemoteIdle()) return; if (!m_contextMenuItem) return; const CServerPath& path = GetPathFromItem(m_contextMenuItem); if (path.empty()) return; if (wxMessageBoxEx(_("Really delete all selected files and/or directories from the server?"), _("Confirmation needed"), wxICON_QUESTION | wxYES_NO, this) != wxYES) return; const bool hasParent = path.HasParent(); CRecursiveOperation* pRecursiveOperation = m_pState->GetRecursiveOperationHandler(); CServerPath startDir; if (hasParent) { const wxString& name = GetItemText(m_contextMenuItem); startDir = path.GetParent(); pRecursiveOperation->AddDirectoryToVisit(startDir, name); } else { startDir = path; pRecursiveOperation->AddDirectoryToVisit(startDir, _T("")); } CServerPath currentPath; const wxTreeItemId selected = GetSelection(); if (selected) currentPath = GetPathFromItem(selected); if (!currentPath.empty() && (path == currentPath || path.IsParentOf(currentPath, false))) currentPath = startDir; CFilterManager filter; pRecursiveOperation->StartRecursiveOperation(CRecursiveOperation::recursive_delete, startDir, filter.GetActiveFilters(false), !hasParent, currentPath); }
void CRemoteRecursiveOperation::StartRecursiveOperation(OperationMode mode, ActiveFilters const& filters, CServerPath const& finalDir, bool immediate) { wxCHECK_RET(m_operationMode == recursive_none, _T("StartRecursiveOperation called with m_operationMode != recursive_none")); wxCHECK_RET(m_state.IsRemoteConnected(), _T("StartRecursiveOperation while disconnected")); wxCHECK_RET(!finalDir.empty(), _T("Empty final dir in recursive operation")); if (mode == recursive_chmod && !m_pChmodDlg) { return; } if ((mode == recursive_transfer || mode == recursive_transfer_flatten) && !m_pQueue) { return; } if (recursion_roots_.empty()) { // Nothing to do in this case return; } m_processedFiles = 0; m_processedDirectories = 0; m_immediate = immediate; m_operationMode = mode; if ((mode == CRecursiveOperation::recursive_transfer || mode == CRecursiveOperation::recursive_transfer_flatten) && immediate) { m_actionAfterBlocker = m_pQueue->GetActionAfterBlocker(); } m_state.NotifyHandlers(STATECHANGE_REMOTE_IDLE); m_state.NotifyHandlers(STATECHANGE_REMOTE_RECURSION_STATUS); m_filters = filters; NextOperation(); }
void CRemoteTreeView::ApplyFilters(bool resort) { std::list<struct _parents> parents; const wxTreeItemId root = GetRootItem(); wxTreeItemIdValue cookie; for (wxTreeItemId child = GetFirstChild(root, cookie); child; child = GetNextSibling(child)) { CServerPath path = GetPathFromItem(child); if (path.empty()) continue; struct _parents dir; dir.item = child; dir.path = path; parents.push_back(dir); } CFilterManager filter; while (!parents.empty()) { struct _parents parent = parents.back(); parents.pop_back(); if (resort) { SortChildren(parent.item); } CDirectoryListing listing; if (m_pState->m_pEngine->CacheLookup(parent.path, listing) == FZ_REPLY_OK) RefreshItem(parent.item, listing, false); else if (filter.HasActiveFilters()) { for (wxTreeItemId child = GetFirstChild(parent.item, cookie); child; child = GetNextSibling(child)) { CServerPath path = GetPathFromItem(child); if (path.empty()) continue; if (filter.FilenameFiltered(GetItemText(child), path.GetPath(), true, -1, false, 0, CDateTime())) { wxTreeItemId sel = GetSelection(); while (sel && sel != child) sel = GetItemParent(sel); if (!sel) { Delete(child); continue; } } struct _parents dir; dir.item = child; dir.path = path; parents.push_back(dir); } // The stuff below has already been done above in this one case continue; } for (wxTreeItemId child = GetFirstChild(parent.item, cookie); child; child = GetNextSibling(child)) { CServerPath path = GetPathFromItem(child); if (path.empty()) continue; struct _parents dir; dir.item = child; dir.path = path; parents.push_back(dir); } } }
CServerPath CServerPath::GetCommonParent(const CServerPath& path) const { if (*this == path) { return *this; } if (empty() || path.empty()) { return CServerPath(); } if (m_type != path.m_type || (!traits[m_type].prefixmode && m_data->m_prefix != path.m_data->m_prefix)) { return CServerPath(); } if (!HasParent()) { if (path.IsSubdirOf(*this, false)) { return *this; } else { return CServerPath(); } } else if (!path.HasParent()) { if (IsSubdirOf(path, false)) { return path; } else { return CServerPath(); } } CServerPath parent; parent.m_type = m_type; CServerPathData& parentData = parent.m_data.get(); tConstSegmentIter last = m_data->m_segments.end(); tConstSegmentIter last2 = path.m_data->m_segments.end(); if (traits[m_type].prefixmode == 1) { if (!m_data->m_prefix) { --last; } if (!path.m_data->m_prefix) { --last2; } parentData.m_prefix = GetParent().m_data->m_prefix; } else parentData.m_prefix = m_data->m_prefix; tConstSegmentIter iter = m_data->m_segments.begin(); tConstSegmentIter iter2 = path.m_data->m_segments.begin(); while (iter != last && iter2 != last2) { if (*iter != *iter2) { if (!traits[m_type].has_root && parentData.m_segments.empty()) { return CServerPath(); } else { return parent; } } parentData.m_segments.push_back(*iter); ++iter; ++iter2; } 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); }
recursion_root::recursion_root(CServerPath const& start_dir, bool allow_parent) : m_remoteStartDir(start_dir) , m_allowParent(allow_parent) { wxASSERT_MSG(!start_dir.empty(), _T("Empty startDir in recursion_root constructor")); }
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 }
virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def) { if (def == wxDragError || def == wxDragNone || def == wxDragCancel) return def; wxTreeItemId hit = GetHit(wxPoint(x, y)); if (!hit) return wxDragNone; CServerPath path = m_pRemoteTreeView->GetPathFromItem(hit); if (path.empty()) return wxDragNone; if (!GetData()) return wxDragError; CDragDropManager* pDragDropManager = CDragDropManager::Get(); if (pDragDropManager) pDragDropManager->pDropTarget = m_pRemoteTreeView; if (m_pDataObject->GetReceivedFormat() == m_pFileDataObject->GetFormat()) m_pRemoteTreeView->m_pState->UploadDroppedFiles(m_pFileDataObject, path, false); else { if (m_pRemoteDataObject->GetProcessId() != (int)wxGetProcessId()) { wxMessageBoxEx(_("Drag&drop between different instances of FileZilla has not been implemented yet.")); return wxDragNone; } if (!m_pRemoteTreeView->m_pState->GetServer() || !m_pRemoteDataObject->GetServer().EqualsNoPass(*m_pRemoteTreeView->m_pState->GetServer())) { wxMessageBoxEx(_("Drag&drop between different servers has not been implemented yet.")); return wxDragNone; } // Make sure path path is valid if (path == m_pRemoteDataObject->GetServerPath()) { wxMessageBoxEx(_("Source and path of the drop operation are identical")); return wxDragNone; } const std::list<CRemoteDataObject::t_fileInfo>& files = m_pRemoteDataObject->GetFiles(); for (std::list<CRemoteDataObject::t_fileInfo>::const_iterator iter = files.begin(); iter != files.end(); ++iter) { const CRemoteDataObject::t_fileInfo& info = *iter; if (info.dir) { CServerPath dir = m_pRemoteDataObject->GetServerPath(); dir.AddSegment(info.name); if (dir == path) return wxDragNone; else if (dir.IsParentOf(path, false)) { wxMessageBoxEx(_("A directory cannot be dragged into one of its subdirectories.")); return wxDragNone; } } } for (std::list<CRemoteDataObject::t_fileInfo>::const_iterator iter = files.begin(); iter != files.end(); ++iter) { const CRemoteDataObject::t_fileInfo& info = *iter; m_pRemoteTreeView->m_pState->m_pCommandQueue->ProcessCommand( new CRenameCommand(m_pRemoteDataObject->GetServerPath(), info.name, path, info.name) ); } return wxDragNone; } return def; }