예제 #1
0
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;
		}
	}
}
예제 #2
0
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();
}
예제 #3
0
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;
}
예제 #4
0
// 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();
}
예제 #6
0
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;
}
예제 #8
0
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();
}
예제 #9
0
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;
}
예제 #10
0
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;
}
예제 #11
0
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;
}
예제 #12
0
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;
}
예제 #13
0
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();
}
예제 #14
0
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();
	}
}
예제 #15
0
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);
}
예제 #16
0
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;
}
예제 #17
0
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;
}
예제 #18
0
// 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);

}
예제 #19
0
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();
}
예제 #21
0
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);
		}
	}
}
예제 #22
0
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;
}
예제 #23
0
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"));
}
예제 #25
0
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
}
예제 #26
0
	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;
	}