doublecmd/src/uconnectionmanager.pas
2021-04-25 13:19:51 +03:00

243 lines
7 KiB
ObjectPascal

unit uConnectionManager;
{$mode delphi}
interface
uses
Classes, SysUtils, uFileSource, uDrive, uDrivesList;
type
TFileSourceRecord = record
Count: Integer;
Name, Path: String;
FileSource: IFileSource;
end;
PFileSourceRecord = ^TFileSourceRecord;
function GetNetworkPath(ADrive: PDrive): String;
procedure UpdateDriveList(ADriveList: TDrivesList);
procedure ShowVirtualDriveMenu(ADrive: PDrive; X, Y : Integer; CloseEvent: TNotifyEvent);
procedure AddNetworkConnection(const Name, Path: String; FileSource: IFileSource);
procedure RemoveNetworkConnection(const Name, Path: String);
procedure CloseNetworkConnection();
var
WfxConnectionList: TStringList = nil;
implementation
uses
Forms, Menus, StrUtils, DCStrUtils, fMain, uWfxPluginFileSource, uLog,
uGlobs, uFileSourceUtil, uFileView;
var
ContextMenu: TPopupMenu = nil;
function GetConnectionName(const Name, Path: String): String; inline;
begin
Result:= Name + ': ' + Path;
end;
function NewFileSourceRecord(FileSource: IFileSource; const Name, Path: String): PFileSourceRecord;
begin
New(Result);
Result^.Count:= 1;
Result^.Name:= Name;
Result^.Path:= Path;
Result^.FileSource:= FileSource;
end;
procedure DisposeFileSourceRecord(FileSourceRecord: PFileSourceRecord);
begin
FileSourceRecord^.FileSource:= nil;
Dispose(FileSourceRecord);
end;
procedure CloseConnection(Index: Integer);
var
Connection: TFileSourceRecord;
FileSource: IWfxPluginFileSource;
begin
PFileSourceRecord(WfxConnectionList.Objects[Index]).Count:= 1;
Connection:= PFileSourceRecord(WfxConnectionList.Objects[Index])^;
FileSource:= Connection.FileSource as IWfxPluginFileSource;
if FileSource.WfxModule.WfxDisconnect(Connection.Path) then
begin
RemoveNetworkConnection(Connection.Name, Connection.Path);
end;
with frmMain do
begin
if ActiveFrame.FileSource.Equals(FileSource) and
IsInPath(Connection.Path, ActiveFrame.CurrentPath, True, True) then
begin
ActiveFrame.RemoveCurrentFileSource;
end
else if NotActiveFrame.FileSource.Equals(FileSource) and
IsInPath(Connection.Path, NotActiveFrame.CurrentPath, True, True) then
begin
NotActiveFrame.RemoveCurrentFileSource
end;
end;
end;
procedure OnNetworkDisconnect(Self, Sender: TObject);
var
Index: Integer;
MenuItem: TMenuItem absolute Sender;
begin
Index:= WfxConnectionList.IndexOf(MenuItem.Hint);
if Index >= 0 then CloseConnection(Index);
end;
function GetNetworkPath(ADrive: PDrive): String;
begin
Result:= ADrive^.DeviceId + StringReplace(ADrive^.Path, '\', '/', [rfReplaceAll]);
end;
procedure UpdateDriveList(ADriveList: TDrivesList);
var
Drive: PDrive;
Index: Integer;
FileSourceRecord: PFileSourceRecord;
begin
for Index:= 0 to WfxConnectionList.Count - 1 do
begin
FileSourceRecord:= PFileSourceRecord(WfxConnectionList.Objects[Index]);
New(Drive);
Drive^.DriveSize:= 0;
Drive^.IsMounted:= True;
Drive^.DriveType:= dtVirtual;
Drive^.Path:= FileSourceRecord.Path;
Drive^.DisplayName:= IntToStr(Index);
Drive^.DeviceId:= 'wfx://' + FileSourceRecord.Name;
Drive^.DriveLabel:= GetConnectionName(FileSourceRecord.Name, FileSourceRecord.Path);
ADriveList.Add(Drive);
end;
end;
procedure ShowVirtualDriveMenu(ADrive: PDrive; X, Y: Integer; CloseEvent: TNotifyEvent);
var
Handler: TMethod;
MenuItem: TMenuItem;
begin
if not StrBegins(ADrive^.DeviceId, 'wfx://') then
Exit;
// Free previous created menu
FreeAndNil(ContextMenu);
// Create new context menu
ContextMenu:= TPopupMenu.Create(nil);
ContextMenu.OnClose := CloseEvent;
MenuItem:= TMenuItem.Create(ContextMenu);
MenuItem.Caption:= ADrive.DriveLabel;
MenuItem.Enabled:= False;
ContextMenu.Items.Add(MenuItem);
MenuItem:= TMenuItem.Create(ContextMenu);
MenuItem.Caption:= '-';
ContextMenu.Items.Add(MenuItem);
MenuItem:= TMenuItem.Create(ContextMenu);
MenuItem.Caption:= frmMain.actNetworkDisconnect.Caption;
MenuItem.Hint:= ADrive.DriveLabel;
Handler.Data:= MenuItem;
Handler.Code:= @OnNetworkDisconnect;
MenuItem.OnClick:= TNotifyEvent(Handler);
ContextMenu.Items.Add(MenuItem);
// Show context menu
ContextMenu.PopUp(X, Y);
end;
procedure AddNetworkConnection(const Name, Path: String; FileSource: IFileSource);
var
Index: Integer;
ConnectionName: String;
FileSourceRecord: PFileSourceRecord;
begin
ConnectionName:= GetConnectionName(Name, Path);
Index:= WfxConnectionList.IndexOf(ConnectionName);
if Index >= 0 then begin
FileSourceRecord:= PFileSourceRecord(WfxConnectionList.Objects[Index]);
FileSourceRecord.Count:= FileSourceRecord.Count + 1;
end
else begin
FileSourceRecord:= NewFileSourceRecord(FileSource, Name, Path);
WfxConnectionList.AddObject(ConnectionName, TObject(FileSourceRecord));
with frmMain do
begin
miNetworkDisconnect.Enabled:= WfxConnectionList.Count > 0;
UpdateDiskCount;
end;
end;
end;
procedure RemoveNetworkConnection(const Name, Path: String);
var
Index: Integer;
ConnectionName: String;
FileSourceRecord: PFileSourceRecord;
begin
ConnectionName:= GetConnectionName(Name, Path);
Index:= WfxConnectionList.IndexOf(ConnectionName);
if Index >= 0 then
with frmMain do
begin
FileSourceRecord:= PFileSourceRecord(WfxConnectionList.Objects[Index]);
FileSourceRecord^.Count:= FileSourceRecord^.Count - 1;
if FileSourceRecord^.Count > 0 then Exit;
DisposeFileSourceRecord(PFileSourceRecord(WfxConnectionList.Objects[Index]));
WfxConnectionList.Delete(Index);
miNetworkDisconnect.Enabled:= WfxConnectionList.Count > 0;
if WfxConnectionList.Count = 0 then
begin
if gLogWindow = False then
begin
ShowLogWindow(PtrInt(False));
end;
end;
UpdateDiskCount;
end;
end;
procedure CloseNetworkConnection;
var
Index: Integer;
ConnectionName: String;
FileView: TFileView = nil;
begin
if WfxConnectionList.Count > 0 then
with frmMain do
begin
if ActiveFrame.FileSource.IsInterface(IWfxPluginFileSource) and (ActiveFrame.CurrentPath <> PathDelim) then
FileView:= ActiveFrame
else if NotActiveFrame.FileSource.IsInterface(IWfxPluginFileSource) and (NotActiveFrame.CurrentPath <> PathDelim) then begin
FileView:= NotActiveFrame
end;
if Assigned(FileView) then
begin
ConnectionName:= ExtractWord(2, FileView.CurrentAddress, ['/']);
ConnectionName:= GetConnectionName(ConnectionName, PathDelim + ExtractWord(1, FileView.CurrentPath, [PathDelim]));
Index:= WfxConnectionList.IndexOf(ConnectionName);
if Index >= 0 then CloseConnection(Index);
end
// Close last connection
else begin
CloseConnection(WfxConnectionList.Count - 1);
end;
end;
end;
initialization
WfxConnectionList:= TStringList.Create;
finalization
FreeAndNil(WfxConnectionList);
end.