Try to avoid a NullReferenceException:
[cyberduck.git] / source / ch / cyberduck / ui / controller / BrowserController.cs
blobf8611f0cf3f1ecf2ef57f8e1a149a921cbd370c7
1 //
2 // Copyright (c) 2010-2014 Yves Langisch. All rights reserved.
3 // http://cyberduck.ch/
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // Bug fixes, suggestions and comments should be sent to:
16 // yves@cyberduck.ch
17 //
19 using System;
20 using System.Collections.Generic;
21 using System.Collections.ObjectModel;
22 using System.Collections.Specialized;
23 using System.IO;
24 using System.Windows.Forms;
25 using BrightIdeasSoftware;
26 using ch.cyberduck.core;
27 using ch.cyberduck.core.bonjour;
28 using ch.cyberduck.core.cdn;
29 using ch.cyberduck.core.editor;
30 using ch.cyberduck.core.exception;
31 using ch.cyberduck.core.features;
32 using ch.cyberduck.core.local;
33 using ch.cyberduck.core.pasteboard;
34 using ch.cyberduck.core.preferences;
35 using ch.cyberduck.core.serializer;
36 using ch.cyberduck.core.sftp;
37 using ch.cyberduck.core.ssl;
38 using ch.cyberduck.core.threading;
39 using ch.cyberduck.core.transfer;
40 using ch.cyberduck.core.worker;
41 using ch.cyberduck.ui.browser;
42 using ch.cyberduck.ui.comparator;
43 using Ch.Cyberduck.Core;
44 using Ch.Cyberduck.Core.Local;
45 using Ch.Cyberduck.Ui.Controller.Threading;
46 using Ch.Cyberduck.Ui.Winforms;
47 using Ch.Cyberduck.Ui.Winforms.Taskdialog;
48 using java.lang;
49 using java.util;
50 using org.apache.log4j;
51 using StructureMap;
52 using Application = ch.cyberduck.core.local.Application;
53 using Boolean = java.lang.Boolean;
54 using Exception = System.Exception;
55 using Path = ch.cyberduck.core.Path;
56 using String = System.String;
57 using StringBuilder = System.Text.StringBuilder;
59 namespace Ch.Cyberduck.Ui.Controller
61 public class BrowserController : WindowController<IBrowserView>, TranscriptListener, CollectionListener,
62 ProgressListener
64 public delegate void CallbackDelegate();
66 public delegate bool DialogCallbackDelegate(DialogResult result);
68 internal static readonly Filter HiddenFilter = new RegexFilter();
69 private static readonly Logger Log = Logger.getLogger(typeof (BrowserController).FullName);
70 private static readonly Filter NullFilter = new NullFilter();
71 protected static string DEFAULT = LocaleFactory.localizedString("Default");
72 private readonly BookmarkCollection _bookmarkCollection = BookmarkCollection.defaultCollection();
73 private readonly BookmarkModel _bookmarkModel;
74 private readonly TreeBrowserModel _browserModel;
75 private readonly PathCache _cache = new PathCache(PreferencesFactory.get().getInteger("browser.cache.size"));
76 private readonly ListProgressListener _limitListener;
77 private readonly Navigation _navigation = new Navigation();
78 private readonly IList<FileSystemWatcher> _temporaryWatcher = new List<FileSystemWatcher>();
79 private Comparator _comparator = new NullComparator();
80 private String _dropFolder; // holds the drop folder of the current drag operation
81 private InfoController _inspector;
82 private BrowserView _lastBookmarkView = BrowserView.Bookmark;
83 private PathPasteboard _pasteboard;
84 private bool _showHiddenFiles;
86 public BrowserController(IBrowserView view)
88 View = view;
90 ShowHiddenFiles = PreferencesFactory.get().getBoolean("browser.showHidden");
92 _limitListener = new DialogLimitedListProgressListener(this);
93 _browserModel = new TreeBrowserModel(this, _cache, _limitListener);
94 _bookmarkModel = new BookmarkModel(this, _bookmarkCollection);
95 View.ViewClosedEvent += delegate { _bookmarkModel.Source = null; };
97 //default view is the bookmark view
98 ToggleView(BrowserView.Bookmark);
99 View.StopActivityAnimation();
101 View.SetComparator += View_SetComparator;
102 View.ChangeBrowserView += View_ChangeBrowserView;
104 View.QuickConnect += View_QuickConnect;
105 View.BrowserDoubleClicked += View_BrowserDoubleClicked;
106 View.BrowserSelectionChanged += View_BrowserSelectionChanged;
107 View.PathSelectionChanged += View_PathSelectionChanged;
108 View.EditEvent += View_EditEvent;
109 View.ItemsChanged += View_ItemsChanged;
111 View.ShowTransfers += View_ShowTransfers;
113 View.BrowserCanDrop += View_BrowserCanDrop;
114 View.HostCanDrop += View_HostCanDrop;
115 View.BrowserModelCanDrop += View_BrowserModelCanDrop;
116 View.HostModelCanDrop += View_HostModelCanDrop;
117 View.BrowserDropped += View_BrowserDropped;
118 View.HostDropped += View_HostDropped;
119 View.HostModelDropped += View_HostModelDropped;
120 View.BrowserModelDropped += View_BrowserModelDropped;
121 View.BrowserDrag += View_BrowserDrag;
122 View.HostDrag += View_HostDrag;
123 View.BrowserEndDrag += View_BrowserEndDrag;
124 View.HostEndDrag += View_HostEndDrag;
125 View.SearchFieldChanged += View_SearchFieldChanged;
128 View.ContextMenuEnabled += View_ContextMenuEnabled;
130 #region Commands - File
132 View.NewBrowser += View_NewBrowser;
133 View.ValidateNewBrowser += View_ValidateNewBrowser;
134 View.OpenConnection += View_OpenConnection;
135 View.ValidateOpenConnection += () => true;
136 View.NewDownload += View_NewDownload;
137 View.ValidateNewDownload += () => false; //todo implement
138 View.NewFolder += View_NewFolder;
139 View.ValidateNewFolder += View_ValidateNewFolder;
140 View.NewFile += View_NewFile;
141 View.ValidateNewFile += View_ValidateNewFile;
142 View.NewSymbolicLink += View_NewSymbolicLink;
143 View.ValidateNewSymbolicLink += View_ValidateNewSymbolicLink;
144 View.RenameFile += View_RenameFile;
145 View.ValidateRenameFile += View_ValidateRenameFile;
146 View.DuplicateFile += View_DuplicateFile;
147 View.ValidateDuplicateFile += View_ValidateDuplicateFile;
148 View.OpenUrl += View_OpenUrl;
149 View.ValidateOpenWebUrl += View_ValidateOpenWebUrl;
150 View.ValidateEditWith += View_ValidateEditWith;
151 View.ShowInspector += View_ShowInspector;
152 View.ValidateShowInspector += View_ValidateShowInspector;
153 View.Download += View_Download;
154 View.ValidateDownload += View_ValidateDownload;
155 View.DownloadAs += View_DownloadAs;
156 View.ValidateDownloadAs += View_ValidateDownloadAs;
157 View.DownloadTo += View_DownloadTo;
158 View.ValidateDownloadTo += View_ValidateDownload; //use same validation handler
159 View.Upload += View_Upload;
160 View.ValidateUpload += View_ValidateUpload;
161 View.Synchronize += View_Synchronize;
162 View.ValidateSynchronize += View_ValidateSynchronize;
163 View.Delete += View_Delete;
164 View.ValidateDelete += View_ValidateDelete;
165 View.RevertFile += View_RevertFile;
166 View.ValidateRevertFile += View_ValidateRevertFile;
167 View.GetArchives += View_GetArchives;
168 View.GetCopyUrls += View_GetCopyUrls;
169 View.GetOpenUrls += View_GetOpenUrls;
170 View.CreateArchive += View_CreateArchive;
171 View.ValidateCreateArchive += View_ValidateCreateArchive;
172 View.ExpandArchive += View_ExpandArchive;
173 View.ValidateExpandArchive += View_ValidateExpandArchive;
175 #endregion
177 #region Commands - Edit
179 View.Cut += View_Cut;
180 View.ValidateCut += View_ValidateCut;
181 View.Copy += View_Copy;
182 View.ValidateCopy += View_ValidateCopy;
183 View.Paste += View_Paste;
184 View.ValidatePaste += View_ValidatePaste;
185 View.ShowPreferences += View_ShowPreferences;
187 #endregion
189 #region Commands - View
191 View.ToggleToolbar += View_ToggleToolbar;
192 View.ShowHiddenFiles += View_ShowHiddenFiles;
193 View.ValidateTextEncoding += View_ValidateTextEncoding;
194 View.EncodingChanged += View_EncodingChanged;
195 View.ToggleLogDrawer += View_ToggleLogDrawer;
197 #endregion
199 #region Commands - Go
201 View.RefreshBrowser += View_RefreshBrowser;
202 View.ValidateRefresh += View_ValidateRefresh;
203 View.GotoFolder += View_GotoFolder;
204 View.ValidateGotoFolder += View_ValidateGotoFolder;
205 View.HistoryBack += View_HistoryBack;
206 View.ValidateHistoryBack += View_ValidateHistoryBack;
207 View.HistoryForward += View_HistoryForward;
208 View.ValidateHistoryForward += View_ValidateHistoryForward;
209 View.FolderUp += View_FolderUp;
210 View.ValidateFolderUp += View_ValidateFolderUp;
211 View.FolderInside += View_FolderInside;
212 View.ValidateFolderInside += View_ValidateFolderInside;
213 View.Search += View_Search;
214 View.SendCustomCommand += View_SendCustomCommand;
215 View.ValidateSendCustomCommand += View_ValidateSendCustomCommand;
216 View.OpenInTerminal += View_OpenInTerminal;
217 View.ValidateOpenInTerminal += View_ValidateOpenInTerminal;
218 View.Stop += View_Disconnect;
219 View.ValidateStop += View_ValidateStop;
220 View.Disconnect += View_Disconnect;
221 View.ValidateDisconnect += View_ValidateDisconnect;
223 #endregion
225 #region Commands - Bookmark
227 View.ToggleBookmarks += View_ToggleBookmarks;
228 View.SortBookmarksByHostname += View_SortBookmarksByHostname;
229 View.SortBookmarksByNickname += View_SortBookmarksByNickname;
230 View.SortBookmarksByProtocol += View_SortBookmarksByProtocol;
232 View.ConnectBookmark += View_ConnectBookmark;
233 View.ValidateConnectBookmark += View_ValidateConnectBookmark;
234 View.NewBookmark += View_NewBookmark;
235 View.ValidateNewBookmark += View_ValidateNewBookmark;
236 View.EditBookmark += View_EditBookmark;
237 View.ValidateEditBookmark += View_ValidateEditBookmark;
238 View.DeleteBookmark += View_DeleteBookmark;
239 View.ValidateDeleteBookmark += View_ValidateDeleteBookmark;
240 View.DuplicateBookmark += View_DuplicateBookmark;
241 View.ValidateDuplicateBookmark += View_ValidateDuplicateBookmark;
243 #endregion
245 #region Browser model delegates
247 View.ModelCanExpandDelegate = _browserModel.CanExpand;
248 View.ModelChildrenGetterDelegate = _browserModel.ChildrenGetter;
249 View.ModelFilenameGetter = _browserModel.GetName;
250 View.ModelIconGetter = _browserModel.GetIcon;
251 View.ModelSizeGetter = _browserModel.GetSize;
252 View.ModelSizeAsStringGetter = _browserModel.GetSizeAsString;
253 View.ModelModifiedGetter = _browserModel.GetModified;
254 View.ModelModifiedAsStringGetter = _browserModel.GetModifiedAsString;
255 View.ModelOwnerGetter = _browserModel.GetOwner;
256 View.ModelGroupGetter = _browserModel.GetGroup;
257 View.ModelPermissionsGetter = _browserModel.GetPermission;
258 View.ModelKindGetter = _browserModel.GetKind;
259 View.ModelActiveGetter = _browserModel.GetActive;
260 View.ModelExtensionGetter = _browserModel.GetExtension;
261 View.ModelRegionGetter = _browserModel.GetRegion;
262 View.ModelVersionGetter = _browserModel.GetVersion;
264 #endregion
266 #region Bookmark model delegates
268 View.BookmarkImageGetter = _bookmarkModel.GetBookmarkImage;
269 View.BookmarkNicknameGetter = _bookmarkModel.GetNickname;
270 View.BookmarkHostnameGetter = _bookmarkModel.GetHostname;
271 View.BookmarkUrlGetter = _bookmarkModel.GetUrl;
272 View.BookmarkNotesGetter = _bookmarkModel.GetNotes;
273 View.BookmarkStatusImageGetter = _bookmarkModel.GetBookmarkStatusImage;
275 #endregion
277 _bookmarkCollection.addListener(this);
278 View.ViewClosedEvent += delegate { _bookmarkCollection.removeListener(this); };
280 PopulateQuickConnect();
281 PopulateEncodings();
282 UpdateOpenIcon();
284 View.ToolbarVisible = PreferencesFactory.get().getBoolean("browser.toolbar");
285 View.LogDrawerVisible = PreferencesFactory.get().getBoolean("browser.transcript.open");
287 View.GetEditorsForSelection += View_GetEditorsForSelection;
288 View.GetBookmarks += View_GetBookmarks;
289 View.GetHistory += View_GetHistory;
290 View.GetBonjourHosts += View_GetBonjourHosts;
291 View.ClearHistory += View_ClearHistory;
292 View.ShowCertificate += View_Certificate;
294 View.ValidatePathsCombobox += View_ValidatePathsCombobox;
295 View.ValidateSearchField += View_ValidateSearchField;
297 View.Exit += View_Exit;
298 View.SetBookmarkModel(_bookmarkCollection, null);
301 public BrowserController() : this(ObjectFactory.GetInstance<IBrowserView>())
305 /// <summary>
306 /// The first selected path found or null if there is no selection
307 /// </summary>
308 public Path SelectedPath
312 IList<Path> selectedPaths = View.SelectedPaths;
313 if (selectedPaths.Count > 0)
315 return selectedPaths[0];
317 return null;
321 public Path Workdir { get; set; }
323 /// <summary>
325 /// </summary>
326 /// <value>
327 /// All selected paths or an empty list if there is no selection
328 /// </value>
329 public IList<Path> SelectedPaths
333 if (IsMounted())
335 return View.SelectedPaths;
337 return new List<Path>();
339 set { View.SelectedPaths = value; }
342 public bool ShowHiddenFiles
344 get { return _showHiddenFiles; }
347 FilenameFilter = value ? NullFilter : HiddenFilter;
348 _showHiddenFiles = value;
349 View.HiddenFilesVisible = _showHiddenFiles;
353 public PathCache Cache
355 get { return _cache; }
358 public Filter FilenameFilter { get; set; }
360 public Comparator FilenameComparator
362 get { return _comparator; }
363 set { _comparator = value; }
366 public Session Session { get; private set; }
368 public void collectionLoaded()
370 AsyncDelegate mainAction = delegate { ReloadBookmarks(); };
371 Invoke(mainAction);
374 public void collectionItemAdded(object obj)
376 AsyncDelegate mainAction = delegate { PopulateQuickConnect(); };
377 Invoke(mainAction);
380 public void collectionItemRemoved(object obj)
382 AsyncDelegate mainAction = delegate { PopulateQuickConnect(); };
383 Invoke(mainAction);
386 public void collectionItemChanged(object obj)
388 AsyncDelegate mainAction = delegate { PopulateQuickConnect(); };
389 Invoke(mainAction);
392 public override void message(string msg)
394 string label;
395 if (Utils.IsNotBlank(msg))
397 label = msg;
399 else
401 if (View.CurrentView == BrowserView.Bookmark || View.CurrentView == BrowserView.History ||
402 View.CurrentView == BrowserView.Bonjour)
404 label = String.Format("{0} {1}", View.NumberOfBookmarks, LocaleFactory.localizedString("Bookmarks"));
406 else
408 if (IsConnected())
410 label = String.Format(LocaleFactory.localizedString("{0} Files"), View.NumberOfFiles);
412 else
414 label = String.Empty;
418 AsyncDelegate updateLabel = delegate { View.StatusLabel = label; };
419 Invoke(updateLabel);
422 public override void log(bool request, string transcript)
424 if (View.LogDrawerVisible)
426 AsyncDelegate mainAction = delegate { View.AddTranscriptEntry(request, transcript); };
427 Invoke(mainAction);
431 private void View_NewSymbolicLink()
433 CreateSymlinkController slc =
434 new CreateSymlinkController(ObjectFactory.GetInstance<ICreateSymlinkPromptView>(), this);
435 slc.Show();
438 private bool View_ValidateNewSymbolicLink()
440 return IsMounted() && Session.getFeature(typeof (Symlink)) != null && SelectedPaths.Count == 1;
443 private void View_SortBookmarksByProtocol()
445 BookmarkCollection.defaultCollection().sortByProtocol();
446 ReloadBookmarks();
449 private void View_SortBookmarksByNickname()
451 BookmarkCollection.defaultCollection().sortByNickname();
452 ReloadBookmarks();
455 private void View_SortBookmarksByHostname()
457 BookmarkCollection.defaultCollection().sortByHostname();
458 ReloadBookmarks();
461 private bool View_ValidateOpenInTerminal()
463 return IsMounted() && Session is SFTPSession &&
464 File.Exists(PreferencesFactory.get().getProperty("terminal.command.ssh"));
467 private void View_OpenInTerminal()
469 Host host = Session.getHost();
470 Path workdir = null;
471 if (SelectedPaths.Count == 1)
473 Path selected = SelectedPath;
474 if (selected.isDirectory())
476 workdir = selected;
479 if (null == workdir)
481 workdir = Workdir;
483 new SshTerminalService().open(host, workdir);
486 private void View_SetComparator(BrowserComparator comparator)
488 if (!comparator.equals(_comparator))
490 _comparator = comparator;
491 ReloadData(true);
495 private IList<Application> View_GetEditorsForSelection()
497 Path p = SelectedPath;
498 if (null != p)
500 if (p.isFile())
502 return Utils.ConvertFromJavaList<Application>(EditorFactory.instance().getEditors(p.getName()), null);
505 return new List<Application>();
508 private bool View_ValidateNewBrowser()
510 return IsMounted();
513 private List<KeyValuePair<String, List<String>>> View_GetCopyUrls()
515 List<KeyValuePair<String, List<String>>> items = new List<KeyValuePair<String, List<String>>>();
516 IList<Path> selected = View.SelectedPaths;
517 if (selected.Count == 0)
519 items.Add(new KeyValuePair<string, List<String>>(LocaleFactory.localizedString("None"),
520 new List<string>()));
522 else
524 UrlProvider urlProvider = ((UrlProvider) Session.getFeature(typeof (UrlProvider)));
525 if (urlProvider != null)
527 for (int i = 0; i < urlProvider.toUrl(SelectedPath).size(); i++)
529 DescriptiveUrl descUrl = (DescriptiveUrl) urlProvider.toUrl(SelectedPath).toArray()[i];
530 KeyValuePair<String, List<String>> entry =
531 new KeyValuePair<string, List<string>>(descUrl.getHelp(), new List<string>());
532 items.Add(entry);
533 foreach (Path path in selected)
535 entry.Value.Add(((DescriptiveUrl) urlProvider.toUrl(path).toArray()[i]).getUrl());
539 UrlProvider distributionConfiguration =
540 ((UrlProvider) Session.getFeature(typeof (DistributionConfiguration)));
541 if (distributionConfiguration != null)
543 for (int i = 0; i < distributionConfiguration.toUrl(SelectedPath).size(); i++)
545 DescriptiveUrl descUrl =
546 (DescriptiveUrl) distributionConfiguration.toUrl(SelectedPath).toArray()[i];
547 KeyValuePair<String, List<String>> entry =
548 new KeyValuePair<string, List<string>>(descUrl.getHelp(), new List<string>());
549 items.Add(entry);
550 foreach (Path path in selected)
552 entry.Value.Add(
553 ((DescriptiveUrl) distributionConfiguration.toUrl(path).toArray()[i]).getUrl());
558 return items;
561 private bool IsBrowser()
563 return View.CurrentView == BrowserView.File;
566 private IList<KeyValuePair<string, List<string>>> View_GetOpenUrls()
568 IList<KeyValuePair<String, List<String>>> items = new List<KeyValuePair<String, List<String>>>();
569 IList<Path> selected = View.SelectedPaths;
570 if (selected.Count == 0)
572 items.Add(new KeyValuePair<string, List<String>>(LocaleFactory.localizedString("None"),
573 new List<string>()));
575 else
577 DescriptiveUrlBag urls =
578 ((UrlProvider) Session.getFeature(typeof (UrlProvider))).toUrl(SelectedPath)
579 .filter(DescriptiveUrl.Type.http, DescriptiveUrl.Type.cname, DescriptiveUrl.Type.cdn,
580 DescriptiveUrl.Type.signed, DescriptiveUrl.Type.authenticated, DescriptiveUrl.Type.torrent);
581 for (int i = 0; i < urls.size(); i++)
583 DescriptiveUrl descUrl = (DescriptiveUrl) urls.toArray()[i];
584 KeyValuePair<String, List<String>> entry = new KeyValuePair<string, List<string>>(
585 descUrl.getHelp(), new List<string>());
586 items.Add(entry);
588 foreach (Path path in selected)
590 entry.Value.Add(((DescriptiveUrl) urls.toArray()[i]).getUrl());
594 return items;
597 public void UpdateBookmarks()
599 View.UpdateBookmarks();
602 private bool View_ValidateDuplicateBookmark()
604 return _bookmarkModel.Source.allowsEdit() && View.SelectedBookmarks.Count == 1;
607 private void View_DuplicateBookmark()
609 ToggleView(BrowserView.Bookmark);
610 Host duplicate = new HostDictionary().deserialize(View.SelectedBookmark.serialize(SerializerFactory.get()));
611 // Make sure a new UUID is asssigned for duplicate
612 duplicate.setUuid(null);
613 AddBookmark(duplicate);
616 private void View_HostModelDropped(ModelDropEventArgs dropargs)
618 int sourceIndex = _bookmarkModel.Source.indexOf(dropargs.SourceModels[0]);
619 int destIndex = dropargs.DropTargetIndex;
620 if (dropargs.DropTargetLocation == DropTargetLocation.BelowItem)
622 destIndex++;
624 if (dropargs.Effect == DragDropEffects.Copy)
626 Host host =
627 new HostDictionary().deserialize(((Host) dropargs.SourceModels[0]).serialize(SerializerFactory.get()));
628 host.setUuid(null);
629 AddBookmark(host, destIndex);
631 if (dropargs.Effect == DragDropEffects.Move)
633 if (sourceIndex < destIndex)
635 destIndex--;
637 foreach (Host promisedDragBookmark in dropargs.SourceModels)
639 _bookmarkModel.Source.remove(promisedDragBookmark);
640 if (destIndex > _bookmarkModel.Source.size())
642 _bookmarkModel.Source.add(promisedDragBookmark);
644 else
646 _bookmarkModel.Source.add(destIndex, promisedDragBookmark);
648 //view.selectRowIndexes(NSIndexSet.indexSetWithIndex(row), false);
649 //view.scrollRowToVisible(row);
654 private void View_HostModelCanDrop(ModelDropEventArgs args)
656 if (!_bookmarkModel.Source.allowsEdit())
658 // Do not allow drags for non writable collections
659 args.Effect = DragDropEffects.None;
660 args.DropTargetLocation = DropTargetLocation.None;
661 return;
663 switch (args.DropTargetLocation)
665 case DropTargetLocation.BelowItem:
666 case DropTargetLocation.AboveItem:
667 if (args.SourceModels.Count > 1)
669 args.Effect = DragDropEffects.Move;
671 break;
672 default:
673 args.Effect = DragDropEffects.None;
674 args.DropTargetLocation = DropTargetLocation.None;
675 return;
679 private void View_HostDropped(OlvDropEventArgs e)
681 if (e.DataObject is DataObject && ((DataObject) e.DataObject).ContainsFileDropList())
683 DataObject data = (DataObject) e.DataObject;
685 if (e.DropTargetLocation == DropTargetLocation.Item)
687 IList<TransferItem> roots = new List<TransferItem>();
688 Host host = null;
689 foreach (string filename in data.GetFileDropList())
691 //check if we received at least one non-duck file
692 if (!".duck".Equals(Utils.GetSafeExtension(filename)))
694 // The bookmark this file has been dropped onto
695 Host destination = (Host) e.DropTargetItem.RowObject;
696 if (null == host)
698 host = destination;
700 Local local = LocalFactory.get(filename);
701 // Upload to the remote host this bookmark points to
702 roots.Add(
703 new TransferItem(
704 new Path(
705 new Path(PathNormalizer.normalize(destination.getDefaultPath(), true),
706 EnumSet.of(AbstractPath.Type.directory)), local.getName(),
707 EnumSet.of(AbstractPath.Type.file)), local));
710 if (roots.Count > 0)
712 UploadTransfer q = new UploadTransfer(host, Utils.ConvertToJavaList(roots));
713 // If anything has been added to the queue, then process the queue
714 if (q.getRoots().size() > 0)
716 TransferController.Instance.StartTransfer(q);
719 return;
722 if (e.DropTargetLocation == DropTargetLocation.AboveItem)
724 Host destination = (Host) e.DropTargetItem.RowObject;
725 foreach (string file in data.GetFileDropList())
727 _bookmarkModel.Source.add(_bookmarkModel.Source.indexOf(destination),
728 HostReaderFactory.get().read(LocalFactory.get(file)));
731 if (e.DropTargetLocation == DropTargetLocation.BelowItem)
733 Host destination = (Host) e.DropTargetItem.RowObject;
734 foreach (string file in data.GetFileDropList())
736 _bookmarkModel.Source.add(_bookmarkModel.Source.indexOf(destination) + 1,
737 HostReaderFactory.get().read(LocalFactory.get(file)));
740 if (e.DropTargetLocation == DropTargetLocation.Background)
742 foreach (string file in data.GetFileDropList())
744 _bookmarkModel.Source.add(HostReaderFactory.get().read(LocalFactory.get(file)));
750 private void View_HostCanDrop(OlvDropEventArgs args)
752 if (!_bookmarkModel.Source.allowsEdit())
754 // Do not allow drags for non writable collections
755 args.Effect = DragDropEffects.None;
756 args.DropTargetLocation = DropTargetLocation.None;
757 return;
760 DataObject dataObject = (DataObject) args.DataObject;
761 if (dataObject.ContainsFileDropList())
763 //check if all files are .duck files
764 foreach (string file in dataObject.GetFileDropList())
766 string ext = Utils.GetSafeExtension(file);
767 if (!".duck".Equals(ext))
769 //if at least one non-duck file we prepare for uploading
770 args.Effect = DragDropEffects.Copy;
771 if (args.DropTargetLocation == DropTargetLocation.Item)
773 Host destination = (Host) args.DropTargetItem.RowObject;
774 (args.DataObject as DataObject).SetDropDescription((DropImageType) args.Effect,
775 "Upload to %1", BookmarkNameProvider.toString(destination));
777 args.DropTargetLocation = DropTargetLocation.Item;
778 return;
782 //at least one .duck file
783 args.Effect = DragDropEffects.Copy;
784 if (args.DropTargetLocation == DropTargetLocation.Item)
786 args.DropTargetLocation = DropTargetLocation.Background;
788 return;
790 args.Effect = DragDropEffects.None;
793 private void View_HostEndDrag(DataObject data)
795 RemoveTemporaryFiles(data);
796 RemoveTemporaryFilesystemWatcher();
799 private string CreateAndWatchTemporaryFile(FileSystemEventHandler del)
801 string tfile = System.IO.Path.Combine(System.IO.Path.GetTempPath(), Guid.NewGuid().ToString());
802 using (File.Create(tfile))
804 FileInfo tmpFile = new FileInfo(tfile);
805 tmpFile.Attributes |= FileAttributes.Hidden;
807 DriveInfo[] allDrives = DriveInfo.GetDrives();
808 foreach (DriveInfo d in allDrives)
810 if (d.IsReady && d.DriveType != DriveType.CDRom)
814 FileSystemWatcher watcher = new FileSystemWatcher(@d.Name, System.IO.Path.GetFileName(tfile));
815 watcher.BeginInit();
816 watcher.IncludeSubdirectories = true;
817 watcher.EnableRaisingEvents = true;
818 watcher.Created += del;
819 watcher.EndInit();
820 _temporaryWatcher.Add(watcher);
822 catch (Exception e)
824 Log.info(string.Format("Cannot watch drive {0}", d), e);
828 return tfile;
831 private DataObject View_HostDrag(ObjectListView list)
833 DataObject data = new DataObject(DataFormats.FileDrop,
834 new[]
836 CreateAndWatchTemporaryFile(delegate(object sender, FileSystemEventArgs args)
838 Invoke(delegate
840 _dropFolder = System.IO.Path.GetDirectoryName(args.FullPath);
841 foreach (Host host in
842 View.SelectedBookmarks)
844 string filename = BookmarkNameProvider.toString(host) + ".duck";
845 foreach (char c in
846 System.IO.Path.GetInvalidFileNameChars())
848 filename = filename.Replace(c.ToString(), String.Empty);
851 Local file = LocalFactory.get(_dropFolder, filename);
852 HostWriterFactory.get().write(host, file);
857 return data;
860 private void View_BrowserModelCanDrop(ModelDropEventArgs args)
862 if (IsMounted())
864 Path destination;
865 switch (args.DropTargetLocation)
867 case DropTargetLocation.Item:
868 destination = (Path) args.DropTargetItem.RowObject;
869 if (!destination.isDirectory())
871 //dragging over file
872 destination = destination.getParent();
874 break;
875 case DropTargetLocation.Background:
876 destination = Workdir;
877 break;
878 default:
879 args.Effect = DragDropEffects.None;
880 args.DropTargetLocation = DropTargetLocation.None;
881 return;
883 Touch feature = (Touch) Session.getFeature(typeof (Touch));
884 if (!feature.isSupported(destination))
886 args.Effect = DragDropEffects.None;
887 args.DropTargetLocation = DropTargetLocation.None;
888 return;
890 foreach (Path sourcePath in args.SourceModels)
892 if (args.ListView == args.SourceListView)
894 // Use drag action from user
896 else
898 // If copying between sessions is supported
899 args.Effect = DragDropEffects.Copy;
901 if (sourcePath.isDirectory() && sourcePath.equals(destination))
903 // Do not allow dragging onto myself.
904 args.Effect = DragDropEffects.None;
905 args.DropTargetLocation = DropTargetLocation.None;
906 return;
908 if (sourcePath.isDirectory() && destination.isChild(sourcePath))
910 // Do not allow dragging a directory into its own containing items
911 args.Effect = DragDropEffects.None;
912 args.DropTargetLocation = DropTargetLocation.None;
913 return;
915 if (sourcePath.isFile() && sourcePath.getParent().equals(destination))
917 // Moving file to the same destination makes no sense
918 args.Effect = DragDropEffects.None;
919 args.DropTargetLocation = DropTargetLocation.None;
920 return;
923 if (Workdir == destination)
925 args.DropTargetLocation = DropTargetLocation.Background;
927 else
929 args.DropTargetItem = args.ListView.ModelToItem(destination);
934 /// <summary>
935 /// A file dragged within the browser has been received
936 /// </summary>
937 /// <param name="dropargs"></param>
938 private void View_BrowserModelDropped(ModelDropEventArgs dropargs)
940 Path destination;
941 switch (dropargs.DropTargetLocation)
943 case DropTargetLocation.Item:
944 destination = (Path) dropargs.DropTargetItem.RowObject;
945 break;
946 case DropTargetLocation.Background:
947 destination = Workdir;
948 break;
949 default:
950 destination = null;
951 break;
953 if (null != destination)
955 IDictionary<Path, Path> files = new Dictionary<Path, Path>();
956 foreach (Path next in dropargs.SourceModels)
958 Path renamed = new Path(destination, next.getName(), next.getType());
959 files.Add(next, renamed);
961 if (files.Count > 0)
963 if (dropargs.Effect == DragDropEffects.Copy)
965 foreach (BrowserController controller in MainController.Browsers)
967 // Find source browser
968 if (controller.View.Browser.Equals(dropargs.SourceListView))
970 controller.transfer(
971 new CopyTransfer(controller.Session.getHost(), Session.getHost(),
972 Utils.ConvertToJavaMap(files)), new List<Path>(files.Values), false);
973 break;
977 if (dropargs.Effect == DragDropEffects.Move)
979 // The file should be renamed
980 RenamePaths(files);
986 private void View_Download()
988 Download(SelectedPaths, new DownloadDirectoryFinder().find(Session.getHost()));
991 private bool View_ValidateRevertFile()
993 if (IsMounted() && SelectedPaths.Count == 1)
995 return Session.getFeature(typeof (Versioning)) != null;
997 return false;
1000 private void View_RevertFile()
1002 RevertPaths(SelectedPaths);
1005 private void RevertPaths(IList<Path> files)
1007 Background(new RevertAction(this, files));
1010 private void View_ToggleBookmarks()
1012 if (View.CurrentView == BrowserView.File)
1014 View.CurrentView = _lastBookmarkView;
1016 else
1018 _lastBookmarkView = View.CurrentView;
1019 View.CurrentView = BrowserView.File;
1023 private bool View_ValidateSearchField()
1025 return IsMounted() || View.CurrentView != BrowserView.File;
1028 private bool View_ValidatePathsCombobox()
1030 return IsMounted();
1033 private void View_ItemsChanged()
1035 SetStatus();
1038 private void View_Certificate()
1040 if (Session is SSLSession)
1042 SSLSession secured = (SSLSession) Session;
1043 List certificates = secured.getAcceptedIssuers();
1044 CertificateStoreFactory.get().display(certificates);
1048 private void View_ClearHistory()
1050 HistoryCollection.defaultCollection().clear();
1053 private List<Host> View_GetBonjourHosts()
1055 List<Host> b = new List<Host>();
1056 foreach (Host h in RendezvousCollection.defaultCollection())
1058 b.Add(h);
1060 return b;
1063 private List<Host> View_GetHistory()
1065 List<Host> b = new List<Host>();
1066 foreach (Host h in HistoryCollection.defaultCollection())
1068 b.Add(h);
1070 return b;
1073 private List<Host> View_GetBookmarks()
1075 List<Host> b = new List<Host>();
1076 foreach (Host h in BookmarkCollection.defaultCollection())
1078 b.Add(h);
1080 return b;
1083 private void PopulateEncodings()
1085 List<string> list = new List<string>();
1086 list.AddRange(new DefaultCharsetProvider().availableCharsets());
1087 View.PopulateEncodings(list);
1088 View.SelectedEncoding = PreferencesFactory.get().getProperty("browser.charset.encoding");
1091 private void View_EncodingChanged(object sender, EncodingChangedArgs e)
1093 string encoding = e.Encoding;
1094 if (Utils.IsBlank(encoding))
1096 return;
1098 View.SelectedEncoding = encoding;
1099 if (IsMounted())
1101 if (Session.getEncoding().Equals(encoding))
1103 return;
1105 Session.getHost().setEncoding(encoding);
1106 Mount(Session.getHost());
1110 private void View_ConnectBookmark(object sender, ConnectBookmarkArgs connectBookmarkArgs)
1112 Mount(connectBookmarkArgs.Bookmark);
1115 private bool View_ValidateConnectBookmark()
1117 return View.SelectedBookmarks.Count == 1;
1120 private bool View_ValidateDeleteBookmark()
1122 return _bookmarkModel.Source.allowsDelete() && View.SelectedBookmarks.Count > 0;
1125 private bool View_ValidateEditBookmark()
1127 return _bookmarkModel.Source.allowsEdit() && View.SelectedBookmarks.Count == 1;
1130 private bool View_ValidateNewBookmark()
1132 return _bookmarkModel.Source.allowsAdd();
1135 private void View_ChangeBrowserView(object sender, ChangeBrowserViewArgs e)
1137 ToggleView(e.View);
1140 private void View_EditBookmark()
1142 if (View.SelectedBookmarks.Count == 1)
1144 BookmarkController.Factory.Create(View.SelectedBookmark).View.Show(View);
1148 private void View_NewBookmark()
1150 Host bookmark;
1151 if (IsMounted())
1153 Path selected = SelectedPath;
1154 if (null == selected || !selected.isDirectory())
1156 selected = Workdir;
1158 bookmark = new HostDictionary().deserialize(Session.getHost().serialize(SerializerFactory.get()));
1159 bookmark.setUuid(null);
1160 bookmark.setDefaultPath(selected.getAbsolute());
1162 else
1164 bookmark =
1165 new Host(
1166 ProtocolFactory.forName(PreferencesFactory.get().getProperty("connection.protocol.default")),
1167 PreferencesFactory.get().getProperty("connection.hostname.default"),
1168 PreferencesFactory.get().getInteger("connection.port.default"));
1170 ToggleView(BrowserView.Bookmark);
1171 AddBookmark(bookmark);
1174 public void AddBookmark(Host item)
1176 AddBookmark(item, -1);
1179 private void AddBookmark(Host item, int index)
1181 _bookmarkModel.Filter = null;
1182 if (index != -1)
1184 _bookmarkModel.Source.add(index, item);
1186 else
1188 _bookmarkModel.Source.add(item);
1190 View.SelectBookmark(item);
1191 View.EnsureBookmarkVisible(item);
1192 BookmarkController.Factory.Create(item).View.Show(View);
1195 private void View_DeleteBookmark()
1197 List<Host> selected = View.SelectedBookmarks;
1198 StringBuilder alertText = new StringBuilder();
1199 int i = 0;
1200 foreach (Host host in selected)
1202 if (i > 0)
1204 alertText.Append("\n");
1206 alertText.Append(Character.toString('\u2022')).Append(" ").Append(BookmarkNameProvider.toString(host));
1207 i++;
1208 if (i > 10)
1210 break;
1213 DialogResult result = QuestionBox(LocaleFactory.localizedString("Delete Bookmark"),
1214 LocaleFactory.localizedString("Do you want to delete the selected bookmark?"), alertText.ToString(),
1215 String.Format("{0}", LocaleFactory.localizedString("Delete")), true);
1216 if (result == DialogResult.OK)
1218 _bookmarkModel.Source.removeAll(Utils.ConvertToJavaList(selected));
1222 public override bool ViewShouldClose()
1224 return Unmount();
1227 private void View_OpenUrl()
1229 DescriptiveUrlBag list;
1230 if (SelectedPaths.Count == 1)
1232 list = ((UrlProvider) Session.getFeature(typeof (UrlProvider))).toUrl(SelectedPath);
1234 else
1236 list = ((UrlProvider) Session.getFeature(typeof (UrlProvider))).toUrl(Workdir);
1238 if (!list.isEmpty())
1240 BrowserLauncherFactory.get().open(list.find(DescriptiveUrl.Type.http).getUrl());
1244 private void View_SearchFieldChanged()
1246 if (View.CurrentView == BrowserView.File)
1248 SetPathFilter(View.SearchString);
1250 else
1252 SetBookmarkFilter(View.SearchString);
1256 private void SetBookmarkFilter(string searchString)
1258 if (Utils.IsBlank(searchString))
1260 View.SearchString = String.Empty;
1261 _bookmarkModel.Filter = null;
1263 else
1265 _bookmarkModel.Filter = new BookmarkFilter(searchString);
1267 ReloadBookmarks();
1270 private bool View_ValidateDisconnect()
1272 // disconnect/stop button update
1273 View.ActivityRunning = isActivityRunning();
1274 if (!IsConnected())
1276 return isActivityRunning();
1278 return IsConnected();
1281 private bool View_ValidateStop()
1283 return isActivityRunning();
1286 private bool View_ValidateSendCustomCommand()
1288 return IsMounted() && Session.getFeature(typeof (Command)) != null;
1291 private bool View_ValidateFolderInside()
1293 return IsMounted() && SelectedPaths.Count > 0;
1296 private bool View_ValidateFolderUp()
1298 return IsMounted() && !Workdir.isRoot();
1301 private bool View_ValidateHistoryForward()
1303 return IsMounted() && _navigation.getForward().size() > 0;
1306 private bool View_ValidateHistoryBack()
1308 return IsMounted() && _navigation.getBack().size() > 1;
1311 private bool View_ValidateGotoFolder()
1313 return IsMounted();
1316 private bool View_ValidateRefresh()
1318 return IsMounted();
1321 private void View_Disconnect()
1323 if (isActivityRunning())
1325 // Remove all pending actions)
1326 foreach (BackgroundAction action in getActions().toArray(new BackgroundAction[getActions().size()]))
1328 action.cancel();
1331 CallbackDelegate run = delegate
1333 if (PreferencesFactory.get().getBoolean("browser.disconnect.bookmarks.show"))
1335 ToggleView(BrowserView.Bookmark);
1337 else
1339 ToggleView(BrowserView.File);
1342 Disconnect(run);
1346 * Unmount this session
1349 private void Disconnect(CallbackDelegate runnable)
1351 InfoController infoController = _inspector;
1352 if (infoController != null)
1354 infoController.View.Close();
1356 if (HasSession())
1358 Background(new DisconnectAction(this, runnable));
1360 else
1362 runnable();
1366 private void View_SendCustomCommand()
1368 new CommandController(this, Session).View.ShowDialog();
1371 private void View_Search()
1373 View.StartSearch();
1376 private void View_FolderInside()
1378 Path selected = SelectedPath;
1379 if (null == selected)
1381 return;
1383 if (selected.isDirectory())
1385 SetWorkdir(selected);
1387 else if (selected.isFile() || View.SelectedPaths.Count > 1)
1389 if (PreferencesFactory.get().getBoolean("browser.doubleclick.edit"))
1391 View_EditEvent(null);
1393 else
1395 View_Download();
1400 public void Download(IList<Path> downloads, Local downloadFolder)
1402 if (downloads.Count > 0)
1404 IList<TransferItem> items = new List<TransferItem>();
1405 foreach (Path selected in downloads)
1407 items.Add(new TransferItem(selected, LocalFactory.get(downloadFolder, selected.getName())));
1409 Transfer q = new DownloadTransfer(Session.getHost(), Utils.ConvertToJavaList(items));
1410 transfer(q, new List<Path>());
1414 private void View_GotoFolder()
1416 GotoController gc = new GotoController(ObjectFactory.GetInstance<IGotoPromptView>(), this);
1417 gc.Show();
1420 private void View_RefreshBrowser()
1422 if (IsMounted())
1424 _cache.invalidate(Workdir);
1425 foreach (Path path in View.VisiblePaths)
1427 if (null == path) continue;
1428 _cache.invalidate(path);
1430 ReloadData(true);
1434 private bool View_ValidateTextEncoding()
1436 return IsMounted() && !isActivityRunning();
1439 private void View_ToggleLogDrawer()
1441 View.LogDrawerVisible = !View.LogDrawerVisible;
1442 PreferencesFactory.get().setProperty("browser.transcript.open", View.LogDrawerVisible);
1445 private void View_ShowHiddenFiles()
1447 ShowHiddenFiles = !ShowHiddenFiles;
1448 if (IsMounted())
1450 ReloadData(true);
1454 private void View_ToggleToolbar()
1456 View.ToolbarVisible = !View.ToolbarVisible;
1457 PreferencesFactory.get().setProperty("browser.toolbar", View.ToolbarVisible);
1460 private bool View_ValidatePaste()
1462 return IsBrowser() && IsMounted() && !_pasteboard.isEmpty();
1465 private void View_Paste()
1467 IDictionary<Path, Path> files = new Dictionary<Path, Path>();
1468 Path parent = Workdir;
1469 for (int i = 0; i < _pasteboard.size(); i++)
1471 Path next = (Path) _pasteboard.get(i);
1472 Path renamed = new Path(parent, next.getName(), next.getType());
1473 files.Add(next, renamed);
1475 _pasteboard.clear();
1476 if (_pasteboard.isCut())
1478 RenamePaths(files);
1480 if (_pasteboard.isCopy())
1482 DuplicatePaths(files);
1486 private bool View_ValidateCopy()
1488 return IsBrowser() && IsMounted() && SelectedPaths.Count > 0;
1491 private void View_Copy()
1493 _pasteboard.clear();
1494 _pasteboard.setCopy(true);
1495 foreach (Path p in SelectedPaths)
1497 // Writing data for private use when the item gets dragged to the transfer queue.
1498 _pasteboard.add(p);
1502 private bool View_ValidateCut()
1504 return IsBrowser() && IsMounted() && SelectedPaths.Count > 0;
1507 private void View_Cut()
1509 _pasteboard.clear();
1510 _pasteboard.setCut(true);
1511 foreach (Path s in SelectedPaths)
1513 // Writing data for private use when the item gets dragged to the transfer queue.
1514 _pasteboard.add(s);
1518 private void View_ShowPreferences()
1520 PreferencesController.Instance.View.Show();
1523 private bool View_ContextMenuEnabled()
1525 //context menu is always enabled
1526 return true;
1529 private void View_Exit()
1531 MainController.Exit();
1534 private List<string> View_GetArchives()
1536 List<string> result = new List<string>();
1537 Archive[] archives = Archive.getKnownArchives();
1538 foreach (Archive archive in archives)
1540 List selected = Utils.ConvertToJavaList(SelectedPaths, null);
1541 result.Add(archive.getTitle(selected));
1543 return result;
1546 private bool View_ValidateExpandArchive()
1548 if (IsMounted())
1550 if (Session.getFeature(typeof (Compress)) == null)
1552 return false;
1554 if (SelectedPaths.Count > 0)
1556 foreach (Path selected in SelectedPaths)
1558 if (selected.isDirectory())
1560 return false;
1562 if (!Archive.isArchive(selected.getName()))
1564 return false;
1567 return true;
1570 return false;
1573 private void View_ExpandArchive()
1575 List<Path> expanded = new List<Path>();
1576 foreach (Path selected in SelectedPaths)
1578 Archive archive = Archive.forName(selected.getName());
1579 if (null == archive)
1581 continue;
1583 if (CheckOverwrite(Utils.ConvertFromJavaList<Path>(archive.getExpanded(new ArrayList {selected}))))
1585 background(new UnarchiveAction(this, archive, selected, expanded));
1590 private bool View_ValidateCreateArchive()
1592 if (IsMounted())
1594 if (Session.getFeature(typeof (Compress)) == null)
1596 return false;
1598 if (SelectedPaths.Count > 0)
1600 foreach (Path selected in SelectedPaths)
1602 if (selected.isFile() && Archive.isArchive(selected.getName()))
1604 // At least one file selected is already an archive. No distinct action possible
1605 return false;
1608 return true;
1611 return false;
1614 private void View_CreateArchive(object sender, CreateArchiveEventArgs createArchiveEventArgs)
1616 Archive archive = Archive.forName(createArchiveEventArgs.ArchiveName);
1617 IList<Path> selected = SelectedPaths;
1618 if (CheckOverwrite(new List<Path> {archive.getArchive(Utils.ConvertToJavaList(selected))}))
1620 background(new CreateArchiveAction(this, archive, selected));
1624 private bool View_ValidateDelete()
1626 return IsMounted() && SelectedPaths.Count > 0;
1629 private bool View_ValidateSynchronize()
1631 return IsMounted();
1634 private void View_Synchronize()
1636 Path selected;
1637 if (SelectedPaths.Count == 1 && SelectedPath.isDirectory())
1639 selected = SelectedPath;
1641 else
1643 selected = Workdir;
1645 string folder =
1646 View.SynchronizeDialog(
1647 String.Format(LocaleFactory.localizedString("Synchronize {0} with"), selected.getName()),
1648 new UploadDirectoryFinder().find(Session.getHost()), null);
1649 if (null != folder)
1651 Local target = LocalFactory.get(folder);
1652 new UploadDirectoryFinder().save(Session.getHost(), target.getParent());
1653 transfer(new SyncTransfer(Session.getHost(), new TransferItem(selected, target)));
1657 private bool View_ValidateNewFile()
1659 return IsMounted() &&
1660 ((Touch) Session.getFeature(typeof (Touch))).isSupported(
1661 new UploadTargetFinder(Workdir).find(SelectedPath));
1664 private bool View_ValidateUpload()
1666 return IsMounted() &&
1667 ((Touch) Session.getFeature(typeof (Touch))).isSupported(
1668 new UploadTargetFinder(Workdir).find(SelectedPath));
1671 private void View_Upload()
1673 // Due to the limited functionality of the OpenFileDialog class it is
1674 // currently not possible to select a folder. May be we should provide
1675 // a second menu item which allows to select a folder to upload
1676 string[] paths = View.UploadDialog(null);
1677 if (null == paths || paths.Length == 0) return;
1679 Path destination = new UploadTargetFinder(Workdir).find(SelectedPath);
1680 List uploads = Utils.ConvertToJavaList(paths, delegate(string path)
1682 Local local = LocalFactory.get(path);
1683 new UploadDirectoryFinder().save(Session.getHost(), local.getParent());
1684 return
1685 new TransferItem(
1686 new Path(destination, local.getName(),
1687 local.isDirectory()
1688 ? EnumSet.of(AbstractPath.Type.directory)
1689 : EnumSet.of(AbstractPath.Type.file)), local);
1691 transfer(new UploadTransfer(Session.getHost(), uploads));
1694 private void View_DownloadTo()
1696 string folder = View.DownloadToDialog(LocaleFactory.localizedString("Download To…"),
1697 new DownloadDirectoryFinder().find(Session.getHost()), null);
1698 if (null != folder && SelectedPaths.Count > 0)
1700 Local target = LocalFactory.get(folder);
1701 new DownloadDirectoryFinder().save(Session.getHost(), target);
1702 IList<TransferItem> downloads = new List<TransferItem>();
1703 foreach (Path file in SelectedPaths)
1705 downloads.Add(new TransferItem(file, LocalFactory.get(target, file.getName())));
1707 transfer(new DownloadTransfer(Session.getHost(), Utils.ConvertToJavaList(downloads)), new List<Path>());
1711 private bool View_ValidateDownloadAs()
1713 return IsMounted() && SelectedPaths.Count == 1;
1716 private void View_DownloadAs()
1718 string filename = View.DownloadAsDialog(new DownloadDirectoryFinder().find(Session.getHost()),
1719 SelectedPath.getName());
1720 if (null != filename)
1722 Local target = LocalFactory.get(filename);
1723 Path selected = SelectedPath;
1724 new DownloadDirectoryFinder().save(Session.getHost(), target.getParent());
1725 IList<TransferItem> downloads = new List<TransferItem>();
1726 downloads.Add(new TransferItem(selected, target));
1727 transfer(new DownloadTransfer(Session.getHost(), Utils.ConvertToJavaList(downloads)), new List<Path>());
1731 private bool View_ValidateDownload()
1733 return IsMounted() && SelectedPaths.Count > 0;
1736 private bool View_ValidateShowInspector()
1738 return IsMounted() && SelectedPaths.Count > 0;
1741 private bool View_ValidateOpenWebUrl()
1743 return IsMounted();
1746 private bool View_ValidateEditWith()
1748 if (IsMounted() && SelectedPaths.Count > 0)
1750 foreach (Path selected in SelectedPaths)
1752 if (!IsEditable(selected))
1754 return false;
1757 return true;
1759 return false;
1762 /// <param name="selected"></param>
1763 /// <returns>True if the selected path is editable (not a directory)</returns>
1764 private bool IsEditable(Path selected)
1766 if (Session.getHost().getCredentials().isAnonymousLogin())
1768 return false;
1770 return selected.isFile();
1773 private bool View_ValidateDuplicateFile()
1775 return IsMounted() && SelectedPaths.Count == 1;
1778 private bool View_ValidateRenameFile()
1780 if (IsMounted() && SelectedPaths.Count == 1)
1782 if (null == SelectedPath)
1784 return false;
1786 return ((Move) Session.getFeature(typeof (Move))).isSupported(SelectedPath);
1788 return false;
1791 private void View_NewDownload()
1793 throw new NotImplementedException();
1796 private void View_OpenConnection()
1798 ConnectionController c = ConnectionController.Instance(this);
1799 DialogResult result = c.View.ShowDialog(View);
1800 if (result == DialogResult.OK)
1802 Mount(c.ConfiguredHost);
1806 private bool View_ValidateNewFolder()
1808 return IsMounted();
1811 private void View_DuplicateFile()
1813 DuplicateFileController dc =
1814 new DuplicateFileController(ObjectFactory.GetInstance<IDuplicateFilePromptView>(), this);
1815 dc.Show();
1818 private void View_NewFile()
1820 CreateFileController fc = new CreateFileController(ObjectFactory.GetInstance<ICreateFilePromptView>(), this);
1821 fc.Show();
1824 private void View_Delete()
1826 DeletePaths(SelectedPaths);
1829 private void View_NewFolder()
1831 Location feature = (Location) Session.getFeature(typeof (Location));
1832 FolderController fc = new FolderController(ObjectFactory.GetInstance<INewFolderPromptView>(), this,
1833 feature != null
1834 ? (IList<Location.Name>) Utils.ConvertFromJavaList<Location.Name>(feature.getLocations())
1835 : new List<Location.Name>());
1836 fc.Show();
1839 private bool View_RenameFile(Path path, string newName)
1841 if (!String.IsNullOrEmpty(newName) && !newName.Equals(path.getName()))
1843 Path renamed = new Path(path.getParent(), newName, path.getType());
1844 RenamePath(path, renamed);
1846 return false;
1849 private DataObject View_BrowserDrag(ObjectListView listView)
1851 DataObject data = new DataObject(DataFormats.FileDrop,
1852 new[]
1854 CreateAndWatchTemporaryFile(delegate(object sender, FileSystemEventArgs args)
1856 _dropFolder = System.IO.Path.GetDirectoryName(args.FullPath);
1857 Invoke(delegate { Download(SelectedPaths, LocalFactory.get(_dropFolder)); });
1860 return data;
1863 private void RemoveTemporaryFilesystemWatcher()
1865 BeginInvoke(delegate
1867 foreach (FileSystemWatcher watcher in _temporaryWatcher)
1869 watcher.Dispose();
1871 _temporaryWatcher.Clear();
1875 private void RemoveTemporaryFiles(DataObject data)
1877 if (data.ContainsFileDropList())
1879 foreach (string tmpFile in data.GetFileDropList())
1883 if (File.Exists(tmpFile))
1885 File.Delete(tmpFile);
1887 if (null != _dropFolder)
1889 string tmpDestFile = System.IO.Path.Combine(_dropFolder, System.IO.Path.GetFileName(tmpFile));
1890 if (File.Exists(tmpDestFile))
1892 File.Delete(tmpDestFile);
1896 catch (IOException e)
1898 Log.error("Could not remove temporary files.", e);
1904 private void View_BrowserEndDrag(DataObject data)
1906 RemoveTemporaryFiles(data);
1907 RemoveTemporaryFilesystemWatcher();
1910 private void View_BrowserDropped(OlvDropEventArgs e)
1912 if (IsMounted() && e.DataObject is DataObject && ((DataObject) e.DataObject).ContainsFileDropList())
1914 Path destination;
1915 switch (e.DropTargetLocation)
1917 case DropTargetLocation.Item:
1918 destination = (Path) e.DropTargetItem.RowObject;
1919 break;
1920 case DropTargetLocation.Background:
1921 destination = Workdir;
1922 break;
1923 default:
1924 destination = null;
1925 break;
1928 StringCollection dropList = (e.DataObject as DataObject).GetFileDropList();
1929 if (dropList.Count > 0)
1931 IList<TransferItem> roots = new List<TransferItem>();
1932 foreach (string file in dropList)
1934 Local local = LocalFactory.get(file);
1935 roots.Add(
1936 new TransferItem(
1937 new Path(destination, local.getName(),
1938 local.isDirectory()
1939 ? EnumSet.of(AbstractPath.Type.directory)
1940 : EnumSet.of(AbstractPath.Type.file)), local));
1942 UploadDroppedPath(roots, destination);
1947 public void UploadDroppedPath(IList<TransferItem> roots, Path destination)
1949 if (IsMounted())
1951 UploadTransfer q = new UploadTransfer(Session.getHost(), Utils.ConvertToJavaList(roots));
1952 if (q.getRoots().size() > 0)
1954 transfer(q);
1959 /// <summary>
1960 /// Check if we accept drag operation from an external program
1961 /// </summary>
1962 /// <param name="args"></param>
1963 private void View_BrowserCanDrop(OlvDropEventArgs args)
1965 Log.trace("Entering View_BrowserCanDrop with " + args.Effect);
1966 if (IsMounted() && !(args.DataObject is OLVDataObject))
1968 if (args.DataObject is DataObject && ((DataObject) args.DataObject).ContainsFileDropList())
1970 Path destination;
1971 switch (args.DropTargetLocation)
1973 case DropTargetLocation.Item:
1974 destination = (Path) args.DropTargetItem.RowObject;
1975 if (!destination.isDirectory())
1977 //dragging over file
1978 destination = destination.getParent();
1980 break;
1981 case DropTargetLocation.Background:
1982 destination = Workdir;
1983 break;
1984 default:
1985 args.Effect = DragDropEffects.None;
1986 args.DropTargetLocation = DropTargetLocation.None;
1987 return;
1989 Touch feature = (Touch) Session.getFeature(typeof (Touch));
1990 if (!feature.isSupported(destination))
1992 Log.trace("Session does not allow file creation");
1993 args.Effect = DragDropEffects.None;
1994 args.DropTargetLocation = DropTargetLocation.None;
1995 return;
1997 Log.trace("Setting effect to copy");
1998 args.Effect = DragDropEffects.Copy;
1999 if (Workdir == destination)
2001 args.DropTargetLocation = DropTargetLocation.Background;
2003 else
2005 args.DropTargetItem = args.ListView.ModelToItem(destination);
2007 (args.DataObject as DataObject).SetDropDescription((DropImageType) args.Effect, "Copy to %1",
2008 destination.getName());
2013 private void View_ShowTransfers()
2015 TransferController.Instance.View.Show();
2018 private void View_ShowInspector()
2020 IList<Path> selected = SelectedPaths;
2021 if (selected.Count > 0)
2023 if (PreferencesFactory.get().getBoolean("browser.info.inspector"))
2025 if (null == _inspector || _inspector.View.IsDisposed)
2027 _inspector = InfoController.Factory.Create(this, selected);
2029 else
2031 _inspector.Files = selected;
2033 _inspector.View.Show(View);
2035 else
2037 InfoController c = InfoController.Factory.Create(this, selected);
2038 c.View.Show(View);
2043 private void View_EditEvent(string exe)
2045 foreach (Path selected in SelectedPaths)
2047 Editor editor;
2048 if (Utils.IsBlank(exe))
2050 editor = EditorFactory.instance().create(this, Session, selected);
2052 else
2054 editor = EditorFactory.instance().create(this, Session, new Application(exe, null), selected);
2056 this.edit(editor);
2060 public void edit(Editor editor)
2062 this.background(new WorkerBackgroundAction(this, Session,
2063 editor.open(new DisabledApplicationQuitCallback(), new DisabledTransferErrorCallback(),
2064 new DefaultEditorListener(this, Session, editor))));
2067 private void UpdateEditIcon()
2069 Path selected = SelectedPath;
2070 if (null != selected)
2072 if (IsEditable(selected))
2074 Application app = EditorFactory.instance().getEditor(selected.getName());
2075 string editCommand = app != null ? app.getIdentifier() : null;
2076 if (Utils.IsNotBlank(editCommand))
2080 View.EditIcon =
2081 IconCache.Instance.GetFileIconFromExecutable(
2082 WindowsApplicationLauncher.GetExecutableCommand(editCommand), IconCache.IconSize.Large)
2083 .ToBitmap();
2084 return;
2086 catch (ObjectDisposedException)
2092 View.EditIcon = IconCache.Instance.IconForName("pencil", 32);
2095 private void UpdateOpenIcon()
2097 View.OpenIcon = IconCache.Instance.GetDefaultBrowserIcon();
2100 private void View_BrowserSelectionChanged()
2102 UpdateEditIcon();
2104 // update inspector content if available
2105 IList<Path> selectedPaths = SelectedPaths;
2107 if (PreferencesFactory.get().getBoolean("browser.info.inspector"))
2109 if (_inspector != null && _inspector.Visible)
2111 if (selectedPaths.Count > 0)
2113 _inspector.Files = selectedPaths;
2119 private void View_PathSelectionChanged()
2121 string selected = View.SelectedComboboxPath;
2122 if (selected != null)
2124 Path workdir = Workdir;
2125 Path p = workdir;
2126 while (!p.getAbsolute().Equals(selected))
2128 p = p.getParent();
2130 SetWorkdir(p);
2131 if (workdir.getParent().equals(p))
2133 SetWorkdir(p, workdir);
2135 else
2137 SetWorkdir(p);
2142 private void View_FolderUp()
2144 Path previous = Workdir;
2145 SetWorkdir(previous.getParent(), previous);
2148 private void View_HistoryBack()
2150 Path selected = _navigation.back();
2151 if (selected != null)
2153 Path previous = Workdir;
2154 if (previous.getParent().equals(selected))
2156 SetWorkdir(selected, previous);
2158 else
2160 SetWorkdir(selected);
2165 private void View_HistoryForward()
2167 Path selected = _navigation.forward();
2168 if (selected != null)
2170 SetWorkdir(selected);
2174 private void View_BrowserDoubleClicked()
2176 View_FolderInside();
2179 private void View_QuickConnect()
2181 if (string.IsNullOrEmpty(View.QuickConnectValue))
2183 return;
2185 string input = View.QuickConnectValue.Trim();
2187 // First look for equivalent bookmarks
2188 BookmarkCollection bookmarkCollection = BookmarkCollection.defaultCollection();
2189 foreach (Host host in bookmarkCollection)
2191 if (BookmarkNameProvider.toString(host).Equals(input))
2193 Mount(host);
2194 return;
2197 Mount(HostParser.parse(input));
2200 /// <summary>
2201 /// Open a new browser with the current selected folder as the working directory
2202 /// </summary>
2203 private void View_NewBrowser(object sender, NewBrowserEventArgs newBrowserEventArgs)
2205 if (newBrowserEventArgs.SelectedAsWorkingDir)
2207 Path selected = SelectedPath;
2208 if (null == selected || !selected.isDirectory())
2210 selected = Workdir;
2212 BrowserController c = MainController.NewBrowser(true);
2214 Host host = new HostDictionary().deserialize(Session.getHost().serialize(SerializerFactory.get()));
2215 host.setDefaultPath(selected.getAbsolute());
2216 c.Mount(host);
2218 else
2220 BrowserController c = MainController.NewBrowser(true);
2221 MainController.OpenDefaultBookmark(c);
2225 protected void transfer(Transfer transfer)
2227 this.transfer(transfer, Utils.ConvertFromJavaList(transfer.getRoots(), delegate(object o)
2229 TransferItem item = (TransferItem) o;
2230 return item.remote;
2231 }));
2234 /// <summary>
2235 /// Transfers the files either using the queue or using
2236 /// the browser session if #connection.pool.max is 1
2237 /// </summary>
2238 /// <param name="transfer"></param>
2239 protected void transfer(Transfer transfer, IList<Path> selected)
2241 this.transfer(transfer, selected, Session.getTransferType().equals(Host.TransferType.browser));
2244 /// <summary>
2246 /// </summary>
2247 /// <param name="transfer"></param>
2248 /// <param name="destination"></param>
2249 /// <param name="useBrowserConnection"></param>
2250 public void transfer(Transfer transfer, IList<Path> selected, bool browser)
2252 TransferCallback callback = new ReloadTransferCallback(this, selected);
2253 if (browser)
2255 Background(new CallbackTransferBackgroundAction(callback, this, new ProgressTransferAdapter(this), this,
2256 this, transfer, new TransferOptions()));
2258 else
2260 TransferController.Instance.StartTransfer(transfer, new TransferOptions(), callback);
2264 /// <summary>
2266 /// </summary>
2267 /// <returns>true if a connection is being opened or is already initialized</returns>
2268 public bool HasSession()
2270 return Session != null;
2273 public bool IsMounted()
2275 return HasSession() && Workdir != null;
2278 /// <summary>
2280 /// </summary>
2281 /// <param name="preserveSelection">All selected files should be reselected after reloading the view</param>
2282 public void ReloadData(bool preserveSelection)
2284 if (preserveSelection)
2286 //Remember the previously selected paths
2287 ReloadData(SelectedPaths);
2289 else
2291 ReloadData(new List<Path>());
2295 public void RefreshParentPath(Path changed)
2297 RefreshParentPaths(new Collection<Path> {changed});
2300 public void RefreshParentPaths(IList<Path> changed)
2302 RefreshParentPaths(changed, new List<Path>());
2305 public override void start(BackgroundAction action)
2307 Invoke(delegate { View.StartActivityAnimation(); });
2310 public override void stop(BackgroundAction action)
2312 Invoke(delegate { View.StopActivityAnimation(); });
2315 public void RefreshParentPaths(IList<Path> changed, IList<Path> selected)
2317 bool rootRefreshed = false; //prevent multiple root updates
2318 foreach (Path path in changed)
2320 _cache.invalidate(path.getParent());
2321 if (Workdir.equals(path.getParent()))
2323 if (rootRefreshed)
2325 continue;
2327 View.SetBrowserModel(_browserModel.ChildrenGetter(Workdir));
2328 rootRefreshed = true;
2330 else
2332 View.RefreshBrowserObject(path.getParent());
2335 SelectedPaths = selected;
2338 public void ReloadData(Path directory, bool preserveSelection)
2340 if (Workdir.equals(directory))
2342 ReloadData(true);
2344 else
2346 View.RefreshBrowserObject(directory);
2350 protected void ReloadData(IList<Path> selected)
2352 if (null != Workdir)
2354 IEnumerable<Path> children = _browserModel.ChildrenGetter(Workdir);
2355 //clear selection before resetting model. Otherwise we have weird selection effects.
2356 SelectedPaths = new List<Path>();
2357 int savedIndex = View.TopItemIndex;
2358 View.BeginBrowserUpdate();
2359 View.SetBrowserModel(null); // #7670
2360 View.SetBrowserModel(children);
2361 View.TopItemIndex = savedIndex;
2362 SelectedPaths = selected;
2363 List<Path> toUpdate = new List<Path>();
2364 foreach (Path path in View.VisiblePaths)
2366 if (path.isDirectory())
2368 toUpdate.Add(path);
2371 View.RefreshBrowserObjects(toUpdate);
2372 View.EndBrowserUpdate();
2374 else
2376 View.SetBrowserModel(null);
2378 SelectedPaths = selected;
2379 SetStatus();
2382 public void SetWorkdir(Path directory)
2384 SetWorkdir(directory, new List<Path>());
2387 public void SetWorkdir(Path directory, Path selected)
2389 SetWorkdir(directory, new List<Path> {selected});
2392 /// <summary>
2393 /// Sets the current working directory. This will udpate the path selection dropdown button
2394 /// and also add this path to the browsing history. If the path cannot be a working directory (e.g. permission
2395 /// issues trying to enter the directory), reloading the browser view is canceled and the working directory
2396 /// not changed.
2397 /// </summary>
2398 /// <param name="directory">The new working directory to display or null to detach any working directory from the browser</param>
2399 /// <param name="selected"></param>
2400 public void SetWorkdir(Path directory, List<Path> selected)
2402 Workdir = directory;
2403 // Remove any custom file filter
2404 SetPathFilter(null);
2405 // Change to last selected browser view
2406 ReloadData(Workdir != null ? selected : new List<Path>());
2407 SetNavigation(IsMounted());
2410 private void SetNavigation(bool enabled)
2412 View.SearchEnabled = enabled;
2413 if (!enabled)
2415 View.SearchString = String.Empty;
2417 List<string> paths = new List<string>();
2418 if (enabled)
2420 // Update the current working directory
2421 _navigation.add(Workdir);
2422 Path p = Workdir;
2425 paths.Add(p.getAbsolute());
2426 p = p.getParent();
2427 } while (!p.isRoot());
2428 View.PopulatePaths(paths);
2430 View.ComboboxPathEnabled = enabled;
2431 View.HistoryBackEnabled = enabled && _navigation.getBack().size() > 1;
2432 View.HistoryForwardEnabled = enabled && _navigation.getForward().size() > 0;
2433 View.ParentPathEnabled = enabled && !Workdir.isRoot();
2436 public void RefreshObject(Path path, bool preserveSelection)
2438 if (preserveSelection)
2440 RefreshObject(path, View.SelectedPaths);
2442 else
2444 RefreshObject(path, new List<Path>());
2448 public void RefreshObject(Path path, IList<Path> selected)
2450 if (Workdir.Equals(path))
2452 View.SetBrowserModel(_browserModel.ChildrenGetter(path));
2454 else
2456 if (!path.isDirectory())
2458 View.RefreshBrowserObject(path.getParent());
2460 else
2462 View.RefreshBrowserObject(path);
2465 SelectedPaths = selected;
2466 SetStatus();
2469 public void Mount(Host host)
2471 if (Log.isDebugEnabled())
2473 Log.debug(string.Format("Mount session for {0}", host));
2475 CallbackDelegate callbackDelegate = delegate
2477 // The browser has no session, we are allowed to proceed
2478 // Initialize the browser with the new session attaching all listeners
2479 Session session = Init(host);
2480 background(new MountAction(this, session, host, _limitListener));
2482 Unmount(callbackDelegate);
2485 /// <summary>
2486 /// Initializes a session for the passed host. Setting up the listeners and adding any callback
2487 /// controllers needed for login, trust management and hostkey verification.
2488 /// </summary>
2489 /// <param name="host"></param>
2490 /// <returns>A session object bound to this browser controller</returns>
2491 private Session Init(Host host)
2493 Session = SessionFactory.create(host,
2494 new KeychainX509TrustManager(new DefaultTrustManagerHostnameCallback(host)),
2495 new KeychainX509KeyManager());
2496 SetWorkdir(null);
2497 View.SelectedEncoding = Session.getEncoding();
2498 View.ClearTranscript();
2499 _navigation.clear();
2500 _pasteboard = PathPasteboardFactory.getPasteboard(Session);
2501 return Session;
2504 // some simple caching as _session.isConnected() throws a ConnectionCanceledException if not connected
2506 /// <summary>
2508 /// </summary>
2509 /// <returns>true if mounted and the connection to the server is alive</returns>
2510 public bool IsConnected()
2512 if (IsMounted())
2514 return Session.isConnected();
2516 return false;
2519 public static bool ApplicationShouldTerminate()
2521 // Determine if there are any open connections
2522 foreach (BrowserController controller in new List<BrowserController>(MainController.Browsers))
2524 BrowserController c = controller;
2525 if (!controller.Unmount(delegate(DialogResult result)
2527 if (DialogResult.OK == result)
2529 c.View.Dispose();
2530 return true;
2532 return false;
2533 }, delegate { }))
2535 return false; // Disconnect cancelled
2538 return true;
2541 public bool Unmount()
2543 return Unmount(() => { });
2546 public bool Unmount(CallbackDelegate disconnected)
2548 return Unmount(result =>
2550 if (DialogResult.OK == result)
2552 UnmountImpl(disconnected);
2553 return true;
2555 // No unmount yet
2556 return false;
2557 }, disconnected);
2560 /// <summary>
2562 /// </summary>
2563 /// <param name="unmountImpl"></param>
2564 /// <param name="disconnected"></param>
2565 /// <returns>True if the unmount process is in progress or has been finished, false if cancelled</returns>
2566 public bool Unmount(DialogCallbackDelegate unmountImpl, CallbackDelegate disconnected)
2568 if (IsConnected() || isActivityRunning())
2570 if (PreferencesFactory.get().getBoolean("browser.disconnect.confirm"))
2572 DialogResult result = CommandBox(LocaleFactory.localizedString("Disconnect"),
2573 String.Format(LocaleFactory.localizedString("Disconnect from {0}"),
2574 Session.getHost().getHostname()),
2575 LocaleFactory.localizedString("The connection will be closed."),
2576 String.Format("{0}", LocaleFactory.localizedString("Disconnect")), true,
2577 LocaleFactory.localizedString("Don't ask again", "Configuration"), SysIcons.Question,
2578 delegate(int option, bool verificationChecked)
2580 if (verificationChecked)
2582 // Never show again.
2583 PreferencesFactory.get().setProperty("browser.disconnect.confirm", false);
2585 switch (option)
2587 case 0: // Disconnect
2588 unmountImpl(DialogResult.OK);
2589 break;
2592 return DialogResult.OK == result;
2595 UnmountImpl(disconnected);
2596 // Unmount succeeded
2597 return true;
2600 private void UnmountImpl(CallbackDelegate disconnected)
2602 CallbackDelegate run = delegate
2604 _cache.clear();
2605 View.WindowTitle = PreferencesFactory.get().getProperty("application.name");
2606 disconnected();
2609 Disconnect(run);
2612 public void SetStatus()
2614 BackgroundAction current = getActions().getCurrent();
2615 message(null != current ? current.getActivity() : null);
2618 public void SetStatus(string label)
2620 View.StatusLabel = label;
2623 private void PopulateQuickConnect()
2625 List<string> nicknames = new List<string>();
2626 foreach (Host host in _bookmarkCollection)
2628 nicknames.Add(BookmarkNameProvider.toString(host));
2630 View.PopulateQuickConnect(nicknames);
2633 /// <summary>
2635 /// </summary>
2636 /// <param name="path">The existing file</param>
2637 /// <param name="renamed">The renamed file</param>
2638 protected internal void RenamePath(Path path, Path renamed)
2640 RenamePaths(new Dictionary<Path, Path> {{path, renamed}});
2643 /// <summary>
2645 /// </summary>
2646 /// <param name="selected">
2647 /// A dictionary with the original files as the key and
2648 /// the destination files as the value
2649 /// </param>
2650 protected internal void RenamePaths(IDictionary<Path, Path> selected)
2652 if (CheckMove(selected))
2654 List<Path> changed = new List<Path>();
2655 changed.AddRange(selected.Keys);
2656 changed.AddRange(selected.Values);
2657 MoveAction move = new MoveAction(this, Utils.ConvertToJavaMap(selected), changed);
2658 Background(move);
2662 /// <summary>
2663 /// Displays a warning dialog about files to be moved
2664 /// </summary>
2665 /// <param name="selected">The files to check for existence</param>
2666 /// <param name="action"></param>
2667 private bool CheckMove(IDictionary<Path, Path> selected)
2669 if (PreferencesFactory.get().getBoolean("browser.move.confirm"))
2671 StringBuilder alertText =
2672 new StringBuilder(LocaleFactory.localizedString("Do you want to move the selected files?"));
2674 StringBuilder content = new StringBuilder();
2675 int i = 0;
2676 bool rename = false;
2677 IEnumerator<KeyValuePair<Path, Path>> enumerator = null;
2678 for (enumerator = selected.GetEnumerator(); i < 10 && enumerator.MoveNext();)
2680 KeyValuePair<Path, Path> next = enumerator.Current;
2681 if (next.Key.getParent().equals(next.Value.getParent()))
2683 rename = true;
2685 // u2022 = Bullet
2686 content.Append("\n" + Character.toString('\u2022') + " " + next.Key.getName());
2687 i++;
2689 if (enumerator.MoveNext())
2691 content.Append("\n" + Character.toString('\u2022') + " ...)");
2693 bool result = false;
2694 CommandBox(rename ? LocaleFactory.localizedString("Rename") : LocaleFactory.localizedString("Move"),
2695 alertText.ToString(), content.ToString(),
2696 String.Format("{0}",
2697 rename ? LocaleFactory.localizedString("Rename") : LocaleFactory.localizedString("Move")), true,
2698 LocaleFactory.localizedString("Don't ask again", "Configuration"), SysIcons.Question,
2699 delegate(int option, bool verificationChecked)
2701 if (verificationChecked)
2703 // Never show again.
2704 PreferencesFactory.get().setProperty("browser.move.confirm", false);
2706 if (option == 0)
2708 result = CheckOverwrite(selected.Values);
2711 return result;
2713 return CheckOverwrite(selected.Values);
2716 /// <summary>
2717 /// Recursively deletes the files
2718 /// </summary>
2719 /// <param name="selected">The files selected in the browser to delete</param>
2720 public void DeletePaths(ICollection<Path> selected)
2722 ICollection<Path> normalized =
2723 Utils.ConvertFromJavaList<Path>(PathNormalizer.normalize(Utils.ConvertToJavaList(selected)));
2724 if (normalized.Count == 0)
2726 return;
2729 StringBuilder alertText =
2730 new StringBuilder(
2731 LocaleFactory.localizedString("Really delete the following files? This cannot be undone."));
2733 StringBuilder content = new StringBuilder();
2734 int i = 0;
2735 IEnumerator<Path> enumerator;
2736 for (enumerator = selected.GetEnumerator(); i < 10 && enumerator.MoveNext();)
2738 Path item = enumerator.Current;
2739 if (i > 0) content.AppendLine();
2740 // u2022 = Bullet
2741 content.Append(Character.toString('\u2022') + " " + item.getName());
2742 i++;
2744 if (enumerator.MoveNext())
2746 content.Append("\n" + Character.toString('\u2022') + " ...)");
2748 DialogResult r = QuestionBox(LocaleFactory.localizedString("Delete"), alertText.ToString(),
2749 content.ToString(), String.Format("{0}", LocaleFactory.localizedString("Delete")), true);
2750 if (r == DialogResult.OK)
2752 DeletePathsImpl(normalized);
2756 private void DeletePathsImpl(ICollection<Path> files)
2758 background(new DeleteAction(this, LoginCallbackFactory.get(this), Utils.ConvertToJavaList(files)));
2761 public void SetPathFilter(string searchString)
2763 if (Utils.IsBlank(searchString))
2765 View.SearchString = String.Empty;
2766 // Revert to the last used default filter
2767 if (ShowHiddenFiles)
2769 FilenameFilter = new NullFilter();
2771 else
2773 FilenameFilter = new RegexFilter();
2776 else
2778 // Setting up a custom filter for the directory listing
2779 FilenameFilter = new CustomPathFilter(searchString);
2781 ReloadData(true);
2784 /// <summary>
2785 /// Displays a warning dialog about already existing files
2786 /// </summary>
2787 /// <param name="selected">The files to check for existance</param>
2788 private bool CheckOverwrite(ICollection<Path> selected)
2790 StringBuilder alertText =
2791 new StringBuilder(
2792 LocaleFactory.localizedString(
2793 "A file with the same name already exists. Do you want to replace the existing file?"));
2795 StringBuilder content = new StringBuilder();
2796 int i = 0;
2797 IEnumerator<Path> enumerator = null;
2798 bool shouldWarn = false;
2799 for (enumerator = selected.GetEnumerator(); enumerator.MoveNext();)
2801 Path item = enumerator.Current;
2802 if (_cache.get(item.getParent()).contains(item))
2804 if (i < 10)
2806 // u2022 = Bullet
2807 content.Append("\n" + Character.toString('\u2022') + " " + item.getName());
2809 shouldWarn = true;
2811 i++;
2813 if (i >= 10)
2815 content.Append("\n" + Character.toString('\u2022') + " ...)");
2817 if (shouldWarn)
2819 DialogResult r = QuestionBox(LocaleFactory.localizedString("Overwrite"), alertText.ToString(),
2820 content.ToString(), String.Format("{0}", LocaleFactory.localizedString("Overwrite")), true);
2821 return r == DialogResult.OK;
2823 else
2825 return true;
2829 /// <summary>
2831 /// </summary>
2832 /// <param name="source">The original file to duplicate</param>
2833 /// <param name="destination">The destination of the duplicated file</param>
2834 protected internal void DuplicatePath(Path source, Path destination)
2836 DuplicatePaths(new Dictionary<Path, Path> {{source, destination}});
2839 /// <summary>
2841 /// </summary>
2842 /// <param name="selected">A dictionary with the original files as the key and the destination files as the value</param>
2843 ///<param name="browser"></param>
2844 protected internal void DuplicatePaths(IDictionary<Path, Path> selected)
2846 if (CheckOverwrite(selected.Values))
2848 CopyTransfer copy = new CopyTransfer(Session.getHost(), Session.getHost(),
2849 Utils.ConvertToJavaMap(selected));
2850 List<Path> changed = new List<Path>();
2851 changed.AddRange(selected.Values);
2852 transfer(copy, changed, true);
2856 /// <summary>
2858 /// </summary>
2859 /// <param name="view">The view to show</param>
2860 public void ToggleView(BrowserView view)
2862 Log.debug("ToggleView:" + view);
2863 if (View.CurrentView == view) return;
2865 SetBookmarkFilter(null);
2866 switch (view)
2868 case BrowserView.File:
2869 View.CurrentView = BrowserView.File;
2870 SetPathFilter(null);
2871 ReloadData(true);
2872 break;
2873 case BrowserView.Bookmark:
2874 View.CurrentView = BrowserView.Bookmark;
2875 _bookmarkModel.Source = BookmarkCollection.defaultCollection();
2876 ReloadBookmarks();
2877 SelectHost();
2878 break;
2879 case BrowserView.History:
2880 View.CurrentView = BrowserView.History;
2881 _bookmarkModel.Source = HistoryCollection.defaultCollection();
2882 ReloadBookmarks();
2883 SelectHost();
2884 break;
2885 case BrowserView.Bonjour:
2886 View.CurrentView = BrowserView.Bonjour;
2887 _bookmarkModel.Source = RendezvousCollection.defaultCollection();
2888 ReloadBookmarks();
2889 SelectHost();
2890 break;
2894 private void SelectHost()
2896 if (IsMounted())
2898 View.SelectBookmark(Session.getHost());
2902 /// <summary>
2903 /// Reload bookmarks table from the currently selected model
2904 /// </summary>
2905 public void ReloadBookmarks()
2907 ReloadBookmarks(null);
2910 /// <summary>
2911 /// Reload bookmarks table from the currently selected model
2912 /// </summary>
2913 public void ReloadBookmarks(Host selected)
2915 //Note: expensive for a big bookmark list (might need a refactoring)
2916 View.SetBookmarkModel(_bookmarkModel.Source, selected);
2917 SetStatus();
2920 private class BookmarkFilter : HostFilter
2922 private readonly string _searchString;
2924 public BookmarkFilter(String searchString)
2926 _searchString = searchString;
2929 public bool accept(Host host)
2931 return BookmarkNameProvider.toString(host).ToLower().Contains(_searchString.ToLower()) ||
2932 (null == host.getComment()
2933 ? false
2934 : host.getComment().ToLower().Contains(_searchString.ToLower())) ||
2935 (null == host.getCredentials().getUsername()
2936 ? false
2937 : host.getCredentials().getUsername().ToLower().Contains(_searchString.ToLower())) ||
2938 host.getHostname().ToLower().Contains(_searchString.ToLower());
2942 private class CallbackTransferBackgroundAction : TransferBackgroundAction
2944 private readonly TransferCallback _callback;
2945 private readonly Transfer _transfer;
2947 public CallbackTransferBackgroundAction(TransferCallback callback, BrowserController controller,
2948 TransferListener transferListener, ProgressListener progressListener,
2949 TranscriptListener transcriptListener, Transfer transfer, TransferOptions options)
2950 : base(
2951 controller, controller.Session, controller._cache, transferListener, progressListener,
2952 transcriptListener, transfer, options)
2954 _callback = callback;
2955 _transfer = transfer;
2958 public override void finish()
2960 if (_transfer.isComplete())
2962 _callback.complete(_transfer);
2964 base.finish();
2968 private class CreateArchiveAction : BrowserControllerBackgroundAction
2970 private readonly Archive _archive;
2971 private readonly IList<Path> _selected;
2972 private readonly List _selectedJava;
2974 public CreateArchiveAction(BrowserController controller, Archive archive, IList<Path> selected)
2975 : base(controller)
2977 _archive = archive;
2978 _selectedJava = Utils.ConvertToJavaList(selected);
2979 _selected = selected;
2982 public override object run()
2984 ((Compress) BrowserController.Session.getFeature(typeof (Compress))).archive(_archive,
2985 BrowserController.Workdir, _selectedJava, BrowserController, BrowserController);
2986 return true;
2989 public override string getActivity()
2991 return _archive.getCompressCommand(BrowserController.Workdir, _selectedJava);
2994 public override void cleanup()
2996 base.cleanup();
2997 BrowserController.RefreshParentPaths(_selected, new List<Path> {_archive.getArchive(_selectedJava)});
3001 private class CustomPathFilter : SearchFilter, IModelFilter
3003 public CustomPathFilter(String searchString) : base(searchString)
3007 public bool Filter(object modelObject)
3009 return accept(modelObject);
3013 private class DeleteAction : WorkerBackgroundAction
3015 public DeleteAction(BrowserController controller, LoginCallback prompt, List files)
3016 : base(controller, controller.Session, new InnerDeleteWorker(controller, prompt, files))
3020 private class InnerDeleteWorker : DeleteWorker
3022 private readonly BrowserController _controller;
3023 private readonly List _files;
3025 public InnerDeleteWorker(BrowserController controller, LoginCallback prompt, List files)
3026 : base(controller.Session, prompt, files, controller)
3028 _controller = controller;
3029 _files = files;
3032 public override void cleanup(object result)
3034 if (((Boolean) result).booleanValue())
3036 _controller.RefreshParentPaths((IList<Path>) Utils.ConvertFromJavaList<Path>(_files));
3042 private class DisconnectAction : WorkerBackgroundAction
3044 private readonly BrowserController _controller;
3046 public DisconnectAction(BrowserController controller, CallbackDelegate callback)
3047 : base(controller, controller.Session, controller.Cache, new InnerDisconnectWorker(controller, callback)
3050 _controller = controller;
3053 public override void prepare()
3055 if (null == _controller.Session)
3057 throw new ConnectionCanceledException();
3059 if (!_controller.Session.isConnected())
3061 throw new ConnectionCanceledException();
3063 base.prepare();
3066 private class InnerDisconnectWorker : DisconnectWorker
3068 private readonly CallbackDelegate _callback;
3070 public InnerDisconnectWorker(BrowserController controller, CallbackDelegate callback)
3071 : base(controller.Session)
3073 _callback = callback;
3076 public override void cleanup(object wd)
3078 base.cleanup(wd);
3079 _callback();
3084 private class MountAction : WorkerBackgroundAction
3086 private readonly BrowserController _controller;
3087 private readonly Host _host;
3089 public MountAction(BrowserController controller, Session session, Host host, ListProgressListener listener)
3090 : base(controller, controller.Session, new InnerMountWorker(controller, session, listener))
3092 _controller = controller;
3093 _host = host;
3096 public override void init()
3098 base.init();
3099 _controller.View.WindowTitle = BookmarkNameProvider.toString(_host, true);
3100 _controller.View.RefreshBookmark(_controller.Session.getHost());
3103 private class InnerMountWorker : MountWorker
3105 private readonly BrowserController _controller;
3106 private readonly Session _session;
3108 public InnerMountWorker(BrowserController controller, Session session, ListProgressListener listener)
3109 : base(session, controller._cache, listener)
3111 _controller = controller;
3112 _session = session;
3115 public override void cleanup(object wd)
3117 Path workdir = (Path) wd;
3118 if (null == workdir)
3120 _controller.Unmount();
3122 else
3124 // Set the working directory
3125 _controller.SetWorkdir(workdir);
3126 _controller.View.RefreshBookmark(_session.getHost());
3127 _controller.ToggleView(BrowserView.File);
3128 _controller.View.SecureConnection = _session is SSLSession;
3129 _controller.View.CertBasedConnection = _session is SSLSession;
3130 _controller.View.SecureConnectionVisible = true;
3136 private class MoveAction : WorkerBackgroundAction
3138 public MoveAction(BrowserController controller, Map selected, IList<Path> changed)
3139 : base(controller, controller.Session, new InnerMoveWorker(controller, selected, changed))
3143 private class InnerMoveWorker : MoveWorker
3145 private readonly IList<Path> _changed;
3146 private readonly BrowserController _controller;
3147 private readonly Map _files;
3149 public InnerMoveWorker(BrowserController controller, Map files, IList<Path> changed)
3150 : base(controller.Session, files, controller)
3152 _controller = controller;
3153 _files = files;
3154 _changed = changed;
3157 public override void cleanup(object result)
3159 _controller.RefreshParentPaths(_changed,
3160 (IList<Path>) Utils.ConvertFromJavaList<Path>(_files.values()));
3165 private class ProgressTransferAdapter : TransferAdapter
3167 private readonly BrowserController _controller;
3169 public ProgressTransferAdapter(BrowserController controller)
3171 _controller = controller;
3174 public override void progress(TransferProgress status)
3176 _controller.message(status.getProgress());
3180 private class ReloadTransferCallback : TransferCallback
3182 private readonly IList<Path> _changed;
3183 private readonly BrowserController _controller;
3185 public ReloadTransferCallback(BrowserController controller, IList<Path> changed)
3187 _controller = controller;
3188 _changed = changed;
3191 public void complete(Transfer t)
3193 _controller.invoke(new ReloadAction(_controller, _changed));
3196 private class ReloadAction : WindowMainAction
3198 private readonly IList<Path> _changed;
3200 public ReloadAction(BrowserController c, IList<Path> changed) : base(c)
3202 _changed = changed;
3205 public override bool isValid()
3207 return base.isValid() && ((BrowserController) Controller).IsConnected();
3210 public override void run()
3212 ((BrowserController) Controller).RefreshParentPaths(_changed, _changed);
3217 private class RevertAction : WorkerBackgroundAction
3219 public RevertAction(BrowserController controller, IList<Path> files)
3220 : base(controller, controller.Session, new InnerRevertWorker(controller, files))
3224 private class InnerRevertWorker : RevertWorker
3226 private readonly BrowserController _controller;
3227 private readonly IList<Path> _files;
3229 public InnerRevertWorker(BrowserController controller, IList<Path> files)
3230 : base(controller.Session, Utils.ConvertToJavaList(files))
3232 _controller = controller;
3233 _files = files;
3236 public override void cleanup(object result)
3238 _controller.RefreshParentPaths(_files);
3243 private class UnarchiveAction : BrowserControllerBackgroundAction
3245 private readonly Archive _archive;
3246 private readonly List<Path> _expanded;
3247 private readonly Path _selected;
3249 public UnarchiveAction(BrowserController controller, Archive archive, Path selected, List<Path> expanded)
3250 : base(controller)
3252 _archive = archive;
3253 _expanded = expanded;
3254 _selected = selected;
3257 public override object run()
3259 ((Compress) BrowserController.Session.getFeature(typeof (Compress))).unarchive(_archive, _selected,
3260 BrowserController, BrowserController);
3261 return true;
3264 public override string getActivity()
3266 return _archive.getDecompressCommand(_selected);
3269 public override void cleanup()
3271 base.cleanup();
3272 _expanded.AddRange(Utils.ConvertFromJavaList<Path>(_archive.getExpanded(new ArrayList {_selected})));
3273 BrowserController.RefreshParentPaths(_expanded, _expanded);