mirror of
https://github.com/winscp/winscp.git
synced 2026-10-24 02:28:55 +03:00
3013 lines
108 KiB
C++
3013 lines
108 KiB
C++
//---------------------------------------------------------------------------
|
|
#include <WinPCH.h>
|
|
#pragma hdrstop
|
|
|
|
#include "ScpCommander.h"
|
|
|
|
#include <DragDrop.hpp>
|
|
#include "Glyphs.h"
|
|
#include "NonVisual.h"
|
|
#include "TerminalManager.h"
|
|
#include "Bookmarks.h"
|
|
//---------------------------------------------------------------------------
|
|
#pragma link "CustomDirView"
|
|
#pragma link "CustomScpExplorer"
|
|
#pragma link "CustomUnixDirView"
|
|
#pragma link "IEListView"
|
|
#pragma link "NortonLikeListView"
|
|
#pragma link "UnixDirView"
|
|
#pragma link "DirView"
|
|
#pragma link "PathLabel"
|
|
#pragma link "HistoryComboBox"
|
|
#pragma link "CustomDriveView"
|
|
#pragma link "DriveView"
|
|
#pragma link "UnixDriveView"
|
|
#pragma link "TB2Dock"
|
|
#pragma link "TB2Item"
|
|
#pragma link "TB2Toolbar"
|
|
#pragma link "TBX"
|
|
#pragma link "TB2ExtItems"
|
|
#pragma link "TBXExtItems"
|
|
#pragma link "TBXLists"
|
|
#pragma link "TBXStatusBars"
|
|
#pragma link "TBXToolPals"
|
|
#pragma link "ThemePageControl"
|
|
#pragma link "DriveViewInt"
|
|
#pragma link "DirViewInt"
|
|
#pragma resource "*.dfm"
|
|
//---------------------------------------------------------------------------
|
|
class TSynchronizedBrowsingGuard
|
|
{
|
|
public:
|
|
TSynchronizedBrowsingGuard()
|
|
{
|
|
FWasSynchronisingBrowsing = NonVisualDataModule->SynchronizeBrowsingAction2->Checked;
|
|
NonVisualDataModule->SynchronizeBrowsingAction2->Checked = false;
|
|
}
|
|
|
|
~TSynchronizedBrowsingGuard()
|
|
{
|
|
NonVisualDataModule->SynchronizeBrowsingAction2->Checked = FWasSynchronisingBrowsing;
|
|
}
|
|
|
|
private:
|
|
bool FWasSynchronisingBrowsing;
|
|
};
|
|
//---------------------------------------------------------------------------
|
|
__fastcall TScpCommanderForm::TScpCommanderForm(TComponent* Owner)
|
|
: TCustomScpExplorerForm(Owner)
|
|
{
|
|
FConstructed = true;
|
|
FCurrentSide = osLocal;
|
|
FLastLeftPanelWidth = LeftPanelWidth;
|
|
FNormalPanelsWidth = -1;
|
|
FSynchronisingBrowse = false;
|
|
FFirstTerminal = true;
|
|
FInternalDDDownloadList = new TStringList();
|
|
FLocalPathComboBoxPaths = new TStringList();
|
|
FOtherLocalPathComboBoxPaths = new TStringList();
|
|
|
|
DriveInfo->AddHandler(DriveNotification);
|
|
LocalPathComboUpdateDrives();
|
|
|
|
LocalBackButton->LinkSubitems = HistoryMenu(osLocal, true)->Items;
|
|
LocalForwardButton->LinkSubitems = HistoryMenu(osLocal, false)->Items;
|
|
RemoteBackButton->LinkSubitems = HistoryMenu(osRemote, true)->Items;
|
|
RemoteForwardButton->LinkSubitems = HistoryMenu(osRemote, false)->Items;
|
|
|
|
TopDock->PopupMenu = NonVisualDataModule->CommanderBarPopup;
|
|
CopyPopup(StatusBar, TopDock);
|
|
CopyPopup(QueueDock, TopDock);
|
|
CopyPopup(QueueLabel, TopDock);
|
|
CopyPopup(BottomDock, TopDock);
|
|
CopyPopup(QueueSeparatorPanel, TopDock);
|
|
CopyPopup(QueueFileList, TopDock);
|
|
CopyPopup(QueueFileListSplitter, TopDock);
|
|
|
|
LocalTopDock->PopupMenu = NonVisualDataModule->LocalPanelPopup;
|
|
CopyPopup(LocalPathLabel, LocalTopDock);
|
|
CopyPopup(LocalStatusBar, LocalTopDock);
|
|
CopyPopup(LocalDriveView, LocalTopDock);
|
|
CopyPopup(LocalBottomDock, LocalTopDock);
|
|
|
|
RemoteTopDock->PopupMenu = NonVisualDataModule->RemotePanelPopup;
|
|
CopyPopup(RemotePathLabel, RemoteTopDock);
|
|
CopyPopup(RemoteStatusBar, RemoteTopDock);
|
|
CopyPopup(RemoteDriveView, RemoteTopDock);
|
|
CopyPopup(OtherLocalDriveView, RemoteTopDock);
|
|
CopyPopup(RemoteBottomDock, RemoteTopDock);
|
|
|
|
SetShortcuts();
|
|
Splitter->ShowHint = True;
|
|
LocalPanelSplitter->ShowHint = true;
|
|
reinterpret_cast<TLabel*>(Splitter)->OnDblClick = SplitterDblClick;
|
|
reinterpret_cast<TLabel*>(LocalPanelSplitter)->OnDblClick = PanelSplitterDblClick;
|
|
reinterpret_cast<TLabel*>(RemotePanelSplitter)->OnDblClick = PanelSplitterDblClick;
|
|
|
|
CommandLineCombo->Text = L"";
|
|
FCommandLineComboPopulated = false;
|
|
|
|
for (int i = 0; i < Toolbar2Toolbar->Items->Count; i++)
|
|
{
|
|
UpdateToolbar2ItemCaption(Toolbar2Toolbar->Items->Items[i]);
|
|
}
|
|
|
|
UseDesktopFont(LocalDirView);
|
|
UseDesktopFont(LocalDriveView);
|
|
UseDesktopFont(LocalPathLabel);
|
|
UseDesktopFont(RemotePathLabel);
|
|
UseDesktopFont(LocalStatusBar);
|
|
UseDesktopFont(StatusBar);
|
|
UseDesktopFont(OtherLocalDirView);
|
|
UseDesktopFont(OtherLocalDriveView);
|
|
|
|
OtherLocalDirView->Align = RemoteDirView->Align;
|
|
OtherLocalDriveView->Align = RemoteDriveView->Align;
|
|
|
|
NonVisualDataModule->QueueSpeedComboBoxItem(QueueSpeedComboBoxItem);
|
|
// particularly to reorder panels on right-to-left bidi mode
|
|
ConfigurationChanged();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
__fastcall TScpCommanderForm::~TScpCommanderForm()
|
|
{
|
|
DriveInfo->RemoveHandler(DriveNotification);
|
|
delete FInternalDDDownloadList;
|
|
SAFE_DESTROY(FLocalPathComboBoxPaths);
|
|
SAFE_DESTROY(FOtherLocalPathComboBoxPaths);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::UpdateToolbar2ItemCaption(TTBCustomItem * Item)
|
|
{
|
|
Item->Caption =
|
|
ShortCutToText(Item->ShortCut) + L" " +
|
|
StripEllipsis(StripHotkey(Item->Caption));
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::RestoreFormParams()
|
|
{
|
|
DebugAssert(WinConfiguration);
|
|
TCustomScpExplorerForm::RestoreFormParams();
|
|
RestoreForm(WinConfiguration->ScpCommander.WindowParams, this, false, ScpCommanderWindowParamsDefault);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::RestorePanelParams(
|
|
TCustomDirView * DirView, TControl * DriveControl, TTBXStatusBar * StatusBar,
|
|
const TScpCommanderPanelConfiguration & PanelConfiguration)
|
|
{
|
|
DirView->ColProperties->ParamsStr = PanelConfiguration.DirViewParams;
|
|
DirView->DirViewStyle = static_cast<TDirViewStyle>(PanelConfiguration.ViewStyle);
|
|
StatusBar->Visible = PanelConfiguration.StatusBar;
|
|
DriveControl->Visible = PanelConfiguration.DriveView;
|
|
if (DriveControl->Align == alTop)
|
|
{
|
|
DriveControl->Height = LoadDimension(PanelConfiguration.DriveViewHeight, PanelConfiguration.DriveViewHeightPixelsPerInch, this);
|
|
}
|
|
else
|
|
{
|
|
DriveControl->Width = LoadDimension(PanelConfiguration.DriveViewWidth, PanelConfiguration.DriveViewWidthPixelsPerInch, this);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::RestoreParams()
|
|
{
|
|
DebugAssert(Configuration);
|
|
|
|
TCustomScpExplorerForm::RestoreParams();
|
|
LeftPanelWidth = WinConfiguration->ScpCommander.LocalPanelWidth;
|
|
LoadToolbarsLayoutStr(WinConfiguration->ScpCommander.ToolbarsLayout, WinConfiguration->ScpCommander.ToolbarsButtons);
|
|
if (IsUWP())
|
|
{
|
|
UpdatesToolbar->Visible = false;
|
|
}
|
|
SessionsPageControl->Visible = WinConfiguration->ScpCommander.SessionsTabs;
|
|
StatusBar->Visible = WinConfiguration->ScpCommander.StatusBar;
|
|
|
|
RestorePanelParams(LocalDirView, LocalDriveView, LocalStatusBar, WinConfiguration->ScpCommander.LocalPanel);
|
|
RestorePanelParams(RemoteDirView, RemoteDrivePanel, RemoteStatusBar, WinConfiguration->ScpCommander.RemotePanel);
|
|
OtherLocalDirView->ColProperties->ParamsStr = WinConfiguration->ScpCommander.OtherLocalPanelDirViewParams;
|
|
OtherLocalDirView->DirViewStyle = static_cast<TDirViewStyle>(WinConfiguration->ScpCommander.OtherLocalPanelViewStyle);
|
|
FPanelsRestored = true;
|
|
|
|
// just to make sure
|
|
LocalDirView->DirColProperties->ExtVisible = false;
|
|
RemoteDirView->UnixColProperties->ExtVisible = false;
|
|
OtherLocalDirView->DirColProperties->ExtVisible = false;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::StorePanelParams(
|
|
TCustomDirView * DirView, TControl * DriveControl, TTBXStatusBar * StatusBar,
|
|
TScpCommanderPanelConfiguration & PanelConfiguration)
|
|
{
|
|
PanelConfiguration.DirViewParams = DirView->ColProperties->ParamsStr;
|
|
PanelConfiguration.ViewStyle = DirView->DirViewStyle;
|
|
PanelConfiguration.StatusBar = StatusBar->Visible;
|
|
PanelConfiguration.DriveView = DriveControl->Visible;
|
|
if (DriveControl->Align == alTop)
|
|
{
|
|
PanelConfiguration.DriveViewHeight = DriveControl->Height;
|
|
PanelConfiguration.DriveViewHeightPixelsPerInch = GetControlPixelsPerInch(this);
|
|
}
|
|
else
|
|
{
|
|
PanelConfiguration.DriveViewWidth = DriveControl->Width;
|
|
PanelConfiguration.DriveViewWidthPixelsPerInch = GetControlPixelsPerInch(this);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::StoreParams()
|
|
{
|
|
DebugAssert(WinConfiguration);
|
|
|
|
WinConfiguration->BeginUpdate();
|
|
try
|
|
{
|
|
SaveCommandLine();
|
|
|
|
TScpCommanderConfiguration CommanderConfiguration = WinConfiguration->ScpCommander;
|
|
CommanderConfiguration.ToolbarsLayout = GetToolbarsLayoutStr();
|
|
CommanderConfiguration.ToolbarsButtons = GetToolbarsButtonsStr();
|
|
CommanderConfiguration.LocalPanelWidth = LeftPanelWidth;
|
|
CommanderConfiguration.SessionsTabs = SessionsPageControl->Visible;
|
|
CommanderConfiguration.StatusBar = StatusBar->Visible;
|
|
|
|
CommanderConfiguration.CurrentPanel = FCurrentSide;
|
|
|
|
StorePanelParams(LocalDirView, LocalDriveView, LocalStatusBar, CommanderConfiguration.LocalPanel);
|
|
StorePanelParams(RemoteDirView, RemoteDrivePanel, RemoteStatusBar, CommanderConfiguration.RemotePanel);
|
|
CommanderConfiguration.OtherLocalPanelDirViewParams = OtherLocalDirView->ColProperties->ParamsStr;
|
|
CommanderConfiguration.OtherLocalPanelViewStyle = reinterpret_cast<TDirViewStyle>(OtherLocalDirView->DirViewStyle);
|
|
|
|
CommanderConfiguration.LocalPanel.LastPath = LocalDirView->Path;
|
|
CommanderConfiguration.OtherLocalPanelLastPath = OtherLocalDirView->Path;
|
|
|
|
CommanderConfiguration.WindowParams = StoreForm(this);
|
|
|
|
WinConfiguration->ScpCommander = CommanderConfiguration;
|
|
|
|
TCustomScpExplorerForm::StoreParams();
|
|
}
|
|
__finally
|
|
{
|
|
WinConfiguration->EndUpdate();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::UpdateSession(TManagedTerminal * Session)
|
|
{
|
|
TCustomScpExplorerForm::UpdateSession(Session);
|
|
|
|
DebugAssert(LocalDirView != NULL);
|
|
|
|
SAFE_DESTROY(Session->LocalExplorerState);
|
|
SAFE_DESTROY(Session->OtherLocalExplorerState);
|
|
|
|
if (WinConfiguration->PreservePanelState)
|
|
{
|
|
Session->LocalExplorerState = LocalDirView->SaveState();
|
|
|
|
if (IsLocalBrowserMode())
|
|
{
|
|
Session->OtherLocalExplorerState = OtherLocalDirView->SaveState();
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::UpdateSessionData(TSessionData * Data)
|
|
{
|
|
// Keep in sync with TSessionData::CopyStateData
|
|
TCustomScpExplorerForm::UpdateSessionData(Data);
|
|
|
|
DebugAssert(LocalDirView);
|
|
Data->LocalDirectory = LocalDirView->PathName;
|
|
if (IsLocalBrowserMode())
|
|
{
|
|
Data->OtherLocalDirectory = OtherLocalDirView->PathName;
|
|
}
|
|
// Setting both directories makes it a local browser
|
|
DebugAssert(Data->IsLocalBrowser == IsLocalBrowserMode());
|
|
Data->SynchronizeBrowsing = NonVisualDataModule->SynchronizeBrowsingAction2->Checked;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TScpCommanderForm::InternalDDDownload(UnicodeString & TargetDirectory)
|
|
{
|
|
DebugAssert(IsFileControl(FDDTargetControl, osLocal));
|
|
DebugAssert(!IsLocalBrowserMode());
|
|
|
|
bool Result = false;
|
|
if (FDDTargetControl == LocalDirView)
|
|
{
|
|
if (LocalDirView->DropTarget)
|
|
{
|
|
// when drop target is not directory, it is probably file type, which have
|
|
// associated drop handler (such as ZIP file in WinXP). in this case we
|
|
// must leave drop handling to destination application.
|
|
// ! this check is duplicated in LocalDirViewDDTargetHasDropHandler()
|
|
// for shellex downloads
|
|
if (LocalDirView->ItemIsDirectory(LocalDirView->DropTarget))
|
|
{
|
|
TargetDirectory = LocalDirView->ItemFullFileName(LocalDirView->DropTarget);
|
|
Result = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TargetDirectory = DefaultDownloadTargetDirectory();
|
|
Result = true;
|
|
}
|
|
}
|
|
else if (FDDTargetControl == LocalDriveView)
|
|
{
|
|
DebugAssert(LocalDriveView->DropTarget != NULL);
|
|
TargetDirectory = LocalDriveView->NodePathName(LocalDriveView->DropTarget);
|
|
Result = true;
|
|
}
|
|
else
|
|
{
|
|
DebugFail();
|
|
Abort();
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
UnicodeString __fastcall TScpCommanderForm::DefaultDownloadTargetDirectory()
|
|
{
|
|
return IncludeTrailingBackslash(LocalDirView->Path);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TScpCommanderForm::CopyParamDialog(TTransferDirection Direction,
|
|
TTransferType Type, bool Temp, TStrings * FileList, UnicodeString & TargetDirectory,
|
|
TGUICopyParamType & CopyParam, bool Confirm, bool DragDrop, int Options)
|
|
{
|
|
bool Result = false;
|
|
// Temp means d&d here so far, may change in future!
|
|
if (Temp && (Direction == tdToLocal) &&
|
|
IsFileControl(FDDTargetControl, osLocal))
|
|
{
|
|
Result = InternalDDDownload(TargetDirectory);
|
|
if (Result)
|
|
{
|
|
DebugAssert(FileList->Count > 0);
|
|
FInternalDDDownloadList->Assign(FileList);
|
|
}
|
|
}
|
|
else if (!Temp && TargetDirectory.IsEmpty())
|
|
{
|
|
if (Direction == tdToLocal)
|
|
{
|
|
TargetDirectory = DefaultDownloadTargetDirectory();
|
|
}
|
|
else
|
|
{
|
|
TargetDirectory = UnixIncludeTrailingBackslash(RemoteDirView->Path);
|
|
}
|
|
}
|
|
|
|
if (!Result)
|
|
{
|
|
Result = TCustomScpExplorerForm::CopyParamDialog(Direction, Type, Temp,
|
|
FileList, TargetDirectory, CopyParam, Confirm, DragDrop, Options);
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DoShow()
|
|
{
|
|
AddStartupSequence(L"W");
|
|
// Make sure the RemoteDirView is disabled (if not connected yet)
|
|
// before the focusing below,
|
|
// otherwise we disable the view while setting it focused
|
|
// (UpdateControls gets called within the SetFocus),
|
|
// leading to VCL focus inconsistency with Windows,
|
|
// and the view [anything actually] not getting focused after the session
|
|
// is finally connected
|
|
UpdateControls();
|
|
|
|
DoLocalDefaultDirectory(OtherLocalDirView, WinConfiguration->ScpCommander.OtherLocalPanelLastPath, L"P");
|
|
|
|
// If we do not call SetFocus on any control before DoShow,
|
|
// no control will get focused on Login dialog
|
|
// (HACK seems like a bug in VCL)
|
|
if ((WinConfiguration->ScpCommander.CurrentPanel == osLocal) || !DirView(osOther)->Enabled)
|
|
{
|
|
LocalDirView->SetFocus();
|
|
}
|
|
else
|
|
{
|
|
DirView(osOther)->SetFocus();
|
|
}
|
|
|
|
AddStartupSequence(L"U");
|
|
TCustomScpExplorerForm::DoShow();
|
|
|
|
// Need to do do this before the main window really displays.
|
|
// Also the NoSession test in TCustomScpExplorerForm::CMShowingChanged rely on this happening here.
|
|
if (ManagedSession == NULL)
|
|
{
|
|
TTerminalManager::Instance()->NewLocalSession();
|
|
}
|
|
AddStartupSequence(L"O");
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::NeedSession(bool Startup)
|
|
{
|
|
if (ManagedSession == NULL)
|
|
{
|
|
// in the LastTerminalClosed, new session should have already been created by GetReplacementForLastSession
|
|
DebugAssert(Startup);
|
|
|
|
TTerminalManager::Instance()->NewLocalSession();
|
|
}
|
|
|
|
TCustomScpExplorerForm::NeedSession(Startup);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TManagedTerminal * TScpCommanderForm::GetReplacementForLastSession()
|
|
{
|
|
return TTerminalManager::Instance()->NewLocalBrowser();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TScpCommanderForm::NewTab(TOperationSide Side, bool AllowReverse)
|
|
{
|
|
if (Side == osCurrent)
|
|
{
|
|
bool Remote = WinConfiguration->DefaultToNewRemoteTab;
|
|
if (IsKeyPressed(VK_CONTROL) && AllowReverse)
|
|
{
|
|
Remote = !Remote;
|
|
}
|
|
Side = Remote ? osRemote : osLocal;
|
|
}
|
|
|
|
if (Side == osRemote)
|
|
{
|
|
TCustomScpExplorerForm::NewTab();
|
|
}
|
|
else
|
|
{
|
|
TTerminalManager::Instance()->NewLocalSession(LocalDirView->PathName, OtherLocalDirView->PathName);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
Boolean __fastcall TScpCommanderForm::AllowedAction(TAction * Action, TActionAllowed Allowed)
|
|
{
|
|
#define FLAG (static_cast<TActionFlag>(Action->Tag))
|
|
return
|
|
TCustomScpExplorerForm::AllowedAction(Action, Allowed) &&
|
|
// always require Commander flag
|
|
(FLAG & afCommander) &&
|
|
// if action is execution or update, we don't require any other flag
|
|
// if we check for shortcut, we require proper dirview to be selected
|
|
((Allowed != aaShortCut) ||
|
|
((FLAG & afLocal) && (FCurrentSide == osLocal)) ||
|
|
((FLAG & afRemote) && (FCurrentSide == osRemote))
|
|
);
|
|
#undef FLAG
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TCustomDirView * __fastcall TScpCommanderForm::DirView(TOperationSide Side)
|
|
{
|
|
Side = GetSide(Side);
|
|
if (Side == osLocal)
|
|
{
|
|
return LocalDirView;
|
|
}
|
|
else if (DebugAlwaysTrue(Side == osRemote) && IsLocalBrowserMode())
|
|
{
|
|
return OtherLocalDirView;
|
|
}
|
|
else
|
|
{
|
|
return TCustomScpExplorerForm::DirView(Side);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool TScpCommanderForm::IsLocalBrowserMode()
|
|
{
|
|
return OtherLocalDirView->Visible;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TCustomDriveView * __fastcall TScpCommanderForm::DriveView(TOperationSide Side)
|
|
{
|
|
Side = GetSide(Side);
|
|
if (Side == osLocal)
|
|
{
|
|
return LocalDriveView;
|
|
}
|
|
else if (DebugAlwaysTrue(Side == osRemote) && IsLocalBrowserMode())
|
|
{
|
|
return OtherLocalDriveView;
|
|
}
|
|
else
|
|
{
|
|
return TCustomScpExplorerForm::DriveView(Side);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool TScpCommanderForm::SupportsLocalBrowser()
|
|
{
|
|
return true;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool TScpCommanderForm::IsSideLocalBrowser(TOperationSide Side)
|
|
{
|
|
return (GetSide(Side) == osLocal) || IsLocalBrowserMode();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TCustomDirView * TScpCommanderForm::GetCurrentLocalBrowser()
|
|
{
|
|
TOperationSide Side = GetSide(osCurrent);
|
|
if (Side == osLocal)
|
|
{
|
|
return LocalDirView;
|
|
}
|
|
else if (DebugAlwaysTrue(Side == osRemote) && IsLocalBrowserMode())
|
|
{
|
|
return OtherLocalDirView;
|
|
}
|
|
else
|
|
{
|
|
DebugFail();
|
|
Abort();
|
|
return NULL;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TScpCommanderForm::DirViewEnabled(TOperationSide Side)
|
|
{
|
|
if (IsSideLocalBrowser(Side))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return TCustomScpExplorerForm::DirViewEnabled(Side);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TScpCommanderForm::IsFileControl(TObject * Control,
|
|
TOperationSide Side)
|
|
{
|
|
return
|
|
((Side == osLocal) &&
|
|
((Control == LocalDirView) || (Control == LocalDriveView))) ||
|
|
TCustomScpExplorerForm::IsFileControl(Control, Side);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::ReloadLocalDirectory(const UnicodeString Directory)
|
|
{
|
|
if (Directory.IsEmpty() || SamePaths(Directory, LocalDirView->Path))
|
|
{
|
|
LocalDirView->ReloadDirectory();
|
|
LocalDriveView->ValidateDirectory(LocalDriveView->Selected);
|
|
}
|
|
// we may postpone reload, when hidden, as an optimization
|
|
if (Directory.IsEmpty() || SamePaths(Directory, OtherLocalDirView->Path))
|
|
{
|
|
OtherLocalDirView->ReloadDirectory();
|
|
OtherLocalDriveView->ValidateDirectory(OtherLocalDriveView->Selected);
|
|
}
|
|
TCustomScpExplorerForm::ReloadLocalDirectory();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::BatchStart(void *& Storage)
|
|
{
|
|
Storage = new bool;
|
|
*static_cast<bool*>(Storage) = LocalDirView->WatchForChanges;
|
|
LocalDirView->WatchForChanges = false;
|
|
LocalDriveView->WatchDirectory = false;
|
|
OtherLocalDirView->WatchForChanges = false;
|
|
OtherLocalDriveView->WatchDirectory = false;
|
|
|
|
TCustomScpExplorerForm::BatchStart(Storage);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::BatchEnd(void * Storage)
|
|
{
|
|
TCustomScpExplorerForm::BatchEnd(Storage);
|
|
|
|
DebugAssert(Storage != NULL);
|
|
|
|
LocalDirView->WatchForChanges = *static_cast<bool*>(Storage);
|
|
LocalDriveView->WatchDirectory = LocalDirView->WatchForChanges;
|
|
OtherLocalDirView->WatchForChanges = LocalDirView->WatchForChanges;
|
|
OtherLocalDriveView->WatchDirectory = LocalDirView->WatchForChanges;
|
|
|
|
delete static_cast<bool *>(Storage);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::StartingWithoutSession()
|
|
{
|
|
TCustomScpExplorerForm::StartingWithoutSession();
|
|
|
|
AddStartupSequence(L"H");
|
|
LocalDefaultDirectory();
|
|
AddStartupSequence(L"K");
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TScpCommanderForm::RestoreSessionLocalDirView(TDirView * ALocalDirView, const UnicodeString & LocalDirectory)
|
|
{
|
|
// We will load completely different directory, so particularly
|
|
// do not attempt to select previously selected directory.
|
|
// TODO: Does not work, as LastPath is restored in PathChanging.
|
|
ALocalDirView->ContinueSession(false);
|
|
|
|
// reset home directory
|
|
ALocalDirView->HomeDirectory = L"";
|
|
|
|
if (!LocalDirectory.IsEmpty() &&
|
|
(FFirstTerminal || !WinConfiguration->ScpCommander.PreserveLocalDirectory || ManagedSession->LocalBrowser))
|
|
{
|
|
try
|
|
{
|
|
ALocalDirView->Path = LocalDirectory;
|
|
}
|
|
catch(Exception & E)
|
|
{
|
|
if (!ManagedSession->SessionData->UpdateDirectories)
|
|
{
|
|
ManagedSession->ShowExtendedException(&E);
|
|
}
|
|
else
|
|
{
|
|
ALocalDirView->OpenFallbackPath(LocalDirectory);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TScpCommanderForm::AnnounceLocalStates(
|
|
bool RestoreState, bool LocalBrowser, TObject * State, TObject * OtherState)
|
|
{
|
|
if (RestoreState)
|
|
{
|
|
LocalDirView->AnnounceState(State);
|
|
if (LocalBrowser)
|
|
{
|
|
OtherLocalDirView->AnnounceState(OtherState);
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SessionChanged(bool Replaced)
|
|
{
|
|
NonVisualDataModule->SynchronizeBrowsingAction2->Checked = false;
|
|
|
|
TCustomScpExplorerForm::SessionChanged(Replaced);
|
|
|
|
if (ManagedSession != NULL)
|
|
{
|
|
bool RestoreState =
|
|
WinConfiguration->PreservePanelState &&
|
|
(!WinConfiguration->ScpCommander.PreserveLocalDirectory || ManagedSession->LocalBrowser);
|
|
AnnounceLocalStates(
|
|
RestoreState, ManagedSession->LocalBrowser,
|
|
ManagedSession->LocalExplorerState, ManagedSession->OtherLocalExplorerState);
|
|
|
|
try
|
|
{
|
|
RestoreSessionLocalDirView(LocalDirView, ManagedSession->StateData->LocalDirectory);
|
|
|
|
if (ManagedSession->LocalBrowser)
|
|
{
|
|
// Particularly, when switching from a remote to a local-local session,
|
|
// the other local dir view path may not change at all,
|
|
// so the path combo box would retain the remote path.
|
|
OtherLocalPathComboUpdateDrives();
|
|
RestoreSessionLocalDirView(OtherLocalDirView, ManagedSession->StateData->OtherLocalDirectory);
|
|
}
|
|
|
|
FFirstTerminal = false;
|
|
|
|
// Happens when opening a connection from a command-line (StartingWithoutSession was not called),
|
|
// which does not have a local directory set yet.
|
|
// Or when starting with vanila local browser.
|
|
if (LocalDirView->Path.IsEmpty())
|
|
{
|
|
LocalDefaultDirectory();
|
|
}
|
|
|
|
if (WinConfiguration->DefaultDirIsHome &&
|
|
!ManagedSession->SessionData->UpdateDirectories &&
|
|
DebugAlwaysTrue(!ManagedSession->LocalBrowser))
|
|
{
|
|
LocalDirView->HomeDirectory = ManagedSession->SessionData->LocalDirectoryExpanded;
|
|
}
|
|
|
|
if (RestoreState)
|
|
{
|
|
LocalDirView->RestoreState(ManagedSession->LocalExplorerState);
|
|
|
|
if (ManagedSession->LocalBrowser)
|
|
{
|
|
OtherLocalDirView->RestoreState(ManagedSession->OtherLocalExplorerState);
|
|
}
|
|
NonVisualDataModule->SynchronizeBrowsingAction2->Checked = ManagedSession->StateData->SynchronizeBrowsing;
|
|
}
|
|
}
|
|
__finally
|
|
{
|
|
AnnounceLocalStates(RestoreState, ManagedSession->LocalBrowser, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TScpCommanderForm::DoLocalDefaultDirectory(
|
|
TDirView * DirView, const UnicodeString & LastPath, const UnicodeString & StartupSequenceTag)
|
|
{
|
|
bool DocumentsDir = true;
|
|
if (!LastPath.IsEmpty())
|
|
{
|
|
try
|
|
{
|
|
DirView->Path = LastPath;
|
|
DocumentsDir = false;
|
|
}
|
|
catch (...)
|
|
{
|
|
}
|
|
}
|
|
|
|
if (DocumentsDir)
|
|
{
|
|
AddStartupSequence(StartupSequenceTag);
|
|
try
|
|
{
|
|
DirView->HomeDirectory = L"";
|
|
UnicodeString HomeDrive = DriveInfo->GetDriveKey(DirView->HomeDirectory);
|
|
if (DriveInfo->Get(HomeDrive)->DriveType == DRIVE_REMOTE)
|
|
{
|
|
DirView->Path = DriveInfo->AnyValidPath();
|
|
}
|
|
else
|
|
{
|
|
DirView->ExecuteHomeDirectory();
|
|
}
|
|
}
|
|
catch(Exception & E)
|
|
{
|
|
ShowExtendedException(NULL, &E);
|
|
DirView->Path = ExtractFilePath(Application->ExeName);
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalDefaultDirectory()
|
|
{
|
|
DoLocalDefaultDirectory(LocalDirView, WinConfiguration->ScpCommander.LocalPanel.LastPath, L"L");
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::ConfigurationChanged()
|
|
{
|
|
TCustomScpExplorerForm::ConfigurationChanged();
|
|
if (WinConfiguration->DefaultDirIsHome && (ManagedSession != NULL) &&
|
|
!ManagedSession->SessionData->UpdateDirectories)
|
|
{
|
|
LocalDirView->HomeDirectory = ManagedSession->SessionData->LocalDirectoryExpanded;
|
|
}
|
|
else
|
|
{
|
|
LocalDirView->HomeDirectory = L"";
|
|
}
|
|
|
|
LocalDirView->DimmHiddenFiles = WinConfiguration->DimmHiddenFiles;
|
|
LocalDriveView->DimmHiddenDirs = WinConfiguration->DimmHiddenFiles;
|
|
OtherLocalDirView->DimmHiddenFiles = WinConfiguration->DimmHiddenFiles;
|
|
OtherLocalDriveView->DimmHiddenDirs = WinConfiguration->DimmHiddenFiles;
|
|
|
|
LocalDirView->ShowHiddenFiles = WinConfiguration->ShowHiddenFiles;
|
|
LocalDriveView->ShowHiddenDirs = WinConfiguration->ShowHiddenFiles;
|
|
OtherLocalDirView->ShowHiddenFiles = WinConfiguration->ShowHiddenFiles;
|
|
OtherLocalDriveView->ShowHiddenDirs = WinConfiguration->ShowHiddenFiles;
|
|
|
|
LocalDirView->FormatSizeBytes = WinConfiguration->FormatSizeBytes;
|
|
OtherLocalDirView->FormatSizeBytes = WinConfiguration->FormatSizeBytes;
|
|
|
|
LocalDirView->ConfirmOverwrite = WinConfiguration->ConfirmOverwriting;
|
|
LocalDriveView->ConfirmOverwrite = WinConfiguration->ConfirmOverwriting;
|
|
OtherLocalDirView->ConfirmOverwrite = WinConfiguration->ConfirmOverwriting;
|
|
OtherLocalDriveView->ConfirmOverwrite = WinConfiguration->ConfirmOverwriting;
|
|
|
|
LocalDirView->NortonLike = WinConfiguration->ScpCommander.NortonLikeMode;
|
|
OtherLocalDirView->NortonLike = WinConfiguration->ScpCommander.NortonLikeMode;
|
|
RemoteDirView->NortonLike = WinConfiguration->ScpCommander.NortonLikeMode;
|
|
|
|
LocalDirView->NaturalOrderNumericalSorting = WinConfiguration->NaturalOrderNumericalSorting;
|
|
LocalDriveView->NaturalOrderNumericalSorting = WinConfiguration->NaturalOrderNumericalSorting;
|
|
OtherLocalDirView->NaturalOrderNumericalSorting = WinConfiguration->NaturalOrderNumericalSorting;
|
|
OtherLocalDriveView->NaturalOrderNumericalSorting = WinConfiguration->NaturalOrderNumericalSorting;
|
|
|
|
LocalDirView->AlwaysSortDirectoriesByName = WinConfiguration->AlwaysSortDirectoriesByName;
|
|
OtherLocalDirView->AlwaysSortDirectoriesByName = WinConfiguration->AlwaysSortDirectoriesByName;
|
|
|
|
LocalDirView->TimeoutShellIconRetrieval = WinConfiguration->TimeoutShellIconRetrieval;
|
|
LocalDirView->UseIconUpdateThread = WinConfiguration->UseIconUpdateThread;
|
|
OtherLocalDirView->TimeoutShellIconRetrieval = WinConfiguration->TimeoutShellIconRetrieval;
|
|
OtherLocalDirView->UseIconUpdateThread = WinConfiguration->UseIconUpdateThread;
|
|
|
|
UpdateRowSelect(LocalDirView);
|
|
UpdateRowSelect(OtherLocalDirView);
|
|
|
|
// See also LocalDirViewDDTargetHasDropHandler
|
|
LocalDirView->DragDropFilesEx->ShellExtensions->DropHandler = !WinConfiguration->DDFakeFile;
|
|
LocalDriveView->DragDropFilesEx->ShellExtensions->DropHandler = !WinConfiguration->DDFakeFile;
|
|
OtherLocalDirView->DragDropFilesEx->ShellExtensions->DropHandler = !WinConfiguration->DDFakeFile;
|
|
OtherLocalDriveView->DragDropFilesEx->ShellExtensions->DropHandler = !WinConfiguration->DDFakeFile;
|
|
|
|
if (Panel(true)->Left > Panel(false)->Left)
|
|
{
|
|
DisableAlign();
|
|
try
|
|
{
|
|
int AWidth = ClientWidth;
|
|
Panel(false)->Align = alClient;
|
|
// In bidi mode it gets swapped to alRight, what does not work with the rest of this logic
|
|
Splitter->Align = alLeft;
|
|
Panel(true)->Align = alLeft;
|
|
TControl * ControlsOrder[] =
|
|
{ Panel(true), Splitter, Panel(false) };
|
|
SetHorizontalControlsOrder(ControlsOrder, std::size(ControlsOrder));
|
|
Panel(true)->TabOrder = 0;
|
|
Panel(false)->TabOrder = 1;
|
|
ClientWidth = AWidth;
|
|
LeftPanelWidth = FLastLeftPanelWidth;
|
|
}
|
|
__finally
|
|
{
|
|
EnableAlign();
|
|
}
|
|
|
|
int LocalIndex = MenuToolbar->Items->IndexOf(LocalMenuButton);
|
|
int RemoteIndex = MenuToolbar->Items->IndexOf(RemoteMenuButton);
|
|
MenuToolbar->Items->Move(LocalIndex, RemoteIndex);
|
|
RemoteIndex = MenuToolbar->Items->IndexOf(RemoteMenuButton);
|
|
MenuToolbar->Items->Move(RemoteIndex, LocalIndex);
|
|
|
|
SWAP(TShortCut, NonVisualDataModule->LocalChangePathAction2->ShortCut, NonVisualDataModule->RemoteChangePathAction2->ShortCut);
|
|
|
|
SWAP(UnicodeString, NonVisualDataModule->CommanderLocalPanelAction->Caption, NonVisualDataModule->CommanderRemotePanelAction->Caption);
|
|
SWAP(UnicodeString, NonVisualDataModule->CommanderLocalPanelAction->Hint, NonVisualDataModule->CommanderRemotePanelAction->Hint);
|
|
SWAP(int, NonVisualDataModule->LocalLocalCopyAction->ImageIndex, NonVisualDataModule->LocalOtherCopyAction->ImageIndex);
|
|
SWAP(int, NonVisualDataModule->LocalLocalMoveAction->ImageIndex, NonVisualDataModule->LocalOtherMoveAction->ImageIndex);
|
|
}
|
|
|
|
if ((RemoteDrivePanel->Align == alLeft) != WinConfiguration->ScpCommander.TreeOnLeft)
|
|
{
|
|
TScpCommanderPanelConfiguration LocalPanel = WinConfiguration->ScpCommander.LocalPanel;
|
|
TScpCommanderPanelConfiguration RemotePanel = WinConfiguration->ScpCommander.RemotePanel;
|
|
|
|
bool TreeOnLeft = WinConfiguration->ScpCommander.TreeOnLeft;
|
|
|
|
// save value only if it was set yet
|
|
if (FPanelsRestored)
|
|
{
|
|
if (TreeOnLeft)
|
|
{
|
|
// want to be on left, so it is on top, saving height
|
|
LocalPanel.DriveViewHeight = LocalDriveView->Height;
|
|
RemotePanel.DriveViewHeight = RemoteDrivePanel->Height;
|
|
}
|
|
else
|
|
{
|
|
LocalPanel.DriveViewWidth = LocalDriveView->Width;
|
|
RemotePanel.DriveViewWidth = RemoteDrivePanel->Width;
|
|
}
|
|
}
|
|
|
|
TAlign NonClientAlign = (TreeOnLeft ? alLeft : alTop);
|
|
// VCL adjusts cursors only between crVSplit and crHSplit,
|
|
// See TSplitter.RequestAlign
|
|
TCursor SplitterCursor = (TreeOnLeft ? crSizeWE : crSizeNS);
|
|
LocalDriveView->Align = NonClientAlign;
|
|
OtherLocalDriveView->Align = NonClientAlign;
|
|
LocalPanelSplitter->Align = NonClientAlign;
|
|
LocalPanelSplitter->Cursor = SplitterCursor;
|
|
RemoteDrivePanel->Align = NonClientAlign;
|
|
RemotePanelSplitter->Align = NonClientAlign;
|
|
RemotePanelSplitter->Cursor = SplitterCursor;
|
|
FixControlsPlacement();
|
|
|
|
if (TreeOnLeft)
|
|
{
|
|
LocalDriveView->Width = LocalPanel.DriveViewWidth;
|
|
RemoteDrivePanel->Width = RemotePanel.DriveViewWidth;
|
|
}
|
|
else
|
|
{
|
|
LocalDriveView->Height = LocalPanel.DriveViewHeight;
|
|
RemoteDrivePanel->Height = RemotePanel.DriveViewHeight;
|
|
}
|
|
|
|
// in case it triggers config-changed event (does not),
|
|
// make sure it does only after we apply the TreeOnLeft change to avoid endless recursion
|
|
WinConfiguration->ScpCommander.LocalPanel = LocalPanel;
|
|
WinConfiguration->ScpCommander.RemotePanel = RemotePanel;
|
|
}
|
|
|
|
if (FExplorerKeyboardShortcuts != WinConfiguration->ScpCommander.ExplorerKeyboardShortcuts)
|
|
{
|
|
SetShortcuts();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SetShortcuts()
|
|
{
|
|
// set common norton shorcuts to our actions
|
|
NonVisualDataModule->CommanderShortcuts();
|
|
FExplorerKeyboardShortcuts = WinConfiguration->ScpCommander.ExplorerKeyboardShortcuts;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TPanel * __fastcall TScpCommanderForm::Panel(bool Left)
|
|
{
|
|
bool SwappedPanels = WinConfiguration->ScpCommander.SwappedPanels;
|
|
if (IsRightToLeft())
|
|
{
|
|
SwappedPanels = !SwappedPanels;
|
|
}
|
|
return (SwappedPanels == Left ? RemotePanel : LocalPanel);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TPanel * __fastcall TScpCommanderForm::CurrentPanel()
|
|
{
|
|
return (FCurrentSide == osLocal ? LocalPanel : RemotePanel);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SetLeftPanelWidth(double value)
|
|
{
|
|
double Total = LocalPanel->Width + RemotePanel->Width;
|
|
FLeftPanelWidth = value;
|
|
if (value * Total != Panel(true)->Width)
|
|
{
|
|
Panel(true)->Width = static_cast<int>(value * Total);
|
|
UpdateControls();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
double __fastcall TScpCommanderForm::GetLeftPanelWidth()
|
|
{
|
|
return FLeftPanelWidth;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SplitterMoved(TObject * /*Sender*/)
|
|
{
|
|
double Left = Panel(true)->Width;
|
|
double Total = LocalPanel->Width + RemotePanel->Width;
|
|
FLeftPanelWidth = Left / Total;
|
|
FLastLeftPanelWidth = LeftPanelWidth;
|
|
UpdateControls();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SplitterCanResize(TObject * /*Sender*/,
|
|
int &NewSize, bool & /*Accept*/)
|
|
{
|
|
// When splitter is drag so far to right, that width contraint of remote panel would
|
|
// be violated, it doesn't stop, but extend form width.
|
|
// Following prevents this behavior.
|
|
if (ClientWidth - NewSize - Splitter->Width < Panel(false)->Constraints->MinWidth)
|
|
NewSize = (ClientWidth - Panel(false)->Constraints->MinWidth - Splitter->Width);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SplitterDblClick(TObject * /*Sender*/)
|
|
{
|
|
LeftPanelWidth = 0.5;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::PanelSplitterDblClick(TObject * Sender)
|
|
{
|
|
TSplitter * Splitter = dynamic_cast<TSplitter *>(Sender);
|
|
DebugAssert(Splitter != NULL);
|
|
TControl * DriveView;
|
|
TControl * OtherDriveView;
|
|
if (Splitter == LocalPanelSplitter)
|
|
{
|
|
DriveView = LocalDriveView;
|
|
OtherDriveView = RemoteDrivePanel;
|
|
}
|
|
else
|
|
{
|
|
DriveView = RemoteDrivePanel;
|
|
OtherDriveView = LocalDriveView;
|
|
}
|
|
|
|
bool TreeOnLeft = WinConfiguration->ScpCommander.TreeOnLeft;
|
|
DebugAssert(DriveView->Visible);
|
|
if (OtherDriveView->Visible)
|
|
{
|
|
if (TreeOnLeft)
|
|
{
|
|
DriveView->Width = OtherDriveView->Width;
|
|
}
|
|
else
|
|
{
|
|
DriveView->Height = OtherDriveView->Height;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (TreeOnLeft)
|
|
{
|
|
OtherDriveView->Width = DriveView->Width;
|
|
}
|
|
else
|
|
{
|
|
OtherDriveView->Height = DriveView->Height;
|
|
}
|
|
OtherDriveView->Visible = true;
|
|
}
|
|
|
|
FixControlsPlacement();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SetToolbar2ItemAction(TTBXItem * Item, TBasicAction * Action)
|
|
{
|
|
if (Item->Action != Action)
|
|
{
|
|
Item->Action = Action;
|
|
UpdateToolbar2ItemCaption(Item);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TScpCommanderForm::UpdatePanelControls(TCustomDirView * ADirView, TCustomDriveView * ADriveView)
|
|
{
|
|
TCustomScpExplorerForm::UpdatePanelControls(ADirView, ADriveView);
|
|
ADirView->AddParentDir = (ADirView->DirViewStyle == dvsReport);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::UpdateControls()
|
|
{
|
|
// Before TCustomScpExplorerForm disables them (when disconnecting)
|
|
void * Focus = SaveFocus();
|
|
|
|
// When implicitly connecting a not-yet-connected session by switching to its tab opened with workspace,
|
|
// Terminal property is still NULL, but ActiveTerminal is already set.
|
|
// Had we used Terminal for the test, the window would switch to local-local mode temporarily while session is opening.
|
|
bool HasTerminal = (TTerminalManager::Instance()->ActiveTerminal != NULL);
|
|
// Set asap, so that TCustomScpExplorerForm already knows if we are in local-local mode.
|
|
RemoteDirView->Visible = HasTerminal;
|
|
RemoteDriveView->Visible = HasTerminal;
|
|
OtherLocalDirView->Visible = !HasTerminal;
|
|
OtherLocalDriveView->Visible = !HasTerminal;
|
|
|
|
TCustomScpExplorerForm::UpdateControls();
|
|
|
|
UnicodeString SplitterLongHint = Splitter->Hint;
|
|
int P = SplitterLongHint.Pos(L"|");
|
|
if (P == 0)
|
|
{
|
|
P = SplitterLongHint.Pos(L"\n");
|
|
}
|
|
SplitterLongHint.Delete(1, P);
|
|
Splitter->Hint = FORMAT(L"%0.0f%%\n%s", (static_cast<long double>(LeftPanelWidth*100), SplitterLongHint));
|
|
UnicodeString ACommandLinePromptLabel = LoadStr(COMMAND_LINE_LABEL) + " " +
|
|
(!IsSideLocalBrowser(FCurrentSide) ? L"$" : L">");
|
|
if (CommandLinePromptLabel->Caption != ACommandLinePromptLabel)
|
|
{
|
|
CommandLinePromptLabel->Caption = ACommandLinePromptLabel;
|
|
// command line combo width needs to be updated as caption width has probably changed
|
|
ToolBarResize(CommandLineToolbar);
|
|
}
|
|
UpdatePanelControls(LocalDirView, LocalDriveView);
|
|
UpdatePanelControls(OtherLocalDirView, OtherLocalDriveView);
|
|
LocalDirView->Color = PanelColor();
|
|
LocalDriveView->Color = LocalDirView->Color;
|
|
OtherLocalDirView->Color = LocalDirView->Color;
|
|
OtherLocalDriveView->Color = LocalDirView->Color;
|
|
LocalDirView->Font->Color = GetWindowTextColor(LocalDirView->Color);
|
|
LocalDriveView->Font->Color = LocalDirView->Font->Color;
|
|
OtherLocalDirView->Font->Color = LocalDirView->Font->Color;
|
|
OtherLocalDriveView->Font->Color = LocalDirView->Font->Color;
|
|
|
|
LocalColumnsSubmenuItem->Enabled = (DirView(osLocal)->DirViewStyle == dvsReport);
|
|
RemoteColumnsSubmenuItem->Enabled = (DirView(osRemote)->DirViewStyle == dvsReport);
|
|
|
|
if (IsLocalBrowserMode())
|
|
{
|
|
CurrentCopyItem->Visible = false;
|
|
if (FCurrentSide == osLocal)
|
|
{
|
|
CurrentCopyToItem->Action = NonVisualDataModule->LocalLocalCopyAction;
|
|
CurrentMoveToItem->Action = NonVisualDataModule->LocalLocalMoveAction;
|
|
}
|
|
else
|
|
{
|
|
CurrentCopyToItem->Action = NonVisualDataModule->LocalOtherCopyAction;
|
|
CurrentMoveToItem->Action = NonVisualDataModule->LocalOtherMoveAction;
|
|
}
|
|
LocalCopyItem->Action = NonVisualDataModule->LocalLocalCopyAction;
|
|
LocalMoveItem->Action = NonVisualDataModule->LocalLocalMoveAction;
|
|
RemoteCopyItem->Action = NonVisualDataModule->LocalOtherCopyAction;
|
|
RemoteMoveItem->Action = NonVisualDataModule->LocalOtherMoveAction;
|
|
SetToolbar2ItemAction(CurrentCopyToolbar2Item, CurrentCopyToItem->Action);
|
|
SetToolbar2ItemAction(CurrentMoveToolbar2Item, CurrentMoveToItem->Action);
|
|
}
|
|
else
|
|
{
|
|
CurrentCopyItem->Visible = true;
|
|
CurrentCopyToItem->Action = NonVisualDataModule->RemoteCopyToAction;
|
|
CurrentMoveToItem->Action = NonVisualDataModule->RemoteMoveToAction;
|
|
if (IsSideLocalBrowser(FCurrentSide))
|
|
{
|
|
CurrentCopyItem->Action = NonVisualDataModule->LocalCopyAction;
|
|
CurrentMoveItem->Action = NonVisualDataModule->LocalMoveAction;
|
|
CurrentCopyNonQueueItem->Action = NonVisualDataModule->LocalCopyNonQueueAction;
|
|
CurrentCopyQueueItem->Action = NonVisualDataModule->LocalCopyQueueAction;
|
|
}
|
|
else
|
|
{
|
|
CurrentCopyItem->Action = NonVisualDataModule->RemoteCopyAction;
|
|
CurrentMoveItem->Action = NonVisualDataModule->RemoteMoveAction;
|
|
CurrentCopyNonQueueItem->Action = NonVisualDataModule->RemoteCopyNonQueueAction;
|
|
CurrentCopyQueueItem->Action = NonVisualDataModule->RemoteCopyQueueAction;
|
|
}
|
|
LocalCopyItem->Action = NonVisualDataModule->LocalCopyAction;
|
|
LocalMoveItem->Action = NonVisualDataModule->LocalMoveAction;
|
|
RemoteCopyItem->Action = NonVisualDataModule->RemoteCopyAction;
|
|
RemoteMoveItem->Action = NonVisualDataModule->RemoteMoveAction;
|
|
SetToolbar2ItemAction(CurrentCopyToolbar2Item, CurrentCopyItem->Action);
|
|
SetToolbar2ItemAction(CurrentMoveToolbar2Item, CurrentMoveItem->Action);
|
|
}
|
|
|
|
CommandLineCombo->Enabled = IsSideLocalBrowser(FCurrentSide) || CanConsole();
|
|
CommandLinePromptLabel->Enabled = CommandLineCombo->Enabled;
|
|
|
|
// Ad hoc hack to disable the drop down menu, when all its items (and all other buttons on the toolbar) are disabled,
|
|
// otherwise it shines too much on the toolbar.
|
|
RemoteNewSubmenuItem->Enabled = DirViewEnabled(osRemote);
|
|
|
|
bool LocalOnLeft = (Panel(true) == LocalPanel);
|
|
LocalMenuButton->Caption = LoadStr(HasTerminal ? LOCAL_MENU_CAPTION : (LocalOnLeft ? LEFT_MENU_CAPTION : RIGHT_MENU_CAPTION));
|
|
RemoteMenuButton->Caption = LoadStr(HasTerminal ? REMOTE_MENU_CAPTION : (LocalOnLeft ? RIGHT_MENU_CAPTION : LEFT_MENU_CAPTION));
|
|
RestoreFocus(Focus);
|
|
|
|
if (RemotePathLabel->FocusControl != DirView(osOther))
|
|
{
|
|
if (DebugAlwaysTrue(RemotePathLabel->FocusControl != NULL))
|
|
{
|
|
dynamic_cast<TCustomDirView *>(RemotePathLabel->FocusControl)->PathLabel = NULL;
|
|
}
|
|
DirView(osOther)->PathLabel = RemotePathLabel;
|
|
RemotePathLabel->UnixPath = !IsSideLocalBrowser(osOther);
|
|
DirView(osOther)->UpdateStatusBar();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::ChangePath(TOperationSide Side)
|
|
{
|
|
DebugAssert((Side == osLocal) || (Side == osRemote));
|
|
TTBXComboBoxItem * PathComboBox;
|
|
if (Side == osLocal)
|
|
{
|
|
PathComboBox = LocalPathComboBox;
|
|
}
|
|
else
|
|
{
|
|
PathComboBox = RemotePathComboBox;
|
|
}
|
|
ClickToolbarItem(PathComboBox, false);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TControl * __fastcall TScpCommanderForm::GetComponent(Byte Component)
|
|
{
|
|
switch (Component) {
|
|
case fcToolBar2: return Toolbar2Toolbar; // name changed to enforce change of default visibility
|
|
case fcStatusBar: return StatusBar;
|
|
case fcLocalStatusBar: return LocalStatusBar;
|
|
case fcRemoteStatusBar: return RemoteStatusBar;
|
|
case fcCommandLinePanel: return CommandLineToolbar;
|
|
case fcLocalTree: return LocalDriveView;
|
|
case fcSessionToolbar: return SessionToolbar2;
|
|
case fcCustomCommandsBand: return CustomCommandsToolbar;
|
|
case fcColorMenu: return reinterpret_cast<TControl*>(ColorMenuItem);
|
|
case fcTransferDropDown: return reinterpret_cast<TControl*>(TransferDropDown);
|
|
case fcTransferList: return reinterpret_cast<TControl*>(TransferList);
|
|
case fcTransferLabel: return reinterpret_cast<TControl*>(TransferLabel);
|
|
case fcLocalPopup: return reinterpret_cast<TControl *>(NonVisualDataModule->LocalFilePopup);
|
|
case fcRemotePathComboBox: return reinterpret_cast<TControl*>(RemotePathComboBox);
|
|
case fcMenu: return MenuToolbar;
|
|
|
|
case fcCommanderMenuBand: return MenuToolbar;
|
|
case fcCommanderSessionBand: return SessionToolbar2;
|
|
case fcCommanderPreferencesBand: return PreferencesToolbar;
|
|
case fcCommanderSortBand: return SortToolbar;
|
|
case fcCommanderCommandsBand: return CommandsToolbar;
|
|
case fcCommanderUpdatesBand: return UpdatesToolbar;
|
|
case fcCommanderTransferBand: return TransferToolbar;
|
|
case fcCommanderCustomCommandsBand: return CustomCommandsToolbar;
|
|
case fcCommanderLocalHistoryBand: return LocalHistoryToolbar;
|
|
case fcCommanderLocalNavigationBand: return LocalNavigationToolbar;
|
|
case fcCommanderLocalFileBand: return LocalFileToolbar;
|
|
case fcCommanderLocalSelectionBand: return LocalSelectionToolbar;
|
|
case fcCommanderRemoteHistoryBand: return RemoteHistoryToolbar;
|
|
case fcCommanderRemoteNavigationBand: return RemoteNavigationToolbar;
|
|
case fcCommanderRemoteFileBand: return RemoteFileToolbar;
|
|
case fcCommanderRemoteSelectionBand: return RemoteSelectionToolbar;
|
|
default: return TCustomScpExplorerForm::GetComponent(Component);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::FixControlsPlacement()
|
|
{
|
|
TCustomScpExplorerForm::FixControlsPlacement();
|
|
|
|
QueueSeparatorPanel->Visible = QueuePanel->Visible;
|
|
|
|
LocalPanelSplitter->Visible = LocalDriveView->Visible;
|
|
|
|
TControl * ControlsOrder[] =
|
|
{ BottomDock, QueueSeparatorPanel, QueueSplitter, QueuePanel, StatusBar };
|
|
SetVerticalControlsOrder(ControlsOrder, std::size(ControlsOrder));
|
|
|
|
TControl * LocalControlsOrder[] =
|
|
{ LocalTopDock, LocalPathLabel, LocalDriveView, LocalPanelSplitter,
|
|
LocalDirView, LocalBottomDock, LocalStatusBar };
|
|
SetVerticalControlsOrder(LocalControlsOrder, std::size(LocalControlsOrder));
|
|
SetHorizontalControlsOrder(LocalControlsOrder, std::size(LocalControlsOrder));
|
|
|
|
TControl * RemoteControlsOrder[] =
|
|
{ RemoteTopDock, RemotePathLabel, RemoteDrivePanel, RemotePanelSplitter,
|
|
RemoteDirPanel, RemoteBottomDock, RemoteStatusBar };
|
|
SetVerticalControlsOrder(RemoteControlsOrder, std::size(RemoteControlsOrder));
|
|
SetHorizontalControlsOrder(RemoteControlsOrder, std::size(RemoteControlsOrder));
|
|
|
|
MakeFocusedItemVisible(LocalDirView);
|
|
MakeFocusedItemVisible(OtherLocalDirView);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TScpCommanderForm::GetHasDirView(TOperationSide Side)
|
|
{
|
|
return TCustomScpExplorerForm::GetHasDirView(Side) || (Side == osLocal);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::CompareDirectories()
|
|
{
|
|
LocalDirView->CompareFiles(DirView(osOther), false,
|
|
WinConfiguration->ScpCommander.CompareCriterias());
|
|
DirView(osOther)->CompareFiles(LocalDirView, false,
|
|
WinConfiguration->ScpCommander.CompareCriterias());
|
|
if (LocalDirView->SelCount + DirView(osOther)->SelCount == 0)
|
|
{
|
|
UnicodeString Message = MainInstructions(LoadStr(COMPARE_NO_DIFFERENCES));
|
|
MessageDialog(Message, qtInformation, qaOK, HELP_COMPARE_NO_DIFFERENCES);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SynchronizeDirectories()
|
|
{
|
|
DebugAssert(!IsLocalBrowserMode());
|
|
UnicodeString LocalDirectory = LocalDirView->PathName;
|
|
UnicodeString RemoteDirectory = RemoteDirView->PathName;
|
|
DoSynchronizeDirectories(LocalDirectory, RemoteDirectory, -1);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::FullSynchronizeDirectories()
|
|
{
|
|
UnicodeString Directory1 = LocalDirView->PathName;
|
|
UnicodeString Directory2 = DirView(osOther)->PathName;
|
|
bool SaveMode = !(GUIConfiguration->SynchronizeModeAuto < 0);
|
|
TSynchronizeMode Mode =
|
|
(SaveMode ? static_cast<TSynchronizeMode>(GUIConfiguration->SynchronizeModeAuto) :
|
|
((FCurrentSide == osLocal) ? smRemote : smLocal));
|
|
int Params = GUIConfiguration->SynchronizeParams;
|
|
if (DoFullSynchronizeDirectories(Directory1, Directory2, Mode, Params, SaveMode, -1) >= 0)
|
|
{
|
|
if (SaveMode)
|
|
{
|
|
GUIConfiguration->SynchronizeModeAuto = Mode;
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::ExploreLocalDirectory(TOperationSide Side)
|
|
{
|
|
DebugAssert(IsSideLocalBrowser(Side));
|
|
OpenFolderInExplorer(DirView(Side)->Path);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalDirViewExecFile(TObject *Sender,
|
|
TListItem *Item, bool &AllowExec)
|
|
{
|
|
DebugAssert(Item);
|
|
TDirView * ADirView = DebugNotNull(dynamic_cast<TDirView *>(Sender));
|
|
if ((UpperCase(PFileRec(Item->Data)->FileExt) == L"LNK") &&
|
|
DirectoryExists(ApiPath(ResolveFileShortCut(ADirView->ItemFullFileName(Item), true))))
|
|
{
|
|
AllowExec = true;
|
|
}
|
|
else
|
|
{
|
|
DoDirViewExecFile(Sender, Item, AllowExec);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalFileControlDDDragEnter(TObject *Sender,
|
|
IDataObject *DataObj, int grfKeyState, TPoint &Point, int &dwEffect,
|
|
bool &Accept)
|
|
{
|
|
// LocalDirViewDDDragEnter is duplication of
|
|
// TCustomScpExplorerForm::DirViewDDDragEnter, but it differs in
|
|
// literal type of 'DataObj' parameter. The actual type is however the same.
|
|
FileControlDDDragEnter(Sender, DataObj, grfKeyState, Point, dwEffect, Accept);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TScpCommanderForm::PanelOperation(TOperationSide Side,
|
|
bool DragDrop)
|
|
{
|
|
return TCustomScpExplorerForm::PanelOperation(Side, DragDrop) ||
|
|
(DropSourceControl == LocalDirView);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::FileOperationProgress(
|
|
TFileOperationProgressType & ProgressData)
|
|
{
|
|
// Heuristic: When operation finishes and DD target is local dir view,
|
|
// we suppose that drag&drop download finished, so local dir view should be
|
|
// reloaded
|
|
if (!ProgressData.InProgress && FProgressForm &&
|
|
IsFileControl(FDDTargetControl, osLocal) &&
|
|
ProgressData.IsTransfer())
|
|
{
|
|
ReloadLocalDirectory();
|
|
}
|
|
TCustomScpExplorerForm::FileOperationProgress(ProgressData);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
UnicodeString __fastcall TScpCommanderForm::ChangeFilePath(UnicodeString Path, TOperationSide Side)
|
|
{
|
|
TGUICopyParamType CopyParams = GUIConfiguration->CurrentCopyParam;
|
|
UnicodeString Result;
|
|
while (!Path.IsEmpty())
|
|
{
|
|
int P = Path.Pos(Side == osLocal ? L'\\' : L'/');
|
|
if (P > 0)
|
|
{
|
|
Result += Terminal->ChangeFileName(&CopyParams, Path.SubString(1, P - 1), Side, false) +
|
|
(Side == osLocal ? L'/' : L'\\');
|
|
Path.Delete(1, P);
|
|
}
|
|
else
|
|
{
|
|
Result += Terminal->ChangeFileName(&CopyParams, Path, osLocal, false);
|
|
Path = L"";
|
|
}
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::CreateRemoteDirectory(const UnicodeString & Path)
|
|
{
|
|
UnicodeString Dir = UnixExtractFileDir(Path);
|
|
if (!IsUnixRootPath(Dir) && !Terminal->FileExists(Dir))
|
|
{
|
|
CreateRemoteDirectory(Dir);
|
|
}
|
|
TRemoteProperties Properties = GUIConfiguration->NewDirectoryProperties;
|
|
TCustomScpExplorerForm::CreateRemoteDirectory(Path, Properties);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SynchronizeBrowsingLocal(
|
|
UnicodeString PrevPath, UnicodeString & NewPath, bool Create)
|
|
{
|
|
DebugAssert(!IsLocalBrowserMode());
|
|
Terminal->ExceptionOnFail = true;
|
|
TStrings * Paths = new TStringList();
|
|
try
|
|
{
|
|
Paths->Add(IncludeTrailingBackslash(PrevPath));
|
|
Paths->Add(IncludeTrailingBackslash(LocalDirView->Path));
|
|
UnicodeString CommonPath;
|
|
if (ExtractCommonPath(Paths, CommonPath))
|
|
{
|
|
PrevPath = IncludeTrailingBackslash(PrevPath);
|
|
CommonPath = IncludeTrailingBackslash(CommonPath);
|
|
NewPath = RemoteDirView->Path;
|
|
while (!SamePaths(PrevPath, CommonPath))
|
|
{
|
|
if (NewPath == UnixExcludeTrailingBackslash(NewPath))
|
|
{
|
|
Abort();
|
|
}
|
|
NewPath = UnixExtractFilePath(UnixExcludeTrailingBackslash(NewPath));
|
|
PrevPath = ExtractFilePath(ExcludeTrailingBackslash(PrevPath));
|
|
}
|
|
|
|
NewPath = UnixIncludeTrailingBackslash(NewPath) +
|
|
ToUnixPath(LocalDirView->Path.SubString(PrevPath.Length() + 1,
|
|
LocalDirView->Path.Length() - PrevPath.Length()));
|
|
}
|
|
else
|
|
{
|
|
Abort();
|
|
}
|
|
|
|
if (Create)
|
|
{
|
|
CreateRemoteDirectory(UnixExcludeTrailingBackslash(NewPath));
|
|
}
|
|
|
|
RemoteDirView->Path = NewPath;
|
|
}
|
|
__finally
|
|
{
|
|
Terminal->ExceptionOnFail = false;
|
|
delete Paths;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::CreateLocalDirectory(const UnicodeString & Path)
|
|
{
|
|
DebugAssert(!IsLocalBrowserMode()); // Used for synchronized browsing only
|
|
UnicodeString Dir = ExtractFileDir(Path);
|
|
if (!Dir.IsEmpty() && !DirectoryExists(Dir))
|
|
{
|
|
CreateLocalDirectory(Dir);
|
|
}
|
|
LocalDirView->CreateDir(Path);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SynchronizeBrowsingRemote(
|
|
UnicodeString PrevPath, UnicodeString & NewPath, bool Create)
|
|
{
|
|
TStrings * Paths = new TStringList();
|
|
try
|
|
{
|
|
Paths->Add(UnixIncludeTrailingBackslash(PrevPath));
|
|
Paths->Add(UnixIncludeTrailingBackslash(RemoteDirView->Path));
|
|
UnicodeString CommonPath;
|
|
|
|
if (UnixExtractCommonPath(Paths, CommonPath))
|
|
{
|
|
PrevPath = UnixIncludeTrailingBackslash(PrevPath);
|
|
CommonPath = UnixIncludeTrailingBackslash(CommonPath);
|
|
|
|
UnicodeString NewLocalPath;
|
|
NewPath = ExcludeTrailingBackslash(LocalDirView->Path);
|
|
while (!UnixSamePath(PrevPath, CommonPath))
|
|
{
|
|
NewLocalPath = ExcludeTrailingBackslash(ExtractFileDir(NewPath));
|
|
if (NewLocalPath == NewPath)
|
|
{
|
|
Abort();
|
|
}
|
|
NewPath = NewLocalPath;
|
|
PrevPath = UnixExtractFilePath(UnixExcludeTrailingBackslash(PrevPath));
|
|
}
|
|
|
|
NewPath = IncludeTrailingBackslash(NewPath) +
|
|
ChangeFilePath(
|
|
RemoteDirView->Path.SubString(PrevPath.Length() + 1,
|
|
RemoteDirView->Path.Length() - PrevPath.Length()),
|
|
osRemote);
|
|
}
|
|
else
|
|
{
|
|
Abort();
|
|
}
|
|
}
|
|
__finally
|
|
{
|
|
delete Paths;
|
|
}
|
|
|
|
if (Create)
|
|
{
|
|
CreateLocalDirectory(ExcludeTrailingBackslash(NewPath));
|
|
}
|
|
|
|
LocalDirView->Path = NewPath;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SynchronizeBrowsing(TCustomDirView * ADirView,
|
|
UnicodeString PrevPath, UnicodeString & NewPath, bool Create)
|
|
{
|
|
if (ADirView == LocalDirView)
|
|
{
|
|
SynchronizeBrowsingLocal(PrevPath, NewPath, Create);
|
|
}
|
|
else
|
|
{
|
|
SynchronizeBrowsingRemote(PrevPath, NewPath, Create);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SynchronizeBrowsing(TCustomDirView * ADirView)
|
|
{
|
|
UnicodeString PrevPath;
|
|
// cannot assign to UnicodeString before the class is constructed,
|
|
// if we do, the value get lost when UnicodeString constructor gets finally called,
|
|
// what results in memory leak in the best case
|
|
if (FConstructed)
|
|
{
|
|
PrevPath = FPrevPath[ADirView == LocalDirView];
|
|
FPrevPath[ADirView == LocalDirView] = ADirView->Path;
|
|
}
|
|
|
|
if (!FSynchronisingBrowse && NonVisualDataModule->SynchronizeBrowsingAction2->Checked &&
|
|
!PrevPath.IsEmpty() && PrevPath != ADirView->Path)
|
|
{
|
|
DebugAssert(!IsLocalBrowserMode());
|
|
TValueRestorer<bool> AllowTransferPresetAutoSelectRestorer(FAllowTransferPresetAutoSelect, false);
|
|
TValueRestorer<bool> SynchronisingBrowseRestorer(FSynchronisingBrowse, true);
|
|
|
|
try
|
|
{
|
|
UnicodeString NewPath;
|
|
|
|
bool Error = false;
|
|
std::unique_ptr<TStrings> ErrorMoreMessages;
|
|
UnicodeString ErrorHelpKeyword;
|
|
|
|
try
|
|
{
|
|
SynchronizeBrowsing(ADirView, PrevPath, NewPath, false);
|
|
}
|
|
// EAbort means that we do not know how to synchronize browsing
|
|
// there's no fallback scenario for that
|
|
catch(EAbort &)
|
|
{
|
|
throw;
|
|
}
|
|
catch(Exception & E)
|
|
{
|
|
// what does this say?
|
|
if (Application->Terminated)
|
|
{
|
|
throw;
|
|
}
|
|
else
|
|
{
|
|
Error = true;
|
|
ErrorMoreMessages.reset(ExceptionToMoreMessages(&E));
|
|
ErrorHelpKeyword =
|
|
MergeHelpKeyword(HELP_SYNC_DIR_BROWSE_ERROR, GetExceptionHelpKeyword(&E));
|
|
}
|
|
}
|
|
|
|
// this was moved here out of the above catch clause,
|
|
// to avoid deep nesting, what seems to cause some stray access violations
|
|
if (Error)
|
|
{
|
|
if (MoreMessageDialog(FMTLOAD(SYNC_DIR_BROWSE_CREATE2, (NewPath)),
|
|
ErrorMoreMessages.get(), qtConfirmation, qaYes | qaNo,
|
|
ErrorHelpKeyword) == qaYes)
|
|
{
|
|
try
|
|
{
|
|
SynchronizeBrowsing(ADirView, PrevPath, NewPath, true);
|
|
}
|
|
catch(Exception & E)
|
|
{
|
|
if (!Application->Terminated)
|
|
{
|
|
Terminal->ShowExtendedException(&E);
|
|
}
|
|
throw;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NonVisualDataModule->SynchronizeBrowsingAction2->Checked = false;
|
|
}
|
|
}
|
|
|
|
}
|
|
catch(Exception &)
|
|
{
|
|
NonVisualDataModule->SynchronizeBrowsingAction2->Checked = false;
|
|
// what does this say?
|
|
if (Application->Terminated)
|
|
{
|
|
throw;
|
|
}
|
|
else
|
|
{
|
|
MessageDialog(LoadStr(SYNC_DIR_BROWSE_ERROR), qtInformation, qaOK,
|
|
HELP_SYNC_DIR_BROWSE_ERROR);
|
|
}
|
|
}
|
|
|
|
// note the value restorers at the beginning of this block
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DoDirViewLoaded(TCustomDirView * ADirView)
|
|
{
|
|
TCustomScpExplorerForm::DoDirViewLoaded(ADirView);
|
|
|
|
UpdateControls();
|
|
|
|
// In addition to being an optimization, this prevents synchronized browsing against the other local panel,
|
|
// when the users happens to e.g. download a file to the directory loaded in the panel.
|
|
if (ADirView != OtherLocalDirView)
|
|
{
|
|
SynchronizeBrowsing(ADirView);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::AddEditLink(TOperationSide Side, bool Add)
|
|
{
|
|
if (IsSideLocalBrowser(Side))
|
|
{
|
|
bool Edit = false;
|
|
UnicodeString FileName;
|
|
UnicodeString PointTo;
|
|
bool SymbolicLink = true;
|
|
|
|
TDirView * ADirView = DebugNotNull(dynamic_cast<TDirView *>(DirView(Side)));
|
|
if (ADirView->ItemFocused != NULL)
|
|
{
|
|
DebugAssert(ADirView->ItemFocused->Data);
|
|
PFileRec FileRec = static_cast<PFileRec>(ADirView->ItemFocused->Data);
|
|
|
|
Edit = !Add && (UpperCase(FileRec->FileExt) == L"LNK");
|
|
if (Edit)
|
|
{
|
|
UnicodeString FullName = ADirView->ItemFullFileName(ADirView->ItemFocused);
|
|
FileName = FullName;
|
|
PointTo = ResolveFileShortCut(FullName, false);
|
|
if (PointTo.IsEmpty())
|
|
{
|
|
throw Exception(FMTLOAD(RESOLVE_SHORTCUT_ERROR, (FullName)));
|
|
}
|
|
}
|
|
else if (!ADirView->ItemIsParentDirectory(ADirView->ItemFocused))
|
|
{
|
|
PointTo = FileRec->FileName;
|
|
}
|
|
}
|
|
|
|
if (DoSymlinkDialog(FileName, PointTo, osLocal, SymbolicLink, Edit, false))
|
|
{
|
|
Configuration->Usage->Inc(L"LocalShortcutsCreated");
|
|
|
|
DebugAssert(SymbolicLink);
|
|
DebugAssert(!FileName.IsEmpty());
|
|
DebugAssert(!PointTo.IsEmpty());
|
|
|
|
if (ExtractFileDrive(FileName) == L"" && FileName[1] != L'\\')
|
|
{
|
|
FileName = IncludeTrailingBackslash(ADirView->PathName) + FileName;
|
|
}
|
|
if (ExtractFileDrive(PointTo) == L"" && PointTo[1] != L'\\')
|
|
{
|
|
PointTo = IncludeTrailingBackslash(ADirView->PathName) + PointTo;
|
|
}
|
|
if (ExtractFileExt(FileName) == L"")
|
|
{
|
|
FileName = FileName + L".lnk";
|
|
}
|
|
|
|
if (Edit)
|
|
{
|
|
DeleteFileChecked(FileName);
|
|
}
|
|
if (!CreateFileShortCut(PointTo, FileName, L""))
|
|
{
|
|
throw Exception(CREATE_SHORTCUT_ERROR);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TCustomScpExplorerForm::AddEditLink(Side, Add);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DoOpenDirectoryDialog(TOpenDirectoryMode Mode,
|
|
TOperationSide Side)
|
|
{
|
|
bool UseLocationProfiles;
|
|
do
|
|
{
|
|
UseLocationProfiles = WinConfiguration->UseLocationProfiles;
|
|
// Location profiles dialog is not ready to be run without terminal
|
|
if (UseLocationProfiles && IsAvailableTerminal(Terminal))
|
|
{
|
|
TStrings * LocalDirectories = NULL;
|
|
TStrings * RemoteDirectories = NULL;
|
|
try
|
|
{
|
|
LocalDirectories = CreateVisitedDirectories(osLocal);
|
|
RemoteDirectories = CreateVisitedDirectories(osRemote);
|
|
|
|
UnicodeString Local = LocalDirView->PathName;
|
|
UnicodeString Remote = RemoteDirView->PathName;
|
|
|
|
if (LocationProfilesDialog(Mode, Side, Local, Remote, LocalDirectories,
|
|
RemoteDirectories, Terminal))
|
|
{
|
|
DoOpenBookmark(Local, Remote);
|
|
}
|
|
}
|
|
__finally
|
|
{
|
|
delete LocalDirectories;
|
|
delete RemoteDirectories;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TSynchronizedBrowsingGuard SynchronizedBrowsingGuard;
|
|
TCustomScpExplorerForm::DoOpenDirectoryDialog(Mode, Side);
|
|
}
|
|
|
|
// for second and further rounds, always do browse only
|
|
Mode = odBrowse;
|
|
}
|
|
while (UseLocationProfiles != WinConfiguration->UseLocationProfiles);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DoOpenBookmark(UnicodeString Local, UnicodeString Remote)
|
|
{
|
|
TSynchronizedBrowsingGuard SynchronizedBrowsingGuard;
|
|
// make sure that whatever path is valid it is opened first and only
|
|
// after that an eventual error is reported
|
|
try
|
|
{
|
|
if (!Local.IsEmpty())
|
|
{
|
|
DebugAssert(!IsLocalBrowserMode());
|
|
LocalDirView->Path = ExpandEnvironmentVariables(Local);
|
|
}
|
|
}
|
|
__finally
|
|
{
|
|
if (!Remote.IsEmpty())
|
|
{
|
|
// While we might get here when the session is closed (from location profiles),
|
|
// it's not a problem as the Path setter is noop then
|
|
RemoteDirView->Path = Remote;
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TScpCommanderForm::OpenBookmark(TOperationSide Side, TBookmark * Bookmark)
|
|
{
|
|
bool Result;
|
|
if (WinConfiguration->UseLocationProfiles && !IsLocalBrowserMode())
|
|
{
|
|
DoOpenBookmark(Bookmark->Local, Bookmark->Remote);
|
|
Result = true;
|
|
}
|
|
else
|
|
{
|
|
Result = TCustomScpExplorerForm::OpenBookmark(Side, Bookmark);
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalDirViewDDTargetHasDropHandler(
|
|
TObject * Sender, TListItem * Item, int & /*Effect*/, bool & DropHandler)
|
|
{
|
|
// When drop target is not directory, it is probably file type, which have
|
|
// associated drop handler (such as EXE file). In this case we
|
|
// cannot allow drop when when using shellex,
|
|
// as drop handlers are disabled, so drop would error
|
|
// (see TShellExtension.DropHandler assignment in ConfigurationChanged),
|
|
if (WinConfiguration->DDFakeFile &&
|
|
!DebugNotNull(dynamic_cast<TDirView *>(Sender))->ItemIsDirectory(Item))
|
|
{
|
|
DropHandler = false;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TScpCommanderForm::DDGetTarget(
|
|
UnicodeString & Directory, bool & ForceQueue, UnicodeString & CounterName)
|
|
{
|
|
bool Result;
|
|
if (!FDDFakeFileTarget.IsEmpty())
|
|
{
|
|
Directory = FDDFakeFileTarget;
|
|
FDDFakeFileTarget = L"";
|
|
Result = true;
|
|
CounterName = L"DownloadsDragDropInternal";
|
|
ForceQueue = false;
|
|
}
|
|
else
|
|
{
|
|
Result = TCustomScpExplorerForm::DDGetTarget(Directory, ForceQueue, CounterName);
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DDFakeFileInitDrag(TFileList * FileList,
|
|
bool & Created)
|
|
{
|
|
FDDFakeFileTarget = L"";
|
|
TCustomScpExplorerForm::DDFakeFileInitDrag(FileList, Created);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalFileControlDDFileOperation(
|
|
TObject * Sender, int dwEffect, UnicodeString DebugUsedArg(SourcePath),
|
|
UnicodeString DebugUsedArg(TargetPath), bool Paste, bool & DoOperation)
|
|
{
|
|
if (IsFileControl(DropSourceControl, osRemote) && !IsLocalBrowserMode())
|
|
{
|
|
UnicodeString TargetDirectory;
|
|
if (InternalDDDownload(TargetDirectory))
|
|
{
|
|
// See TCustomScpExplorerForm::QueueDDProcessDropped
|
|
if (FDDExtMapFile != NULL)
|
|
{
|
|
FDDFakeFileTarget = TargetDirectory;
|
|
}
|
|
else
|
|
{
|
|
DebugAssert(FInternalDDDownloadList->Count > 0);
|
|
DebugAssert(dwEffect == DROPEFFECT_COPY || dwEffect == DROPEFFECT_MOVE);
|
|
TGUICopyParamType CopyParams = GUIConfiguration->CurrentCopyParam;
|
|
TTransferType TransferType = dwEffect == DROPEFFECT_COPY ? ttCopy : ttMove;
|
|
int Options =
|
|
FLAGMASK(DraggingAllFilesFromDirView(osRemote, FInternalDDDownloadList), coAllFiles);
|
|
bool NoConfirmation = Paste ? false : (WinConfiguration->DDTransferConfirmation == asOff);
|
|
if (CopyParamDialog(tdToLocal, TransferType,
|
|
false, FInternalDDDownloadList, TargetDirectory, CopyParams, NoConfirmation, true, Options))
|
|
{
|
|
int Params =
|
|
(TransferType == ttMove ? cpDelete : 0);
|
|
DDDownload(FInternalDDDownloadList, TargetDirectory,
|
|
&CopyParams, Params);
|
|
Configuration->Usage->Inc(L"DownloadsDragDropInternal");
|
|
FInternalDDDownloadList->Clear();
|
|
}
|
|
}
|
|
DoOperation = false;
|
|
}
|
|
}
|
|
|
|
if (IsLocalBrowserMode() &&
|
|
((IsFileControl(Sender, osRemote) && IsFileControl(DropSourceControl, osLocal)) ||
|
|
(IsFileControl(Sender, osLocal) && IsFileControl(DropSourceControl, osRemote))))
|
|
{
|
|
if (dwEffect == DROPEFFECT_MOVE)
|
|
{
|
|
Configuration->Usage->Inc(L"LocalLocalMovesDragDropInterpanel");
|
|
}
|
|
else
|
|
{
|
|
Configuration->Usage->Inc(L"LocalLocalCopiesDragDropInterpanel");
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::RemoteFileControlDDFileOperationExecuted(
|
|
TObject * /*Sender*/, int dwEffect, UnicodeString /*SourcePath*/,
|
|
UnicodeString /*TargetPath*/)
|
|
{
|
|
if ((dwEffect == DROPEFFECT_MOVE) &&
|
|
IsFileControl(DropSourceControl, osLocal))
|
|
{
|
|
ReloadLocalDirectory();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalDirViewEnter(TObject * /*Sender*/)
|
|
{
|
|
SideEnter(osLocal);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalDriveViewEnter(TObject * /*Sender*/)
|
|
{
|
|
MakeNextInTabOrder(LocalDirView, LocalDriveView);
|
|
SideEnter(osLocal);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SideEnter(TOperationSide Side)
|
|
{
|
|
if (Visible && (IsSideLocalBrowser(FCurrentSide) != IsSideLocalBrowser(Side)))
|
|
{
|
|
// this may get called yet before controls are initialized
|
|
CommandLineCombo->Strings->Clear();
|
|
FCommandLineComboPopulated = false;
|
|
}
|
|
TCustomScpExplorerForm::SideEnter(Side);
|
|
if (Visible)
|
|
{
|
|
UpdateControls();
|
|
UpdatePanelsPathLabelsStatus();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::UpdatePanelsPathLabelsStatus()
|
|
{
|
|
LocalPathLabel->UpdateStatus();
|
|
RemotePathLabel->UpdateStatus();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::OpenConsole(UnicodeString Command)
|
|
{
|
|
SaveCommandLine();
|
|
try
|
|
{
|
|
TCustomScpExplorerForm::OpenConsole(Command);
|
|
}
|
|
__finally
|
|
{
|
|
FCommandLineComboPopulated = false;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SaveCommandLine()
|
|
{
|
|
if (FCommandLineComboPopulated)
|
|
{
|
|
CustomWinConfiguration->History[
|
|
!IsSideLocalBrowser(FCurrentSide) ? L"Commands" : L"LocalCommands"] =
|
|
CommandLineCombo->Strings;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TScpCommanderForm::ExecuteCommandLine()
|
|
{
|
|
UnicodeString Command = CommandLineCombo->Text;
|
|
bool Result =
|
|
!NonVisualDataModule->Busy &&
|
|
!Command.IsEmpty() &&
|
|
(IsSideLocalBrowser(FCurrentSide) ||
|
|
(Terminal->AllowedAnyCommand(Command) &&
|
|
EnsureCommandSessionFallback(fcAnyCommand)));
|
|
if (Result)
|
|
{
|
|
CommandLinePopulate();
|
|
SaveToHistory(CommandLineCombo->Strings, Command);
|
|
CommandLineCombo->Text = L"";
|
|
if (!IsSideLocalBrowser(FCurrentSide))
|
|
{
|
|
OpenConsole(Command);
|
|
}
|
|
else
|
|
{
|
|
ExecuteShellChecked(Command);
|
|
}
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::CommandLinePopulate()
|
|
{
|
|
if (!FCommandLineComboPopulated)
|
|
{
|
|
TStrings * CommandsHistory;
|
|
CommandsHistory = CustomWinConfiguration->History[
|
|
!IsSideLocalBrowser(FCurrentSide) ? L"Commands" : L"LocalCommands"];
|
|
if ((CommandsHistory != NULL) && (CommandsHistory->Count > 0))
|
|
{
|
|
CommandLineCombo->Strings = CommandsHistory;
|
|
}
|
|
else
|
|
{
|
|
CommandLineCombo->Strings->Clear();
|
|
}
|
|
FCommandLineComboPopulated = true;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::GoToCommandLine()
|
|
{
|
|
ComponentVisible[fcCommandLinePanel] = true;
|
|
if (CommandLineCombo->Enabled)
|
|
{
|
|
ClickToolbarItem(CommandLineCombo, true);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::GoToTree()
|
|
{
|
|
if (FCurrentSide == osLocal)
|
|
{
|
|
ComponentVisible[fcLocalTree] = true;
|
|
LocalDriveView->SetFocus();
|
|
}
|
|
else
|
|
{
|
|
TCustomScpExplorerForm::GoToTree();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::PanelExportStore(TOperationSide Side,
|
|
TPanelExport Export, TPanelExportDestination Destination,
|
|
TStrings * ExportData)
|
|
{
|
|
if (Destination == pedCommandLine)
|
|
{
|
|
ComponentVisible[fcCommandLinePanel] = true;
|
|
|
|
UnicodeString Buf;
|
|
for (int Index = 0; Index < ExportData->Count; Index++)
|
|
{
|
|
Buf += ExportData->Strings[Index] + L" ";
|
|
}
|
|
|
|
CommandLineCombo->Text = CommandLineCombo->Text + Buf;
|
|
}
|
|
else
|
|
{
|
|
TCustomScpExplorerForm::PanelExportStore(Side, Export, Destination, ExportData);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
int __fastcall TScpCommanderForm::GetStaticComponentsHeight()
|
|
{
|
|
return TCustomScpExplorerForm::GetStaticComponentsHeight() +
|
|
(BottomDock->Visible ? BottomDock->Height : 0) +
|
|
(QueueSeparatorPanel->Visible ? QueueSeparatorPanel->Height : 0) +
|
|
(StatusBar->Visible ? StatusBar->Height : 0);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::SysResizing(unsigned int Cmd)
|
|
{
|
|
TCustomScpExplorerForm::SysResizing(Cmd);
|
|
|
|
if ((Cmd == SC_MAXIMIZE) ||
|
|
((Cmd == SC_DEFAULT) && (WindowState != wsMaximized)))
|
|
{
|
|
FNormalPanelsWidth = LocalPanel->Width + RemotePanel->Width;
|
|
}
|
|
else if ((Cmd == SC_RESTORE) ||
|
|
((Cmd == SC_DEFAULT) && (WindowState == wsMaximized)))
|
|
{
|
|
if (FNormalPanelsWidth >= 0)
|
|
{
|
|
Panel(true)->Width = static_cast<int>(FLeftPanelWidth * FNormalPanelsWidth);
|
|
FNormalPanelsWidth = -1;
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::Resize()
|
|
{
|
|
TCustomScpExplorerForm::Resize();
|
|
|
|
LeftPanelWidth = FLastLeftPanelWidth;
|
|
UpdateControls();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::PathLabelDblClick(TObject * Sender)
|
|
{
|
|
if (!NonVisualDataModule->Busy)
|
|
{
|
|
OpenDirectory(Sender == LocalPathLabel ? osLocal : osRemote);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalPathLabelGetStatus(
|
|
TCustomPathLabel * /*Sender*/, bool & Active)
|
|
{
|
|
// WORKAROUND this strange form is here to make borland compiler work :-)
|
|
Active = Active || LocalDriveView->Focused();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::RemotePathLabelGetStatus(
|
|
TCustomPathLabel * /*Sender*/, bool & Active)
|
|
{
|
|
// WORKAROUND this strange form is here to make borland compiler work :-)
|
|
Active = Active || DriveView(osOther)->Focused();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DoPathLabelPathClick(TOperationSide Side, const UnicodeString & Path)
|
|
{
|
|
if (!NonVisualDataModule->Busy)
|
|
{
|
|
TCustomDirView * ADirView = DirView(Side);
|
|
|
|
bool Same;
|
|
if (IsSideLocalBrowser(Side))
|
|
{
|
|
Same = SamePaths(Path, ADirView->Path);
|
|
}
|
|
else
|
|
{
|
|
Same = UnixSamePath(Path, ADirView->Path);
|
|
}
|
|
|
|
if (Same)
|
|
{
|
|
OpenDirectory(Side);
|
|
}
|
|
else
|
|
{
|
|
ADirView->Path = Path;
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalPathLabelPathClick(
|
|
TCustomPathLabel * /*Sender*/, UnicodeString Path)
|
|
{
|
|
DoPathLabelPathClick(osLocal, Path);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::RemotePathLabelPathClick(
|
|
TCustomPathLabel * /*Sender*/, UnicodeString Path)
|
|
{
|
|
DoPathLabelPathClick(osOther, Path);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalDirViewFileIconForName(
|
|
TObject * /*Sender*/, UnicodeString & FileName)
|
|
{
|
|
int PartialFileExtLen = GetPartialFileExtLen(FileName);
|
|
if (PartialFileExtLen > 0)
|
|
{
|
|
FileName.SetLength(FileName.Length() - PartialFileExtLen);
|
|
}
|
|
if (WinConfiguration->LocalIconsByExt)
|
|
{
|
|
FileName = ExtractFileName(FileName);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DoUpdateFileStatusBar(
|
|
TObject * Sender, TTBXStatusBar * StatusBar, const TStatusFileInfo & FileInfo, TOperationSide Side)
|
|
{
|
|
TCustomDirView * DirView = dynamic_cast<TCustomDirView *>(Sender);
|
|
// Prevent hidden "right" panel from messing with the status bar
|
|
if (DirView->Visible)
|
|
{
|
|
UpdateFileStatusBar(StatusBar, FileInfo, Side);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalDirViewUpdateStatusBar(TObject * Sender, const TStatusFileInfo & FileInfo)
|
|
{
|
|
DoUpdateFileStatusBar(Sender, LocalStatusBar, FileInfo, osLocal);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::RemoteDirViewUpdateStatusBar(TObject * Sender, const TStatusFileInfo & FileInfo)
|
|
{
|
|
DoUpdateFileStatusBar(Sender, RemoteStatusBar, FileInfo, osRemote);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::OtherLocalDirViewUpdateStatusBar(TObject * Sender, const TStatusFileInfo & FileInfo)
|
|
{
|
|
DoUpdateFileStatusBar(Sender, RemoteStatusBar, FileInfo, osOther);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalStatusBarClick(TObject * /*Sender*/)
|
|
{
|
|
LocalDirView->SetFocus();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
UnicodeString __fastcall TScpCommanderForm::PathForCaption()
|
|
{
|
|
UnicodeString Result;
|
|
if (IsSideLocalBrowser(FCurrentSide))
|
|
{
|
|
// make sure the path corresponds to the terminal in title
|
|
// (there's a mismatch, while opening a new session)
|
|
if (ManagedSession == TTerminalManager::Instance()->ActiveSession)
|
|
{
|
|
switch (WinConfiguration->PathInCaption)
|
|
{
|
|
case picShort:
|
|
Result = ExtractShortName(GetCurrentLocalBrowser()->PathName, false);
|
|
break;
|
|
|
|
case picFull:
|
|
Result = GetCurrentLocalBrowser()->PathName;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Result = TCustomScpExplorerForm::PathForCaption();
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::GetTransferPresetAutoSelectData(
|
|
TCopyParamRuleData & Data)
|
|
{
|
|
TCustomScpExplorerForm::GetTransferPresetAutoSelectData(Data);
|
|
Data.LocalDirectory = LocalDirView->PathName;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::RemoteDirViewPathChange(TCustomDirView * /*Sender*/)
|
|
{
|
|
UpdateRemotePathComboBox(false);
|
|
ResetIncrementalSearch();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::UpdateImages()
|
|
{
|
|
TCustomScpExplorerForm::UpdateImages();
|
|
|
|
TImageList * ImageList = ShellImageListForControl(this, ilsSmall);
|
|
RemotePathComboBox->Images = ImageList;
|
|
RemotePathComboBox->SubMenuImages = ImageList;
|
|
LocalPathComboBox->Images = ImageList;
|
|
LocalPathComboBox->SubMenuImages = ImageList;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TScpCommanderForm::LocalPathComboUpdateDrives(
|
|
TTBXComboBoxItem * ALocalPathComboBox, TCustomDirView * ADirView, TDriveView * ALocalDriveView, TStrings * LocalPathComboBoxPaths)
|
|
{
|
|
int LocalSpecialPaths = 0;
|
|
TStrings * Strings = ALocalPathComboBox->Strings;
|
|
Strings->BeginUpdate();
|
|
try
|
|
{
|
|
Strings->Clear();
|
|
LocalPathComboBoxPaths->Clear();
|
|
Strings->Add(LoadStr(SPECIAL_FOLDER_MY_DOCUMENTS));
|
|
LocalPathComboBoxPaths->AddObject(
|
|
GetPersonalFolder(), reinterpret_cast<TObject *>(DriveInfo->SpecialFolder[CSIDL_PERSONAL]->ImageIndex));
|
|
LocalSpecialPaths++;
|
|
Strings->Add(LoadStr(SPECIAL_FOLDER_DESKTOP));
|
|
LocalPathComboBoxPaths->AddObject(
|
|
GetDesktopFolder(), reinterpret_cast<TObject *>(DriveInfo->SpecialFolder[CSIDL_DESKTOP]->ImageIndex));
|
|
LocalSpecialPaths++;
|
|
DebugAssert((FLocalSpecialPaths == 0) || (FLocalSpecialPaths == LocalSpecialPaths));
|
|
FLocalSpecialPaths = LocalSpecialPaths;
|
|
|
|
std::unique_ptr<TStrings> Drives(ALocalDriveView->GetDrives());
|
|
for (int Index = 0; Index < Drives->Count; Index++)
|
|
{
|
|
UnicodeString Drive = Drives->Strings[Index];
|
|
if (DriveInfo->Get(Drive)->Valid)
|
|
{
|
|
UnicodeString Caption = DriveInfo->GetPrettyName(Drive);
|
|
if (DriveInfo->IsRealDrive(Drive))
|
|
{
|
|
Caption.Insert(L"&", 0);
|
|
}
|
|
Strings->Add(Caption);
|
|
UnicodeString RootPath = DriveInfo->GetDriveRoot(Drive);
|
|
int ImageIndex = DriveInfo->GetImageIndex(Drive);
|
|
LocalPathComboBoxPaths->AddObject(RootPath, reinterpret_cast<TObject *>(ImageIndex));
|
|
}
|
|
}
|
|
}
|
|
__finally
|
|
{
|
|
Strings->EndUpdate();
|
|
}
|
|
|
|
LocalPathComboUpdate(ADirView, ALocalPathComboBox, LocalPathComboBoxPaths);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TScpCommanderForm::OtherLocalPathComboUpdateDrives()
|
|
{
|
|
LocalPathComboUpdateDrives(RemotePathComboBox, OtherLocalDirView, OtherLocalDriveView, FOtherLocalPathComboBoxPaths);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalPathComboUpdateDrives()
|
|
{
|
|
LocalPathComboUpdateDrives(LocalPathComboBox, LocalDirView, LocalDriveView, FLocalPathComboBoxPaths);
|
|
|
|
if (IsLocalBrowserMode())
|
|
{
|
|
OtherLocalPathComboUpdateDrives();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TScpCommanderForm::LocalPathComboUpdate(
|
|
TCustomDirView * ADirView, TTBXComboBoxItem * PathComboBox, TStrings * LocalPathComboBoxPaths)
|
|
{
|
|
// this may get called even after destructor finishes
|
|
// (e.g. from SetDockAllowDrag invoked [indirectly] from StoreParams)
|
|
if (LocalPathComboBoxPaths != NULL)
|
|
{
|
|
DebugAssert(LocalPathComboBoxPaths->Count == PathComboBox->Strings->Count);
|
|
|
|
int Index = 0;
|
|
while ((Index < LocalPathComboBoxPaths->Count) &&
|
|
!SamePaths(LocalPathComboBoxPaths->Strings[Index],
|
|
ADirView->Path.SubString(1, LocalPathComboBoxPaths->Strings[Index].Length())))
|
|
{
|
|
Index++;
|
|
}
|
|
|
|
// what to do if not?
|
|
if (Index < LocalPathComboBoxPaths->Count)
|
|
{
|
|
PathComboBox->ItemIndex = Index;
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TScpCommanderForm::DoLocalDirViewPathChange(
|
|
TCustomDirView * Sender, TTBXComboBoxItem * PathComboBox, TStrings * LocalPathComboBoxPaths)
|
|
{
|
|
LocalPathComboUpdate(Sender, PathComboBox, LocalPathComboBoxPaths);
|
|
ResetIncrementalSearch();
|
|
if (IsUncPath(Sender->Path))
|
|
{
|
|
Configuration->Usage->Inc(L"BrowsedUncPath");
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalDirViewPathChange(TCustomDirView * Sender)
|
|
{
|
|
DoLocalDirViewPathChange(Sender, LocalPathComboBox, FLocalPathComboBoxPaths);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalPathComboBoxCancel(TObject * /*Sender*/)
|
|
{
|
|
LocalPathComboUpdate(LocalDirView, LocalPathComboBox, FLocalPathComboBoxPaths);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TScpCommanderForm::DoLocalPathComboBoxAdjustImageIndex(
|
|
TTBXComboBoxItem * Sender, const UnicodeString DebugUsedArg(AText), int AIndex, int & ImageIndex, TStrings * LocalPathComboBoxPaths)
|
|
{
|
|
// this may get called even before constructor starts
|
|
// (e.g. from FixControlsPlacement)
|
|
if (LocalPathComboBoxPaths != NULL)
|
|
{
|
|
TTBXComboBoxItem * PathComboBox = DebugNotNull(dynamic_cast<TTBXComboBoxItem *>(Sender));
|
|
DebugAssert(FSessionChanging || (LocalPathComboBoxPaths->Count == PathComboBox->Strings->Count));
|
|
DebugAssert(FSessionChanging || (AIndex < LocalPathComboBoxPaths->Count));
|
|
|
|
if (AIndex < 0)
|
|
{
|
|
AIndex = PathComboBox->ItemIndex;
|
|
}
|
|
|
|
// We might get called via some Windows messages while switching from remote to local tab (FSessionChanging),
|
|
// before the UpdateRemotePathComboBox gets called. If that happens, ignore the call.
|
|
if ((AIndex >= 0) && (AIndex < LocalPathComboBoxPaths->Count))
|
|
{
|
|
ImageIndex = int(LocalPathComboBoxPaths->Objects[AIndex]);
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalPathComboBoxAdjustImageIndex(
|
|
TTBXComboBoxItem * Sender, const UnicodeString AText, int AIndex,
|
|
int & ImageIndex)
|
|
{
|
|
DebugAssert(Sender == LocalPathComboBox);
|
|
DoLocalPathComboBoxAdjustImageIndex(Sender, AText, AIndex, ImageIndex, FLocalPathComboBoxPaths);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TScpCommanderForm::DoLocalPathComboBoxItemClick(
|
|
TDirView * ADirView, TTBXComboBoxItem * PathComboBox, TStrings * LocalPathComboBoxPaths)
|
|
{
|
|
DebugAssert(LocalPathComboBoxPaths->Count == PathComboBox->Strings->Count);
|
|
DebugAssert((PathComboBox->ItemIndex >= 0) && (PathComboBox->ItemIndex < LocalPathComboBoxPaths->Count));
|
|
|
|
UnicodeString Path = LocalPathComboBoxPaths->Strings[PathComboBox->ItemIndex];
|
|
try
|
|
{
|
|
if (PathComboBox->ItemIndex >= FLocalSpecialPaths)
|
|
{
|
|
UnicodeString Drive = DriveInfo->GetDriveKey(Path);
|
|
TDirView * CurrentDirView = dynamic_cast<TDirView *>(DirView(osCurrent));
|
|
if (IsLocalBrowserMode() && (ADirView != CurrentDirView) &&
|
|
SamePaths(DriveInfo->GetDriveKey(CurrentDirView->PathName), Drive))
|
|
{
|
|
ADirView->Path = CurrentDirView->PathName;
|
|
}
|
|
else
|
|
{
|
|
ADirView->ExecuteDrive(Drive);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ADirView->Path = Path;
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
// Changing the path failed, reset the combo box back.
|
|
// Does not recurse, so infinite recursion should not happen.
|
|
LocalPathComboUpdate(ADirView, PathComboBox, LocalPathComboBoxPaths);
|
|
throw;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalPathComboBoxItemClick(TObject *)
|
|
{
|
|
DoLocalPathComboBoxItemClick(LocalDirView, LocalPathComboBox, FLocalPathComboBoxPaths);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::ToolbarItemResize(TTBXCustomDropDownItem * Item, int Width)
|
|
{
|
|
TCustomScpExplorerForm::ToolbarItemResize(Item, Width);
|
|
if ((Item == LocalPathComboBox) ||
|
|
(Item == RemotePathComboBox) ||
|
|
(Item == CommandLineCombo))
|
|
{
|
|
dynamic_cast<TTBXComboBoxItem *>(Item)->MinListWidth = Width - 4;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::CommandLineComboPopup(
|
|
TTBCustomItem * /*Sender*/, bool /*FromLink*/)
|
|
{
|
|
CommandLinePopulate();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::CommandLineComboBeginEdit(
|
|
TTBEditItem * /*Sender*/, TTBEditItemViewer * /*Viewer*/, TEdit *EditControl)
|
|
{
|
|
InstallPathWordBreakProc(EditControl);
|
|
FCommandLineComboEdit = EditControl;
|
|
FToolbarEditOldWndProc = EditControl->WindowProc;
|
|
EditControl->WindowProc = CommandLineComboEditWndProc;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::ExitToolbar()
|
|
{
|
|
CurrentPanel()->SetFocus();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::CommandLineComboEditWndProc(TMessage & Message)
|
|
{
|
|
bool Handled = false;
|
|
if (Message.Msg == WM_CHAR)
|
|
{
|
|
switch (reinterpret_cast<TWMChar &>(Message).CharCode)
|
|
{
|
|
case VK_ESCAPE:
|
|
CommandLineCombo->Text = L"";
|
|
ExitToolbar();
|
|
Handled = true;
|
|
break;
|
|
|
|
case VK_TAB:
|
|
CommandLineCombo->Text = FCommandLineComboEdit->Text;
|
|
ExitToolbar();
|
|
Handled = true;
|
|
break;
|
|
|
|
case VK_RETURN:
|
|
CommandLineCombo->Text = FCommandLineComboEdit->Text;
|
|
ExitToolbar();
|
|
if (!ExecuteCommandLine())
|
|
{
|
|
// re-enter command line
|
|
// (most probably exited by now as message dialog was shown)
|
|
GoToCommandLine();
|
|
}
|
|
Handled = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!Handled)
|
|
{
|
|
FToolbarEditOldWndProc(Message);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DriveNotification(TDriveNotification Notification, UnicodeString DebugUsedArg(Drive))
|
|
{
|
|
if (Notification == dnRefresh)
|
|
{
|
|
// This unreliably relies on this handler to be called after the drive view handlers
|
|
LocalPathComboUpdateDrives();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::HomeDirectory(TOperationSide Side)
|
|
{
|
|
bool SynchronizeBrowsing = NonVisualDataModule->SynchronizeBrowsingAction2->Checked;
|
|
|
|
TSynchronizedBrowsingGuard SynchronizedBrowsingGuard;
|
|
|
|
TCustomScpExplorerForm::HomeDirectory(Side);
|
|
|
|
if (SynchronizeBrowsing)
|
|
{
|
|
TCustomScpExplorerForm::HomeDirectory(GetOtherSize(Side));
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::QueueSubmenuItemPopup(
|
|
TTBCustomItem * /*Sender*/, bool /*FromLink*/)
|
|
{
|
|
NonVisualDataModule->QueueSpeedComboBoxItemUpdate(QueueSpeedComboBoxItem);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DoFocusRemotePath(TTerminal * Terminal, const UnicodeString & Path)
|
|
{
|
|
TSynchronizedBrowsingGuard SynchronizedBrowsingGuard;
|
|
TCustomScpExplorerForm::DoFocusRemotePath(Terminal, Path);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TOperationSide __fastcall TScpCommanderForm::GetOtherSize(TOperationSide Side)
|
|
{
|
|
Side = GetSide(Side);
|
|
return ReverseOperationSide(Side);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::HistoryGo(TOperationSide Side, int Index)
|
|
{
|
|
TOperationSide OtherSide = GetOtherSize(Side);
|
|
if (NonVisualDataModule->SynchronizeBrowsingAction2->Checked &&
|
|
((Index < 0) ? (-Index < DirView(OtherSide)->BackCount) : (Index < DirView(OtherSide)->ForwardCount)))
|
|
{
|
|
TSynchronizedBrowsingGuard SynchronizedBrowsingGuard;
|
|
TCustomScpExplorerForm::HistoryGo(Side, Index);
|
|
TCustomScpExplorerForm::HistoryGo(OtherSide, Index);
|
|
}
|
|
else
|
|
{
|
|
TCustomScpExplorerForm::HistoryGo(Side, Index);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DirViewHistoryGo(
|
|
TCustomDirView * Sender, int Index, bool & Cancel)
|
|
{
|
|
TOperationSide Side = (Sender == DirView(osRemote) ? osRemote : osLocal);
|
|
HistoryGo(Side, Index);
|
|
Cancel = true;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TScpCommanderForm::EligibleForImageDisplayMode(TTBCustomItem * Item)
|
|
{
|
|
return
|
|
TCustomScpExplorerForm::EligibleForImageDisplayMode(Item) &&
|
|
((Item->Parent == NULL) || (Item->Parent->ParentComponent != Toolbar2Toolbar));
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TScpCommanderForm::UpdateToolbarDisplayMode()
|
|
{
|
|
bool Result = TCustomScpExplorerForm::UpdateToolbarDisplayMode();
|
|
if (Result)
|
|
{
|
|
// command line combo width needs to be updated as caption visibility has changed
|
|
ToolBarResize(CommandLineToolbar);
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::QueueLabelUpdateStatus()
|
|
{
|
|
TCustomScpExplorerForm::QueueLabelUpdateStatus();
|
|
// this is here to deactivate panels path labels when moving focus from
|
|
// directory tree to queue
|
|
UpdatePanelsPathLabelsStatus();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DoLocalDirViewContextPopup(TOperationSide Side, TPoint & MousePos, bool & Handled)
|
|
{
|
|
if (!WinConfiguration->ScpCommander.SystemContextMenu && !FForceSystemContextMenu)
|
|
{
|
|
DirViewContextPopupDefaultItem(Side, NonVisualDataModule->LocalOpenMenuItem, rdcaOpen, rdcaChangeDir);
|
|
DirViewContextPopupDefaultItem(Side, NonVisualDataModule->LocalEditMenuItem, rdcaEdit, rdcaNone);
|
|
if (IsLocalBrowserMode())
|
|
{
|
|
DirViewContextPopupDefaultItem(Side, NonVisualDataModule->LocalLocalCopyMenuItem, rdcaCopy, rdcaNone);
|
|
}
|
|
else
|
|
{
|
|
DirViewContextPopupDefaultItem(Side, NonVisualDataModule->LocalCopyMenuItem, rdcaCopy, rdcaNone);
|
|
}
|
|
|
|
DirViewContextPopup(Side, fcLocalPopup, MousePos);
|
|
Handled = true;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalDirViewContextPopup(TObject *, TPoint & MousePos, bool & Handled)
|
|
{
|
|
DoLocalDirViewContextPopup(osLocal, MousePos, Handled);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::OtherLocalDirViewContextPopup(TObject *, TPoint & MousePos, bool & Handled)
|
|
{
|
|
DoLocalDirViewContextPopup(osOther, MousePos, Handled);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DisplaySystemContextMenu()
|
|
{
|
|
TAutoFlag Flag(FForceSystemContextMenu);
|
|
if ((FLastContextPopupScreenPoint.x >= 0) && (FLastContextPopupScreenPoint.Y >= 0))
|
|
{
|
|
DirView(osCurrent)->DisplayContextMenu(FLastContextPopupScreenPoint);
|
|
}
|
|
else
|
|
{
|
|
DirView(osCurrent)->DisplayContextMenuInSitu();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalStatusBarPanelClick(TTBXCustomStatusBar * /*Sender*/,
|
|
TTBXStatusPanel * Panel)
|
|
{
|
|
FileStatusBarPanelClick(Panel, osLocal);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::RemoteStatusBarPanelClick(TTBXCustomStatusBar * /*Sender*/,
|
|
TTBXStatusPanel *Panel)
|
|
{
|
|
FileStatusBarPanelClick(Panel, osRemote);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::GoToAddress()
|
|
{
|
|
OpenDirectory(GetSide(osCurrent));
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::RemotePathLabelMaskClick(TObject * /*Sender*/)
|
|
{
|
|
Filter(osRemote);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalPathLabelMaskClick(TObject * /*Sender*/)
|
|
{
|
|
Filter(osLocal);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalOpenDirButtonPopup(TTBCustomItem * /*Sender*/, bool /*FromLink*/)
|
|
{
|
|
CreateOpenDirMenu(LocalOpenDirButton, osLocal);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::RemoteOpenDirButtonPopup(TTBCustomItem * /*Sender*/, bool /*FromLink*/)
|
|
{
|
|
CreateOpenDirMenu(RemoteOpenDirButton, osRemote);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::CopyFilesToClipboard(TOperationSide Side, bool OnFocused)
|
|
{
|
|
if (IsSideLocalBrowser(Side))
|
|
{
|
|
TInstantOperationVisualizer Visualizer;
|
|
dynamic_cast<TDirView *>(DirView(Side))->CopyToClipBoard(OnFocused);
|
|
}
|
|
else
|
|
{
|
|
TCustomScpExplorerForm::CopyFilesToClipboard(Side, OnFocused);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::PasteFromClipBoard()
|
|
{
|
|
if (DoesClipboardContainOurFiles() && (IsSideLocalBrowser(osCurrent)))
|
|
{
|
|
if (DebugAlwaysTrue(CanPasteToDirViewFromClipBoard()))
|
|
{
|
|
ClipboardDownload(DirView(osCurrent)->Path, !WinConfiguration->ConfirmTransferring, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TCustomScpExplorerForm::PasteFromClipBoard();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::FileColorsChanged()
|
|
{
|
|
TCustomScpExplorerForm::FileColorsChanged();
|
|
DoFileColorsChanged(LocalDirView);
|
|
DoFileColorsChanged(OtherLocalDirView);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::ExploreFile(const UnicodeString & FileName)
|
|
{
|
|
DebugAssert(!IsLocalBrowserMode());
|
|
TCustomScpExplorerForm::ExploreFile(FileName);
|
|
DoExploreFile(LocalDirView, FileName);
|
|
TScpCommanderConfiguration ScpCommander = WinConfiguration->ScpCommander;
|
|
// Select the panel that has the file, with preference on the remote panel
|
|
if ((RemoteDirView->ItemFocused != NULL) && RemoteDirView->ItemFocused->Selected)
|
|
{
|
|
ScpCommander.CurrentPanel = osRemote;
|
|
}
|
|
else if ((LocalDirView->ItemFocused != NULL) && LocalDirView->ItemFocused->Selected)
|
|
{
|
|
ScpCommander.CurrentPanel = osLocal;
|
|
}
|
|
WinConfiguration->ScpCommander = ScpCommander;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::OtherLocalDirViewEnter(TObject *)
|
|
{
|
|
// Actually identical to LocalDirViewEnter
|
|
SideEnter(osOther);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::OtherLocalDriveViewEnter(TObject *)
|
|
{
|
|
MakeNextInTabOrder(OtherLocalDirView, OtherLocalDriveView);
|
|
SideEnter(osOther);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DoRemotePathComboBoxAdjustImageIndex(
|
|
TTBXComboBoxItem * Sender, const UnicodeString AText, int AIndex, int & ImageIndex)
|
|
{
|
|
if (!IsLocalBrowserMode())
|
|
{
|
|
TCustomScpExplorerForm::DoRemotePathComboBoxAdjustImageIndex(Sender, AText, AIndex, ImageIndex);
|
|
}
|
|
else
|
|
{
|
|
DebugAssert(Sender == RemotePathComboBox);
|
|
DoLocalPathComboBoxAdjustImageIndex(Sender, AText, AIndex, ImageIndex, FOtherLocalPathComboBoxPaths);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DoRemotePathComboBoxCancel(TObject * Sender)
|
|
{
|
|
if (!IsLocalBrowserMode())
|
|
{
|
|
TCustomScpExplorerForm::DoRemotePathComboBoxCancel(Sender);
|
|
}
|
|
else
|
|
{
|
|
LocalPathComboUpdate(OtherLocalDirView, RemotePathComboBox, FOtherLocalPathComboBoxPaths);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::OtherLocalDirViewPathChange(TCustomDirView * Sender)
|
|
{
|
|
// should happen only when called from TScpCommanderForm::DoShow while starting connected
|
|
if (IsLocalBrowserMode())
|
|
{
|
|
DebugUsedParam(Sender);
|
|
DebugAssert(Sender == OtherLocalDirView);
|
|
UpdateRemotePathComboBox(!FSessionChanging);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::DoRemotePathComboBoxItemClick(TObject * Sender)
|
|
{
|
|
if (!IsLocalBrowserMode())
|
|
{
|
|
TCustomScpExplorerForm::DoRemotePathComboBoxItemClick(Sender);
|
|
}
|
|
else
|
|
{
|
|
DoLocalPathComboBoxItemClick(OtherLocalDirView, RemotePathComboBox, FOtherLocalPathComboBoxPaths);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::UpdateRemotePathComboBox(bool TextOnly)
|
|
{
|
|
if (!IsLocalBrowserMode())
|
|
{
|
|
TCustomScpExplorerForm::UpdateRemotePathComboBox(TextOnly);
|
|
}
|
|
else
|
|
{
|
|
LocalPathComboUpdate(OtherLocalDirView, RemotePathComboBox, FOtherLocalPathComboBoxPaths);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TScpCommanderForm::LocalDriveViewNeedHiddenDirectories(TObject *)
|
|
{
|
|
if (DebugAlwaysTrue(!WinConfiguration->ShowHiddenFiles))
|
|
{
|
|
ToggleShowHiddenFiles();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TScpCommanderForm::LocalLocalCopy(
|
|
::TFileOperation Operation, TOperationSide Side, bool OnFocused, bool NoConfirmation, bool DragDrop, unsigned int Flags)
|
|
{
|
|
std::unique_ptr<TFileOperator> FileOperator(new TFileOperator(NULL));
|
|
bool Move;
|
|
switch (Operation)
|
|
{
|
|
case ::foCopy:
|
|
FileOperator->Operation = Fileoperator::foCopy;
|
|
Move = false;
|
|
break;
|
|
case ::foMove:
|
|
FileOperator->Operation = Fileoperator::foMove;
|
|
Move = true;
|
|
break;
|
|
default:
|
|
DebugFail();
|
|
Abort();
|
|
Move = false; // shut up
|
|
}
|
|
|
|
TOperationSide OtherSide = GetOtherSide(GetSide(Side));
|
|
|
|
TCustomDirView * SourceDirView = DirView(Side);
|
|
UnicodeString DestinationDir = DirView(OtherSide)->PathName;
|
|
SourceDirView->CreateFileList(OnFocused, true, FileOperator->OperandFrom);
|
|
|
|
int OutputOptions =
|
|
FLAGMASK(GetDoNotShowCopyDialogDefault(DragDrop), clooDoNotShowAgain);
|
|
bool MultipleFiles = (FileOperator->OperandFrom->Count > 1);
|
|
int Options =
|
|
FLAGMASK(FLAGSET(Flags, cocShortCutHint), cloShortCutHint) |
|
|
FLAGMASK(MultipleFiles, cloMultipleFiles);
|
|
UnicodeString FileMask = AnyMask;
|
|
|
|
bool Confirmed =
|
|
NoConfirmation ||
|
|
DoCopyLocalDialog(Move, Options, DestinationDir, FileMask, OutputOptions);
|
|
|
|
if (Confirmed)
|
|
{
|
|
HandleDoNotShowCopyDialogAgain(DragDrop, FLAGSET(OutputOptions, clooDoNotShowAgain));
|
|
|
|
FileOperator->Flags = FileOperator->Flags << foMultiDestFiles;
|
|
if (!WinConfiguration->ConfirmOverwriting)
|
|
{
|
|
FileOperator->Flags = FileOperator->Flags << foNoConfirmation;
|
|
}
|
|
|
|
if (Move)
|
|
{
|
|
Configuration->Usage->Inc(L"LocalLocalMovesCommand");
|
|
}
|
|
else
|
|
{
|
|
Configuration->Usage->Inc(L"LocalLocalCopiesCommand");
|
|
}
|
|
|
|
for (int Index = 0; Index < FileOperator->OperandFrom->Count; Index++)
|
|
{
|
|
UnicodeString SourcePath = FileOperator->OperandFrom->Strings[Index];
|
|
UnicodeString FileName = TPath::GetFileName(SourcePath);
|
|
FileName = MaskFileName(FileName, FileMask);
|
|
UnicodeString DestinationPath = CombinePaths(DestinationDir, FileName);
|
|
FileOperator->OperandTo->Add(DestinationPath);
|
|
}
|
|
|
|
SourceDirView->ClearSelection();
|
|
|
|
{
|
|
TAutoBatch AutoBatch(this);
|
|
FileOperator->Execute();
|
|
}
|
|
|
|
ReloadLocalDirectory(DestinationDir);
|
|
if (Operation == ::foMove)
|
|
{
|
|
UnicodeString SourceDir = SourceDirView->PathName;
|
|
if (!SamePaths(SourceDir, DestinationDir))
|
|
{
|
|
ReloadLocalDirectory(SourceDir);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
UnicodeString TScpCommanderForm::GetLocalBrowserSessionTitle(TManagedTerminal * ASession)
|
|
{
|
|
UnicodeString Result;
|
|
if (ASession->SessionData->HasSessionName())
|
|
{
|
|
Result = ASession->SessionData->SessionName;
|
|
}
|
|
else
|
|
{
|
|
DebugAssert(ASession->LocalBrowser);
|
|
UnicodeString Path1;
|
|
UnicodeString Path2;
|
|
TTerminalManager * Manager = TTerminalManager::Instance();
|
|
// might use GetSessionPath here
|
|
if ((ASession == ManagedSession) &&
|
|
// prevent tab title flicker, when switching to local-local tab, as the path changes in individual local panels
|
|
!FSessionChanging)
|
|
{
|
|
Path1 = LocalDirView->PathName;
|
|
Path2 = OtherLocalDirView->PathName;
|
|
}
|
|
else
|
|
{
|
|
Path1 = ASession->StateData->LocalDirectory;
|
|
Path2 = ASession->StateData->OtherLocalDirectory;
|
|
}
|
|
// See also TSessionData::GetDefaultSessionName()
|
|
Path1 = Manager->GetPathForSessionTabName(ExtractShortName(Path1, false));
|
|
Path2 = Manager->GetPathForSessionTabName(ExtractShortName(Path2, false));
|
|
Result = Path1 + TitleSeparator + Path2;
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
int TScpCommanderForm::GetNewTabActionImageIndex()
|
|
{
|
|
return WinConfiguration->DefaultToNewRemoteTab ?
|
|
TCustomScpExplorerForm::GetNewTabActionImageIndex() : NonVisualDataModule->NewLocalTabAction->ImageIndex;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
int TScpCommanderForm::GetNewTabTabImageIndex(TOperationSide Side)
|
|
{
|
|
if (Side == osCurrent)
|
|
{
|
|
Side = WinConfiguration->DefaultToNewRemoteTab ? osRemote : osLocal;
|
|
}
|
|
return TCustomScpExplorerForm::GetNewTabTabImageIndex(Side);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
UnicodeString TScpCommanderForm::GetTabHintDetails(TManagedTerminal * ASession)
|
|
{
|
|
UnicodeString Result;
|
|
if (!ASession->LocalBrowser)
|
|
{
|
|
Result = GetTabHintSessionDetails(ASession);
|
|
}
|
|
if (!ASession->LocalBrowser && !ASession->Active)
|
|
{
|
|
Result += LoadStr(STATUS_NOT_CONNECTED2);
|
|
}
|
|
else
|
|
{
|
|
UnicodeString Local = GetSessionPath(ASession, osLocal);
|
|
UnicodeString Other = GetSessionPath(ASession, osOther);
|
|
// Contrary to Panel(), the IsRightToLeft() is not considered here,
|
|
// as I assume they expect the right panel first, as they read from the right.
|
|
UnicodeString Sep = L"\n";
|
|
if (!WinConfiguration->ScpCommander.SwappedPanels)
|
|
{
|
|
Result += Local + Sep + Other;
|
|
}
|
|
else
|
|
{
|
|
Result += Other + Sep + Local;
|
|
}
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
UnicodeString TScpCommanderForm::GetNewTabHintDetails()
|
|
{
|
|
UnicodeString Result;
|
|
if (WinConfiguration->DefaultToNewRemoteTab)
|
|
{
|
|
Result = TCustomScpExplorerForm::GetNewTabHintDetails();
|
|
Result = FMTLOAD(NEW_REMOTE_TAB_CTRL_HINT, (Result));
|
|
}
|
|
else
|
|
{
|
|
Result = LoadStr(NEW_LOCAL_TAB_HINT);
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool TScpCommanderForm::SupportedSession(TSessionData *)
|
|
{
|
|
return true;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TScpCommanderForm::ResetLayoutColumns(TOperationSide Side)
|
|
{
|
|
UnicodeString DirViewParamsDefault =
|
|
IsSideLocalBrowser(Side) ? ScpCommanderLocalPanelDirViewParamsDefault : ScpCommanderRemotePanelDirViewParamsDefault;
|
|
|
|
DirView(Side)->ColProperties->ParamsStr = DirViewParamsDefault;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void * TScpCommanderForm::SaveFocus()
|
|
{
|
|
// When window is disabled, the ActiveControl might actually not be focusable
|
|
return ((ActiveControl != NULL) && ActiveControl->Focused()) ? ActiveControl : NULL;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TScpCommanderForm::RestoreFocus(void * Focus)
|
|
{
|
|
TWinControl * ControlFocus = static_cast<TWinControl *>(Focus);
|
|
if ((ControlFocus == LocalDirView) || (ControlFocus == LocalDriveView))
|
|
{
|
|
DebugAssert(ActiveControl == ControlFocus);
|
|
DebugAssert(ControlFocus->CanFocus());
|
|
// noop
|
|
}
|
|
else if ((ControlFocus == RemoteDirView) || (ControlFocus == OtherLocalDirView))
|
|
{
|
|
TCustomDirView * OtherDirView = DirView(osOther);
|
|
if (OtherDirView->CanFocus())
|
|
{
|
|
ControlFocus = OtherDirView;
|
|
}
|
|
else
|
|
{
|
|
DebugAssert(LocalDirView->CanFocus());
|
|
ControlFocus = LocalDirView;
|
|
}
|
|
}
|
|
else if ((ControlFocus == RemoteDriveView) || (ControlFocus == OtherLocalDriveView))
|
|
{
|
|
TCustomDriveView * OtherDriveView = DriveView(osOther);
|
|
if (OtherDriveView->CanFocus())
|
|
{
|
|
ControlFocus = OtherDriveView;
|
|
}
|
|
else if (LocalDriveView->CanFocus())
|
|
{
|
|
ControlFocus = LocalDriveView;
|
|
}
|
|
else
|
|
{
|
|
// Switching to a disconnected session with local drive view hidden -
|
|
// fallback to the local dir view (should always be visible)
|
|
DebugAssert(LocalDirView->CanFocus());
|
|
ControlFocus = LocalDirView;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ControlFocus = NULL;
|
|
}
|
|
|
|
// The CanFocus check is hack and should be removed eventually
|
|
if ((ControlFocus != NULL) && DebugAlwaysTrue(ControlFocus->CanFocus()))
|
|
{
|
|
ActiveControl = ControlFocus;
|
|
}
|
|
}
|