mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
Completed splitting the connection tree from the connection tree window
This commit is contained in:
29
mRemoteNGTests/Tree/ConnectionTreeTests.cs
Normal file
29
mRemoteNGTests/Tree/ConnectionTreeTests.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class ConnectionTreeTests
|
||||
{
|
||||
private ConnectionTree _connectionTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionTree = new ConnectionTree();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
_connectionTree.Dispose();
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void test()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,9 @@
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
@@ -146,6 +148,7 @@
|
||||
<Compile Include="Security\CryptographyProviderFactoryTests.cs" />
|
||||
<Compile Include="Security\EncryptedSecureStringTests.cs" />
|
||||
<Compile Include="Security\LegacyRijndaelCryptographyProviderTests.cs" />
|
||||
<Compile Include="Tree\ConnectionTreeTests.cs" />
|
||||
<Compile Include="Tree\NodeSearcherTests.cs" />
|
||||
<Compile Include="Tree\RootNodeInfoTests.cs" />
|
||||
<Compile Include="UI\Controls\TestForm.cs">
|
||||
|
||||
@@ -42,8 +42,8 @@ namespace mRemoteNG.App
|
||||
public static SecureString EncryptionKey { get; set; } = new RootNodeInfo(RootNodeType.Connection).PasswordString.ConvertToSecureString();
|
||||
public static ConnectionTreeModel ConnectionTreeModel
|
||||
{
|
||||
get { return Windows.TreeForm.ConnectionTreeModel; }
|
||||
set { Windows.TreeForm.ConnectionTreeModel = value; }
|
||||
get { return Windows.TreeForm.ConnectionTree.ConnectionTreeModel; }
|
||||
set { Windows.TreeForm.ConnectionTree.ConnectionTreeModel = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace mRemoteNG.App
|
||||
// Load config
|
||||
connectionsLoader.ConnectionFileName = filename;
|
||||
ConnectionTreeModel = connectionsLoader.LoadConnections(false);
|
||||
Windows.TreeForm.ConnectionTreeModel = ConnectionTreeModel;
|
||||
Windows.TreeForm.ConnectionTree.ConnectionTreeModel = ConnectionTreeModel;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -288,7 +288,7 @@ namespace mRemoteNG.App
|
||||
|
||||
connectionsLoader.UseDatabase = Settings.Default.UseSQLServer;
|
||||
ConnectionTreeModel = connectionsLoader.LoadConnections(false);
|
||||
Windows.TreeForm.ConnectionTreeModel = ConnectionTreeModel;
|
||||
Windows.TreeForm.ConnectionTree.ConnectionTreeModel = ConnectionTreeModel;
|
||||
|
||||
if (Settings.Default.UseSQLServer)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using BrightIdeasSoftware;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Config.Putty;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
|
||||
|
||||
@@ -10,12 +19,451 @@ namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
public partial class ConnectionTree : TreeListView
|
||||
{
|
||||
private ConnectionTreeModel _connectionTreeModel;
|
||||
private readonly ConnectionTreeDragAndDropHandler _dragAndDropHandler = new ConnectionTreeDragAndDropHandler();
|
||||
private readonly PuttySessionsManager _puttySessionsManager = PuttySessionsManager.Instance;
|
||||
private OLVColumn _olvNameColumn;
|
||||
private ImageList imgListTree;
|
||||
|
||||
|
||||
public ConnectionInfo SelectedNode => (ConnectionInfo)SelectedObject;
|
||||
|
||||
public NodeSearcher NodeSearcher { get; private set; }
|
||||
|
||||
public ConnectionTreeModel ConnectionTreeModel
|
||||
{
|
||||
get { return _connectionTreeModel; }
|
||||
set
|
||||
{
|
||||
_connectionTreeModel = value;
|
||||
PopulateTreeView();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ConnectionTree()
|
||||
{
|
||||
InitializeComponent();
|
||||
SetupConnectionTreeView();
|
||||
}
|
||||
|
||||
#region ConnectionTree Setup
|
||||
private void SetupConnectionTreeView()
|
||||
{
|
||||
CreateNameColumn();
|
||||
CreateImageList();
|
||||
FillImageList();
|
||||
LinkModelToView();
|
||||
SetupDropSink();
|
||||
SetEventHandlers();
|
||||
}
|
||||
|
||||
private void CreateNameColumn()
|
||||
{
|
||||
_olvNameColumn = new OLVColumn
|
||||
{
|
||||
AspectName = "Name",
|
||||
FillsFreeSpace = true,
|
||||
IsButton = true,
|
||||
AspectGetter = item => ((ConnectionInfo)item).Name,
|
||||
ImageGetter = ConnectionImageGetter
|
||||
};
|
||||
Columns.Add(_olvNameColumn);
|
||||
AllColumns.Add(_olvNameColumn);
|
||||
}
|
||||
|
||||
private void CreateImageList()
|
||||
{
|
||||
imgListTree = new ImageList(this.components)
|
||||
{
|
||||
ColorDepth = ColorDepth.Depth32Bit,
|
||||
ImageSize = new System.Drawing.Size(16, 16),
|
||||
TransparentColor = System.Drawing.Color.Transparent
|
||||
};
|
||||
SmallImageList = imgListTree;
|
||||
}
|
||||
|
||||
private void FillImageList()
|
||||
{
|
||||
try
|
||||
{
|
||||
imgListTree.Images.Add(Resources.Root);
|
||||
imgListTree.Images.SetKeyName(0, "Root");
|
||||
imgListTree.Images.Add(Resources.Folder);
|
||||
imgListTree.Images.SetKeyName(1, "Folder");
|
||||
imgListTree.Images.Add(Resources.Play);
|
||||
imgListTree.Images.SetKeyName(2, "Play");
|
||||
imgListTree.Images.Add(Resources.Pause);
|
||||
imgListTree.Images.SetKeyName(3, "Pause");
|
||||
imgListTree.Images.Add(Resources.PuttySessions);
|
||||
imgListTree.Images.SetKeyName(4, "PuttySessions");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("FillImageList (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void LinkModelToView()
|
||||
{
|
||||
CanExpandGetter = item =>
|
||||
{
|
||||
var itemAsContainer = item as ContainerInfo;
|
||||
return itemAsContainer?.Children.Count > 0;
|
||||
};
|
||||
ChildrenGetter = item => ((ContainerInfo)item).Children;
|
||||
//ContextMenuStrip = _contextMenu;
|
||||
}
|
||||
|
||||
private static object ConnectionImageGetter(object rowObject)
|
||||
{
|
||||
if (rowObject is RootPuttySessionsNodeInfo) return "PuttySessions";
|
||||
if (rowObject is RootNodeInfo) return "Root";
|
||||
if (rowObject is ContainerInfo) return "Folder";
|
||||
var connection = rowObject as ConnectionInfo;
|
||||
if (connection == null) return "";
|
||||
return connection.OpenConnections.Count > 0 ? "Play" : "Pause";
|
||||
}
|
||||
|
||||
private void SetupDropSink()
|
||||
{
|
||||
DropSink = new SimpleDropSink();
|
||||
var dropSink = (SimpleDropSink)DropSink;
|
||||
dropSink.CanDropBetween = true;
|
||||
}
|
||||
|
||||
private void SetEventHandlers()
|
||||
{
|
||||
Collapsed += (sender, args) =>
|
||||
{
|
||||
var container = args.Model as ContainerInfo;
|
||||
if (container != null)
|
||||
container.IsExpanded = false;
|
||||
};
|
||||
Expanded += (sender, args) =>
|
||||
{
|
||||
var container = args.Model as ContainerInfo;
|
||||
if (container != null)
|
||||
container.IsExpanded = true;
|
||||
};
|
||||
SelectionChanged += tvConnections_AfterSelect;
|
||||
CellClick += tvConnections_NodeMouseSingleClick;
|
||||
CellClick += tvConnections_NodeMouseDoubleClick;
|
||||
CellToolTipShowing += tvConnections_CellToolTipShowing;
|
||||
ModelCanDrop += _dragAndDropHandler.HandleEvent_ModelCanDrop;
|
||||
ModelDropped += _dragAndDropHandler.HandleEvent_ModelDropped;
|
||||
}
|
||||
|
||||
private void PopulateTreeView()
|
||||
{
|
||||
UnregisterModelUpdateHandlers();
|
||||
SetObjects(ConnectionTreeModel.RootNodes);
|
||||
RegisterModelUpdateHandlers();
|
||||
NodeSearcher = new NodeSearcher(ConnectionTreeModel);
|
||||
ExpandPreviouslyOpenedFolders();
|
||||
ExpandRootConnectionNode();
|
||||
OpenConnectionsFromLastSession();
|
||||
}
|
||||
|
||||
private void RegisterModelUpdateHandlers()
|
||||
{
|
||||
_puttySessionsManager.PuttySessionsCollectionChanged += OnPuttySessionsCollectionChanged;
|
||||
ConnectionTreeModel.CollectionChanged += HandleCollectionChanged;
|
||||
ConnectionTreeModel.PropertyChanged += HandleCollectionPropertyChanged;
|
||||
}
|
||||
|
||||
private void UnregisterModelUpdateHandlers()
|
||||
{
|
||||
_puttySessionsManager.PuttySessionsCollectionChanged -= OnPuttySessionsCollectionChanged;
|
||||
ConnectionTreeModel.CollectionChanged -= HandleCollectionChanged;
|
||||
ConnectionTreeModel.PropertyChanged -= HandleCollectionPropertyChanged;
|
||||
}
|
||||
|
||||
private void OnPuttySessionsCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
RefreshTreeObjects(GetRootPuttyNodes().ToList());
|
||||
}
|
||||
|
||||
private void HandleCollectionPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
|
||||
{
|
||||
//TODO for some reason property changed events are getting triggered twice for each changed property. should be just once. cant find source of duplication
|
||||
var property = propertyChangedEventArgs.PropertyName;
|
||||
if (property != "Name" && property != "OpenConnections") return;
|
||||
var senderAsConnectionInfo = sender as ConnectionInfo;
|
||||
if (senderAsConnectionInfo != null)
|
||||
RefreshTreeObject(senderAsConnectionInfo);
|
||||
}
|
||||
|
||||
private void ExpandPreviouslyOpenedFolders()
|
||||
{
|
||||
var containerList = ConnectionTreeModel.GetRecursiveChildList(GetRootConnectionNode()).OfType<ContainerInfo>();
|
||||
var previouslyExpandedNodes = containerList.Where(container => container.IsExpanded);
|
||||
ExpandedObjects = previouslyExpandedNodes;
|
||||
this.InvokeRebuildAll(true);
|
||||
}
|
||||
|
||||
private void OpenConnectionsFromLastSession()
|
||||
{
|
||||
if (!Settings.Default.OpenConsFromLastSession || Settings.Default.NoReconnect) return;
|
||||
var connectionInfoList = GetRootConnectionNode().GetRecursiveChildList().Where(node => !(node is ContainerInfo));
|
||||
var previouslyOpenedConnections = connectionInfoList.Where(item => item.PleaseConnect);
|
||||
foreach (var connectionInfo in previouslyOpenedConnections)
|
||||
{
|
||||
ConnectionInitiator.OpenConnection(connectionInfo);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ConnectionTree
|
||||
public void DeleteSelectedNode()
|
||||
{
|
||||
if (SelectedNode is RootNodeInfo || SelectedNode is PuttySessionInfo) return;
|
||||
if (!UserConfirmsDeletion()) return;
|
||||
ConnectionTreeModel.DeleteNode(SelectedNode);
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
private bool UserConfirmsDeletion()
|
||||
{
|
||||
var selectedNodeAsContainer = SelectedNode as ContainerInfo;
|
||||
if (selectedNodeAsContainer != null)
|
||||
return selectedNodeAsContainer.HasChildren()
|
||||
? UserConfirmsNonEmptyFolderDeletion()
|
||||
: UserConfirmsEmptyFolderDeletion();
|
||||
return UserConfirmsConnectionDeletion();
|
||||
}
|
||||
|
||||
private bool UserConfirmsEmptyFolderDeletion()
|
||||
{
|
||||
var messagePrompt = string.Format(Language.strConfirmDeleteNodeFolder, SelectedNode.Name);
|
||||
return PromptUser(messagePrompt);
|
||||
}
|
||||
|
||||
private bool UserConfirmsNonEmptyFolderDeletion()
|
||||
{
|
||||
var messagePrompt = string.Format(Language.strConfirmDeleteNodeFolderNotEmpty, SelectedNode.Name);
|
||||
return PromptUser(messagePrompt);
|
||||
}
|
||||
|
||||
private bool UserConfirmsConnectionDeletion()
|
||||
{
|
||||
var messagePrompt = string.Format(Language.strConfirmDeleteNodeConnection, SelectedNode.Name);
|
||||
return PromptUser(messagePrompt);
|
||||
}
|
||||
|
||||
private static bool PromptUser(string promptMessage)
|
||||
{
|
||||
var msgBoxResponse = MessageBox.Show(promptMessage, Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||||
return (msgBoxResponse == DialogResult.Yes);
|
||||
}
|
||||
|
||||
private void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
var senderAsContainerInfo = sender as ContainerInfo;
|
||||
// ReSharper disable once SwitchStatementMissingSomeCases
|
||||
switch (args?.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
var childList = senderAsContainerInfo?.Children;
|
||||
ConnectionInfo otherChild = null;
|
||||
if (childList?.Count > 1)
|
||||
otherChild = childList.First(child => !args.NewItems.Contains(child));
|
||||
RefreshTreeObject(otherChild ?? senderAsContainerInfo);
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
RefreshTreeObjects(args.OldItems);
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Move:
|
||||
RefreshTreeObjects(args.OldItems);
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Reset:
|
||||
RefreshTreeObject(senderAsContainerInfo);
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Replace:
|
||||
break;
|
||||
case null:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshTreeObject(ConnectionInfo modelObject)
|
||||
{
|
||||
RefreshObject(modelObject);
|
||||
}
|
||||
|
||||
private void RefreshTreeObjects(IList modelObjects)
|
||||
{
|
||||
RefreshObjects(modelObjects);
|
||||
}
|
||||
|
||||
public void AddConnection()
|
||||
{
|
||||
try
|
||||
{
|
||||
AddNode(new ConnectionInfo());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("UI.Window.Tree.AddConnection() failed.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddFolder()
|
||||
{
|
||||
try
|
||||
{
|
||||
AddNode(new ContainerInfo());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strErrorAddFolderFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddNode(ConnectionInfo newNode)
|
||||
{
|
||||
if (SelectedNode == null) return;
|
||||
DefaultConnectionInfo.Instance.SaveTo(newNode);
|
||||
DefaultConnectionInheritance.Instance.SaveTo(newNode.Inheritance);
|
||||
var selectedContainer = SelectedNode as ContainerInfo;
|
||||
var parent = selectedContainer ?? SelectedNode?.Parent;
|
||||
newNode.SetParent(parent);
|
||||
Expand(parent);
|
||||
SelectObject(newNode);
|
||||
EnsureModelVisible(newNode);
|
||||
}
|
||||
|
||||
public void DisconnectConnection(ConnectionInfo connectionInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (connectionInfo == null) return;
|
||||
var nodeAsContainer = connectionInfo as ContainerInfo;
|
||||
if (nodeAsContainer != null)
|
||||
{
|
||||
foreach (var child in nodeAsContainer.Children)
|
||||
{
|
||||
for (var i = 0; i <= child.OpenConnections.Count - 1; i++)
|
||||
{
|
||||
child.OpenConnections[i].Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i <= connectionInfo.OpenConnections.Count - 1; i++)
|
||||
{
|
||||
connectionInfo.OpenConnections[i].Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("DisconnectConnection (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void SshTransferFile()
|
||||
{
|
||||
try
|
||||
{
|
||||
Windows.Show(WindowType.SSHTransfer);
|
||||
Windows.SshtransferForm.Hostname = SelectedNode.Hostname;
|
||||
Windows.SshtransferForm.Username = SelectedNode.Username;
|
||||
Windows.SshtransferForm.Password = SelectedNode.Password;
|
||||
Windows.SshtransferForm.Port = Convert.ToString(SelectedNode.Port);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("SSHTransferFile (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void StartExternalApp(ExternalTool externalTool)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (SelectedNode.GetTreeNodeType() == TreeNodeType.Connection | SelectedNode.GetTreeNodeType() == TreeNodeType.PuttySession)
|
||||
externalTool.Start(SelectedNode);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("cMenTreeToolsExternalAppsEntry_Click failed (UI.Window.ConnectionTreeWindow)", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExpandRootConnectionNode()
|
||||
{
|
||||
var rootConnectionNode = GetRootConnectionNode();
|
||||
this.InvokeExpand(rootConnectionNode);
|
||||
}
|
||||
|
||||
public void EnsureRootNodeVisible()
|
||||
{
|
||||
EnsureModelVisible(GetRootConnectionNode());
|
||||
}
|
||||
|
||||
private void tvConnections_AfterSelect(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Windows.ConfigForm.SelectedTreeNode = SelectedNode;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("tvConnections_AfterSelect (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void tvConnections_NodeMouseSingleClick(object sender, CellClickEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.ClickCount > 1) return;
|
||||
var clickedNode = e.Model as ConnectionInfo;
|
||||
|
||||
if (clickedNode == null) return;
|
||||
if (clickedNode.GetTreeNodeType() != TreeNodeType.Connection && clickedNode.GetTreeNodeType() != TreeNodeType.PuttySession) return;
|
||||
if (Settings.Default.SingleClickOnConnectionOpensIt)
|
||||
ConnectionInitiator.OpenConnection(SelectedNode);
|
||||
|
||||
if (Settings.Default.SingleClickSwitchesToOpenConnection)
|
||||
ConnectionInitiator.SwitchToOpenConnection(SelectedNode);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("tvConnections_NodeMouseClick (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void tvConnections_NodeMouseDoubleClick(object sender, CellClickEventArgs e)
|
||||
{
|
||||
if (e.ClickCount < 2) return;
|
||||
var clickedNodeAsContainer = e.Model as ContainerInfo;
|
||||
if (clickedNodeAsContainer != null)
|
||||
{
|
||||
ToggleExpansion(clickedNodeAsContainer);
|
||||
}
|
||||
|
||||
var clickedNode = e.Model as ConnectionInfo;
|
||||
if (clickedNode?.GetTreeNodeType() == TreeNodeType.Connection |
|
||||
clickedNode?.GetTreeNodeType() == TreeNodeType.PuttySession)
|
||||
{
|
||||
ConnectionInitiator.OpenConnection(SelectedNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void tvConnections_CellToolTipShowing(object sender, ToolTipShowingEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var nodeProducingTooltip = (ConnectionInfo)e.Model;
|
||||
e.Text = nodeProducingTooltip.Description;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("tvConnections_MouseMove (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public RootNodeInfo GetRootConnectionNode()
|
||||
@@ -40,5 +488,6 @@ namespace mRemoteNG.UI.Controls
|
||||
SelectedItem.BeginEdit();
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -494,13 +494,13 @@ namespace mRemoteNG.UI.Forms
|
||||
|
||||
private void mMenFileNewConnection_Click(object sender, EventArgs e)
|
||||
{
|
||||
ConnectionTreeWindow.AddConnection();
|
||||
ConnectionTreeWindow.ConnectionTree.AddConnection();
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
private void mMenFileNewFolder_Click(object sender, EventArgs e)
|
||||
{
|
||||
ConnectionTreeWindow.AddFolder();
|
||||
ConnectionTreeWindow.ConnectionTree.AddFolder();
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
@@ -546,19 +546,19 @@ namespace mRemoteNG.UI.Forms
|
||||
|
||||
private void mMenFileDelete_Click(object sender, EventArgs e)
|
||||
{
|
||||
ConnectionTreeWindow.DeleteSelectedNode();
|
||||
ConnectionTreeWindow.ConnectionTree.DeleteSelectedNode();
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
private void mMenFileRename_Click(object sender, EventArgs e)
|
||||
{
|
||||
ConnectionTreeWindow.RenameSelectedNode();
|
||||
ConnectionTreeWindow.ConnectionTree.RenameSelectedNode();
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
private void mMenFileDuplicate_Click(object sender, EventArgs e)
|
||||
{
|
||||
ConnectionTreeWindow.DuplicateSelectedNode();
|
||||
ConnectionTreeWindow.ConnectionTree.DuplicateSelectedNode();
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
|
||||
22
mRemoteV1/UI/Window/ConnectionTreeWindow.Designer.cs
generated
22
mRemoteV1/UI/Window/ConnectionTreeWindow.Designer.cs
generated
@@ -7,7 +7,6 @@ namespace mRemoteNG.UI.Window
|
||||
#region Windows Form Designer generated code
|
||||
internal System.Windows.Forms.TextBox txtSearch;
|
||||
internal System.Windows.Forms.Panel pnlConnections;
|
||||
internal System.Windows.Forms.ImageList imgListTree;
|
||||
internal System.Windows.Forms.MenuStrip msMain;
|
||||
internal System.Windows.Forms.ToolStripMenuItem mMenView;
|
||||
internal System.Windows.Forms.ToolStripMenuItem mMenViewExpandAllFolders;
|
||||
@@ -17,13 +16,10 @@ namespace mRemoteNG.UI.Window
|
||||
internal System.Windows.Forms.ToolStripMenuItem mMenAddConnection;
|
||||
internal System.Windows.Forms.ToolStripMenuItem mMenAddFolder;
|
||||
public System.Windows.Forms.TreeView tvConnections;
|
||||
public mRemoteNG.UI.Controls.ConnectionTree olvConnections;
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.olvConnections = new mRemoteNG.UI.Controls.ConnectionTree();
|
||||
this.olvNameColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
|
||||
this.imgListTree = new System.Windows.Forms.ImageList(this.components);
|
||||
this.pnlConnections = new System.Windows.Forms.Panel();
|
||||
this.PictureBox1 = new System.Windows.Forms.PictureBox();
|
||||
this.txtSearch = new System.Windows.Forms.TextBox();
|
||||
@@ -42,15 +38,12 @@ namespace mRemoteNG.UI.Window
|
||||
//
|
||||
// olvConnections
|
||||
//
|
||||
this.olvConnections.AllColumns.Add(this.olvNameColumn);
|
||||
this.olvConnections.AllowDrop = true;
|
||||
this.olvConnections.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.olvConnections.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.olvConnections.CellEditUseWholeCell = false;
|
||||
this.olvConnections.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.olvNameColumn});
|
||||
this.olvConnections.Cursor = System.Windows.Forms.Cursors.Default;
|
||||
this.olvConnections.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
|
||||
this.olvConnections.HideSelection = false;
|
||||
@@ -64,7 +57,6 @@ namespace mRemoteNG.UI.Window
|
||||
this.olvConnections.SelectedForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
this.olvConnections.ShowGroups = false;
|
||||
this.olvConnections.Size = new System.Drawing.Size(192, 410);
|
||||
this.olvConnections.SmallImageList = this.imgListTree;
|
||||
this.olvConnections.TabIndex = 20;
|
||||
this.olvConnections.UnfocusedSelectedBackColor = System.Drawing.SystemColors.Highlight;
|
||||
this.olvConnections.UnfocusedSelectedForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
@@ -72,18 +64,6 @@ namespace mRemoteNG.UI.Window
|
||||
this.olvConnections.View = System.Windows.Forms.View.Details;
|
||||
this.olvConnections.VirtualMode = true;
|
||||
//
|
||||
// olvNameColumn
|
||||
//
|
||||
this.olvNameColumn.AspectName = "Name";
|
||||
this.olvNameColumn.FillsFreeSpace = true;
|
||||
this.olvNameColumn.IsButton = true;
|
||||
//
|
||||
// imgListTree
|
||||
//
|
||||
this.imgListTree.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit;
|
||||
this.imgListTree.ImageSize = new System.Drawing.Size(16, 16);
|
||||
this.imgListTree.TransparentColor = System.Drawing.Color.Transparent;
|
||||
//
|
||||
// pnlConnections
|
||||
//
|
||||
this.pnlConnections.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
@@ -214,6 +194,6 @@ namespace mRemoteNG.UI.Window
|
||||
#endregion
|
||||
|
||||
private System.ComponentModel.IContainer components;
|
||||
private BrightIdeasSoftware.OLVColumn olvNameColumn;
|
||||
private Controls.ConnectionTree olvConnections;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,10 @@ using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using BrightIdeasSoftware;
|
||||
using mRemoteNG.Config.Putty;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
|
||||
@@ -21,22 +15,14 @@ namespace mRemoteNG.UI.Window
|
||||
{
|
||||
public partial class ConnectionTreeWindow
|
||||
{
|
||||
private ConnectionTreeModel _connectionTreeModel;
|
||||
private readonly ConnectionTreeDragAndDropHandler _dragAndDropHandler = new ConnectionTreeDragAndDropHandler();
|
||||
private NodeSearcher _nodeSearcher;
|
||||
private readonly ConnectionContextMenu _contextMenu = new ConnectionContextMenu();
|
||||
private readonly PuttySessionsManager _puttySessionsManager = PuttySessionsManager.Instance;
|
||||
|
||||
public ConnectionInfo SelectedNode => olvConnections.SelectedNode;
|
||||
|
||||
public ConnectionTreeModel ConnectionTreeModel
|
||||
public ConnectionTree ConnectionTree
|
||||
{
|
||||
get { return _connectionTreeModel; }
|
||||
set
|
||||
{
|
||||
_connectionTreeModel = value;
|
||||
PopulateTreeView();
|
||||
}
|
||||
get { return olvConnections; }
|
||||
set { olvConnections = value; }
|
||||
}
|
||||
|
||||
public ConnectionTreeWindow(DockContent panel)
|
||||
@@ -44,7 +30,10 @@ namespace mRemoteNG.UI.Window
|
||||
WindowType = WindowType.Tree;
|
||||
DockPnl = panel;
|
||||
InitializeComponent();
|
||||
SetupConnectionTreeView();
|
||||
olvConnections.ContextMenuStrip = _contextMenu;
|
||||
SetMenuEventHandlers();
|
||||
SetContextMenuEventHandlers();
|
||||
SetConnectionTreeEventHandlers();
|
||||
}
|
||||
|
||||
#region Form Stuff
|
||||
@@ -88,413 +77,14 @@ namespace mRemoteNG.UI.Window
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ConnectionTree Setup
|
||||
private void SetupConnectionTreeView()
|
||||
#region ConnectionTree
|
||||
private void SetConnectionTreeEventHandlers()
|
||||
{
|
||||
FillImageList();
|
||||
LinkModelToView();
|
||||
SetupDropSink();
|
||||
SetEventHandlers();
|
||||
}
|
||||
|
||||
private void FillImageList()
|
||||
{
|
||||
try
|
||||
{
|
||||
imgListTree.Images.Add(Resources.Root);
|
||||
imgListTree.Images.SetKeyName(0, "Root");
|
||||
imgListTree.Images.Add(Resources.Folder);
|
||||
imgListTree.Images.SetKeyName(1, "Folder");
|
||||
imgListTree.Images.Add(Resources.Play);
|
||||
imgListTree.Images.SetKeyName(2, "Play");
|
||||
imgListTree.Images.Add(Resources.Pause);
|
||||
imgListTree.Images.SetKeyName(3, "Pause");
|
||||
imgListTree.Images.Add(Resources.PuttySessions);
|
||||
imgListTree.Images.SetKeyName(4, "PuttySessions");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("FillImageList (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void LinkModelToView()
|
||||
{
|
||||
olvNameColumn.AspectGetter = item => ((ConnectionInfo)item).Name;
|
||||
olvNameColumn.ImageGetter = ConnectionImageGetter;
|
||||
olvConnections.CanExpandGetter = item =>
|
||||
{
|
||||
var itemAsContainer = item as ContainerInfo;
|
||||
return itemAsContainer?.Children.Count > 0;
|
||||
};
|
||||
olvConnections.ChildrenGetter = item => ((ContainerInfo)item).Children;
|
||||
olvConnections.ContextMenuStrip = _contextMenu;
|
||||
}
|
||||
|
||||
private static object ConnectionImageGetter(object rowObject)
|
||||
{
|
||||
if (rowObject is RootPuttySessionsNodeInfo) return "PuttySessions";
|
||||
if (rowObject is RootNodeInfo) return "Root";
|
||||
if (rowObject is ContainerInfo) return "Folder";
|
||||
var connection = rowObject as ConnectionInfo;
|
||||
if (connection == null) return "";
|
||||
return connection.OpenConnections.Count > 0 ? "Play" : "Pause";
|
||||
}
|
||||
|
||||
private void SetupDropSink()
|
||||
{
|
||||
var dropSink = (SimpleDropSink)olvConnections.DropSink;
|
||||
dropSink.CanDropBetween = true;
|
||||
}
|
||||
|
||||
private void SetEventHandlers()
|
||||
{
|
||||
SetTreeEventHandlers();
|
||||
SetContextMenuEventHandlers();
|
||||
SetMenuEventHandlers();
|
||||
}
|
||||
|
||||
private void SetTreeEventHandlers()
|
||||
{
|
||||
olvConnections.Collapsed += (sender, args) =>
|
||||
{
|
||||
var container = args.Model as ContainerInfo;
|
||||
if (container != null)
|
||||
container.IsExpanded = false;
|
||||
};
|
||||
olvConnections.Expanded += (sender, args) =>
|
||||
{
|
||||
var container = args.Model as ContainerInfo;
|
||||
if (container != null)
|
||||
container.IsExpanded = true;
|
||||
};
|
||||
olvConnections.BeforeLabelEdit += tvConnections_BeforeLabelEdit;
|
||||
olvConnections.AfterLabelEdit += tvConnections_AfterLabelEdit;
|
||||
olvConnections.SelectionChanged += tvConnections_AfterSelect;
|
||||
olvConnections.CellClick += tvConnections_NodeMouseSingleClick;
|
||||
olvConnections.CellClick += tvConnections_NodeMouseDoubleClick;
|
||||
olvConnections.CellToolTipShowing += tvConnections_CellToolTipShowing;
|
||||
olvConnections.ModelCanDrop += _dragAndDropHandler.HandleEvent_ModelCanDrop;
|
||||
olvConnections.ModelDropped += _dragAndDropHandler.HandleEvent_ModelDropped;
|
||||
olvConnections.KeyDown += tvConnections_KeyDown;
|
||||
olvConnections.KeyPress += tvConnections_KeyPress;
|
||||
}
|
||||
|
||||
private void PopulateTreeView()
|
||||
{
|
||||
UnregisterModelUpdateHandlers();
|
||||
olvConnections.SetObjects(ConnectionTreeModel.RootNodes);
|
||||
RegisterModelUpdateHandlers();
|
||||
_nodeSearcher = new NodeSearcher(ConnectionTreeModel);
|
||||
ExpandPreviouslyOpenedFolders();
|
||||
ExpandRootConnectionNode();
|
||||
OpenConnectionsFromLastSession();
|
||||
}
|
||||
|
||||
private void RegisterModelUpdateHandlers()
|
||||
{
|
||||
_puttySessionsManager.PuttySessionsCollectionChanged += OnPuttySessionsCollectionChanged;
|
||||
ConnectionTreeModel.CollectionChanged += HandleCollectionChanged;
|
||||
ConnectionTreeModel.PropertyChanged += HandleCollectionPropertyChanged;
|
||||
}
|
||||
|
||||
private void UnregisterModelUpdateHandlers()
|
||||
{
|
||||
_puttySessionsManager.PuttySessionsCollectionChanged -= OnPuttySessionsCollectionChanged;
|
||||
ConnectionTreeModel.CollectionChanged -= HandleCollectionChanged;
|
||||
ConnectionTreeModel.PropertyChanged -= HandleCollectionPropertyChanged;
|
||||
}
|
||||
|
||||
private void OnPuttySessionsCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
RefreshTreeObjects(olvConnections.GetRootPuttyNodes().ToList());
|
||||
}
|
||||
|
||||
private void HandleCollectionPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
|
||||
{
|
||||
//TODO for some reason property changed events are getting triggered twice for each changed property. should be just once. cant find source of duplication
|
||||
var property = propertyChangedEventArgs.PropertyName;
|
||||
if (property != "Name" && property != "OpenConnections") return;
|
||||
var senderAsConnectionInfo = sender as ConnectionInfo;
|
||||
if (senderAsConnectionInfo != null)
|
||||
RefreshTreeObject(senderAsConnectionInfo);
|
||||
}
|
||||
|
||||
private void ExpandPreviouslyOpenedFolders()
|
||||
{
|
||||
var containerList = ConnectionTreeModel.GetRecursiveChildList(olvConnections.GetRootConnectionNode()).OfType<ContainerInfo>();
|
||||
var previouslyExpandedNodes = containerList.Where(container => container.IsExpanded);
|
||||
olvConnections.ExpandedObjects = previouslyExpandedNodes;
|
||||
olvConnections.InvokeRebuildAll(true);
|
||||
}
|
||||
|
||||
private void OpenConnectionsFromLastSession()
|
||||
{
|
||||
if (!Settings.Default.OpenConsFromLastSession || Settings.Default.NoReconnect) return;
|
||||
var connectionInfoList = olvConnections.GetRootConnectionNode().GetRecursiveChildList().Where(node => !(node is ContainerInfo));
|
||||
var previouslyOpenedConnections = connectionInfoList.Where(item => item.PleaseConnect);
|
||||
foreach (var connectionInfo in previouslyOpenedConnections)
|
||||
{
|
||||
ConnectionInitiator.OpenConnection(connectionInfo);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ConnectionTree
|
||||
public void DuplicateSelectedNode() => olvConnections.DuplicateSelectedNode();
|
||||
|
||||
public void RenameSelectedNode() => olvConnections.RenameSelectedNode();
|
||||
|
||||
public void DeleteSelectedNode()
|
||||
{
|
||||
if (SelectedNode is RootNodeInfo || SelectedNode is PuttySessionInfo) return;
|
||||
if (!UserConfirmsDeletion()) return;
|
||||
ConnectionTreeModel.DeleteNode(SelectedNode);
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
private bool UserConfirmsDeletion()
|
||||
{
|
||||
var selectedNodeAsContainer = SelectedNode as ContainerInfo;
|
||||
if (selectedNodeAsContainer != null)
|
||||
return selectedNodeAsContainer.HasChildren()
|
||||
? UserConfirmsNonEmptyFolderDeletion()
|
||||
: UserConfirmsEmptyFolderDeletion();
|
||||
return UserConfirmsConnectionDeletion();
|
||||
}
|
||||
|
||||
private bool UserConfirmsEmptyFolderDeletion()
|
||||
{
|
||||
var messagePrompt = string.Format(Language.strConfirmDeleteNodeFolder, SelectedNode.Name);
|
||||
return PromptUser(messagePrompt);
|
||||
}
|
||||
|
||||
private bool UserConfirmsNonEmptyFolderDeletion()
|
||||
{
|
||||
var messagePrompt = string.Format(Language.strConfirmDeleteNodeFolderNotEmpty, SelectedNode.Name);
|
||||
return PromptUser(messagePrompt);
|
||||
}
|
||||
|
||||
private bool UserConfirmsConnectionDeletion()
|
||||
{
|
||||
var messagePrompt = string.Format(Language.strConfirmDeleteNodeConnection, SelectedNode.Name);
|
||||
return PromptUser(messagePrompt);
|
||||
}
|
||||
|
||||
private static bool PromptUser(string promptMessage)
|
||||
{
|
||||
var msgBoxResponse = MessageBox.Show(promptMessage, Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||||
return (msgBoxResponse == DialogResult.Yes);
|
||||
}
|
||||
|
||||
private void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
var senderAsContainerInfo = sender as ContainerInfo;
|
||||
// ReSharper disable once SwitchStatementMissingSomeCases
|
||||
switch (args?.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
var childList = senderAsContainerInfo?.Children;
|
||||
ConnectionInfo otherChild = null;
|
||||
if (childList?.Count > 1)
|
||||
otherChild = childList.First(child => !args.NewItems.Contains(child));
|
||||
RefreshTreeObject(otherChild ?? senderAsContainerInfo);
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
RefreshTreeObjects(args.OldItems);
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Move:
|
||||
RefreshTreeObjects(args.OldItems);
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Reset:
|
||||
RefreshTreeObject(senderAsContainerInfo);
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Replace:
|
||||
break;
|
||||
case null:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshTreeObject(ConnectionInfo modelObject)
|
||||
{
|
||||
olvConnections.RefreshObject(modelObject);
|
||||
}
|
||||
|
||||
private void RefreshTreeObjects(IList modelObjects)
|
||||
{
|
||||
olvConnections.RefreshObjects(modelObjects);
|
||||
}
|
||||
|
||||
public void AddConnection()
|
||||
{
|
||||
try
|
||||
{
|
||||
AddNode(new ConnectionInfo());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("UI.Window.Tree.AddConnection() failed.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddFolder()
|
||||
{
|
||||
try
|
||||
{
|
||||
AddNode(new ContainerInfo());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strErrorAddFolderFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddNode(ConnectionInfo newNode)
|
||||
{
|
||||
if (SelectedNode == null) return;
|
||||
DefaultConnectionInfo.Instance.SaveTo(newNode);
|
||||
DefaultConnectionInheritance.Instance.SaveTo(newNode.Inheritance);
|
||||
var selectedContainer = SelectedNode as ContainerInfo;
|
||||
var parent = selectedContainer ?? SelectedNode?.Parent;
|
||||
newNode.SetParent(parent);
|
||||
olvConnections.Expand(parent);
|
||||
olvConnections.SelectObject(newNode);
|
||||
olvConnections.EnsureModelVisible(newNode);
|
||||
}
|
||||
|
||||
private void DisconnectConnection(ConnectionInfo connectionInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (connectionInfo == null) return;
|
||||
var nodeAsContainer = connectionInfo as ContainerInfo;
|
||||
if (nodeAsContainer != null)
|
||||
{
|
||||
foreach (var child in nodeAsContainer.Children)
|
||||
{
|
||||
for (var i = 0; i <= child.OpenConnections.Count - 1; i++)
|
||||
{
|
||||
child.OpenConnections[i].Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i <= connectionInfo.OpenConnections.Count - 1; i++)
|
||||
{
|
||||
connectionInfo.OpenConnections[i].Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("DisconnectConnection (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void SshTransferFile()
|
||||
{
|
||||
try
|
||||
{
|
||||
Windows.Show(WindowType.SSHTransfer);
|
||||
Windows.SshtransferForm.Hostname = SelectedNode.Hostname;
|
||||
Windows.SshtransferForm.Username = SelectedNode.Username;
|
||||
Windows.SshtransferForm.Password = SelectedNode.Password;
|
||||
Windows.SshtransferForm.Port = Convert.ToString(SelectedNode.Port);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("SSHTransferFile (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void StartExternalApp(ExternalTool externalTool)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (SelectedNode.GetTreeNodeType() == TreeNodeType.Connection | SelectedNode.GetTreeNodeType() == TreeNodeType.PuttySession)
|
||||
externalTool.Start(SelectedNode);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("cMenTreeToolsExternalAppsEntry_Click failed (UI.Window.ConnectionTreeWindow)", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExpandRootConnectionNode()
|
||||
{
|
||||
var rootConnectionNode = olvConnections.GetRootConnectionNode();
|
||||
olvConnections.InvokeExpand(rootConnectionNode);
|
||||
}
|
||||
|
||||
public void EnsureRootNodeVisible()
|
||||
{
|
||||
olvConnections.EnsureModelVisible(olvConnections.GetRootConnectionNode());
|
||||
}
|
||||
|
||||
private void tvConnections_AfterSelect(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Windows.ConfigForm.SelectedTreeNode = SelectedNode;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("tvConnections_AfterSelect (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void tvConnections_NodeMouseSingleClick(object sender, CellClickEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.ClickCount > 1) return;
|
||||
var clickedNode = e.Model as ConnectionInfo;
|
||||
|
||||
if (clickedNode == null) return;
|
||||
if (clickedNode.GetTreeNodeType() != TreeNodeType.Connection && clickedNode.GetTreeNodeType() != TreeNodeType.PuttySession) return;
|
||||
if (Settings.Default.SingleClickOnConnectionOpensIt)
|
||||
ConnectionInitiator.OpenConnection(SelectedNode);
|
||||
|
||||
if (Settings.Default.SingleClickSwitchesToOpenConnection)
|
||||
ConnectionInitiator.SwitchToOpenConnection(SelectedNode);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("tvConnections_NodeMouseClick (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void tvConnections_NodeMouseDoubleClick(object sender, CellClickEventArgs e)
|
||||
{
|
||||
if (e.ClickCount < 2) return;
|
||||
var clickedNodeAsContainer = e.Model as ContainerInfo;
|
||||
if (clickedNodeAsContainer != null)
|
||||
{
|
||||
olvConnections.ToggleExpansion(clickedNodeAsContainer);
|
||||
}
|
||||
|
||||
var clickedNode = e.Model as ConnectionInfo;
|
||||
if (clickedNode?.GetTreeNodeType() == TreeNodeType.Connection |
|
||||
clickedNode?.GetTreeNodeType() == TreeNodeType.PuttySession)
|
||||
{
|
||||
ConnectionInitiator.OpenConnection(SelectedNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void tvConnections_CellToolTipShowing(object sender, ToolTipShowingEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var nodeProducingTooltip = (ConnectionInfo)e.Model;
|
||||
e.Text = nodeProducingTooltip.Description;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("tvConnections_MouseMove (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Top Menu
|
||||
@@ -562,11 +152,11 @@ namespace mRemoteNG.UI.Window
|
||||
else
|
||||
ConnectionInitiator.OpenConnection(SelectedNode, ConnectionInfo.Force.OverridePanel | ConnectionInfo.Force.DoNotJump);
|
||||
};
|
||||
_contextMenu.DisconnectClicked += (sender, args) => DisconnectConnection(SelectedNode);
|
||||
_contextMenu.TransferFileClicked += (sender, args) => SshTransferFile();
|
||||
_contextMenu.DuplicateClicked += (sender, args) => DuplicateSelectedNode();
|
||||
_contextMenu.RenameClicked += (sender, args) => RenameSelectedNode();
|
||||
_contextMenu.DeleteClicked += (sender, args) => DeleteSelectedNode();
|
||||
_contextMenu.DisconnectClicked += (sender, args) => olvConnections.DisconnectConnection(SelectedNode);
|
||||
_contextMenu.TransferFileClicked += (sender, args) => olvConnections.SshTransferFile();
|
||||
_contextMenu.DuplicateClicked += (sender, args) => olvConnections.DuplicateSelectedNode();
|
||||
_contextMenu.RenameClicked += (sender, args) => olvConnections.RenameSelectedNode();
|
||||
_contextMenu.DeleteClicked += (sender, args) => olvConnections.DeleteSelectedNode();
|
||||
_contextMenu.ImportFileClicked += (sender, args) =>
|
||||
{
|
||||
var selectedNodeAsContainer = SelectedNode as ContainerInfo ?? SelectedNode.Parent;
|
||||
@@ -581,18 +171,18 @@ namespace mRemoteNG.UI.Window
|
||||
_contextMenu.SortDescendingClicked += (sender, args) => SortNodesRecursive(SelectedNode, ListSortDirection.Descending);
|
||||
_contextMenu.MoveUpClicked += cMenTreeMoveUp_Click;
|
||||
_contextMenu.MoveDownClicked += cMenTreeMoveDown_Click;
|
||||
_contextMenu.ExternalToolClicked += (sender, args) => StartExternalApp((ExternalTool)((ToolStripMenuItem)sender).Tag);
|
||||
_contextMenu.ExternalToolClicked += (sender, args) => olvConnections.StartExternalApp((ExternalTool)((ToolStripMenuItem)sender).Tag);
|
||||
}
|
||||
|
||||
private void cMenTreeAddConnection_Click(object sender, EventArgs e)
|
||||
{
|
||||
AddConnection();
|
||||
olvConnections.AddConnection();
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
private void cMenTreeAddFolder_Click(object sender, EventArgs e)
|
||||
{
|
||||
AddFolder();
|
||||
olvConnections.AddFolder();
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
@@ -632,7 +222,7 @@ namespace mRemoteNG.UI.Window
|
||||
try
|
||||
{
|
||||
_contextMenu.EnableShortcutKeys();
|
||||
ConnectionTreeModel.RenameNode(SelectedNode, e.Label);
|
||||
ConnectionTree.ConnectionTreeModel.RenameNode(SelectedNode, e.Label);
|
||||
Windows.ConfigForm.SelectedTreeNode = SelectedNode;
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
@@ -669,13 +259,13 @@ namespace mRemoteNG.UI.Window
|
||||
}
|
||||
else if (e.KeyCode == Keys.Up)
|
||||
{
|
||||
var match = _nodeSearcher.PreviousMatch();
|
||||
var match = olvConnections.NodeSearcher.PreviousMatch();
|
||||
JumpToNode(match);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.KeyCode == Keys.Down)
|
||||
{
|
||||
var match = _nodeSearcher.NextMatch();
|
||||
var match = olvConnections.NodeSearcher.NextMatch();
|
||||
JumpToNode(match);
|
||||
e.Handled = true;
|
||||
}
|
||||
@@ -693,8 +283,8 @@ namespace mRemoteNG.UI.Window
|
||||
private void txtSearch_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (txtSearch.Text == "") return;
|
||||
_nodeSearcher?.SearchByName(txtSearch.Text);
|
||||
JumpToNode(_nodeSearcher?.CurrentMatch);
|
||||
olvConnections.NodeSearcher?.SearchByName(txtSearch.Text);
|
||||
JumpToNode(olvConnections.NodeSearcher?.CurrentMatch);
|
||||
}
|
||||
|
||||
private void JumpToNode(ConnectionInfo connectionInfo)
|
||||
|
||||
@@ -117,9 +117,6 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="imgListTree.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="msMain.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>119, 19</value>
|
||||
</metadata>
|
||||
|
||||
Reference in New Issue
Block a user