1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00
Files
winscp/source/forms/OpenDirectory.cpp

610 lines
21 KiB
C++

//---------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <CoreMain.h>
#include <Configuration.h>
#include <RemoteFiles.h>
#include <VCLCommon.h>
#include <TextsWin.h>
#include <Common.h>
#include <Math.hpp>
#include <GUITools.h>
#include "OpenDirectory.h"
#include "WinConfiguration.h"
//---------------------------------------------------------------------
#pragma link "HistoryComboBox"
#ifndef NO_RESOURCES
#pragma resource "*.dfm"
#endif
//---------------------------------------------------------------------
bool __fastcall DoOpenDirectoryDialog(TOpenDirectoryMode Mode, TOperationSide Side,
UnicodeString & Directory, TStrings * Directories, TTerminal * Terminal,
bool AllowSwitch)
{
bool Result;
TOpenDirectoryDialog * Dialog = new TOpenDirectoryDialog(Application);
try
{
Dialog->Mode = Mode;
Dialog->OperationSide = Side;
Dialog->Directory = Directory;
Dialog->Directories = Directories;
Dialog->Terminal = Terminal;
Dialog->AllowSwitch = AllowSwitch;
Result = Dialog->Execute();
if (Result)
{
Directory = Dialog->Directory;
}
}
__finally
{
delete Dialog;
}
return Result;
}
//---------------------------------------------------------------------
__fastcall TOpenDirectoryDialog::TOpenDirectoryDialog(TComponent * AOwner):
TForm(AOwner)
{
UseSystemSettings(this);
FOperationSide = osCurrent;
OperationSide = osLocal;
FBookmarkDragDest = -1;
FTerminal = NULL;
FSessionBookmarkList = new TBookmarkList();
FSharedBookmarkList = new TBookmarkList();
FSessionScrollOnDragOver = new TListBoxScrollOnDragOver(SessionBookmarksList, true);
FSharedScrollOnDragOver = new TListBoxScrollOnDragOver(SharedBookmarksList, true);
FixComboBoxResizeBug(LocalDirectoryEdit);
FixComboBoxResizeBug(RemoteDirectoryEdit);
LoadDialogImage(Image, L"Open folder");
}
//---------------------------------------------------------------------
__fastcall TOpenDirectoryDialog::~TOpenDirectoryDialog()
{
SAFE_DESTROY(FSessionScrollOnDragOver);
SAFE_DESTROY(FSharedScrollOnDragOver);
SAFE_DESTROY(FSessionBookmarkList);
SAFE_DESTROY(FSharedBookmarkList);
}
//---------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::SetOperationSide(TOperationSide value)
{
if (OperationSide != value)
{
UnicodeString ADirectory = Directory;
FOperationSide = value;
Directory = ADirectory;
RemoteDirectoryEdit->Visible = False;
LocalDirectoryEdit->Visible = False;
CurrentEdit->Visible = True;
EditLabel->FocusControl = CurrentEdit;
UpdateControls();
}
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::SetDirectory(UnicodeString value)
{
if (OperationSide == osRemote)
{
RemoteDirectoryEdit->Text = value;
}
else
{
LocalDirectoryEdit->Text = value;
}
DirectoryEditChange(NULL);
}
//---------------------------------------------------------------------------
UnicodeString __fastcall TOpenDirectoryDialog::GetDirectory()
{
if (OperationSide == osRemote)
return UnixExcludeTrailingBackslash(RemoteDirectoryEdit->Text);
else
return ExcludeTrailingBackslash(LocalDirectoryEdit->Text);
}
//---------------------------------------------------------------------------
TWinControl * __fastcall TOpenDirectoryDialog::GetCurrentEdit()
{
if (OperationSide == osRemote) return RemoteDirectoryEdit;
else return LocalDirectoryEdit;
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::ControlChange(TObject * /*Sender*/)
{
UpdateControls();
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::UpdateBookmarkControls(
TButton * AddBookmarkButton, TButton * RemoveBookmarkButton,
TButton * ShortCutBookmarkButton,
TButton * UpBookmarkButton, TButton * DownBookmarkButton,
TListBox * BookmarksList, bool ListBoxUpdate)
{
EnableControl(AddBookmarkButton,
!Directory.IsEmpty() && (FindBookmark(BookmarksList, Directory) < 0));
EnableControl(RemoveBookmarkButton, BookmarksList->ItemIndex >= 0);
if (ShortCutBookmarkButton != NULL)
{
EnableControl(ShortCutBookmarkButton, BookmarksList->ItemIndex >= 0);
}
EnableControl(UpBookmarkButton, BookmarksList->ItemIndex > 0);
EnableControl(DownBookmarkButton, BookmarksList->ItemIndex >= 0 &&
BookmarksList->ItemIndex < BookmarksList->Items->Count-1);
if (ListBoxUpdate)
{
int MaxWidth = 0;
for (int i = 0; i < BookmarksList->Items->Count; i++)
{
int Width = BookmarksList->Canvas->TextExtent(BookmarksList->Items->Strings[i]).cx;
if (Width > MaxWidth)
{
MaxWidth = Width;
}
}
BookmarksList->ScrollWidth = MaxWidth;
MaxWidth += ScaleByTextHeight(this, 6);
if (BookmarksList->Items->Count > BookmarksList->ClientHeight / BookmarksList->ItemHeight)
{
MaxWidth += GetSystemMetricsForControl(this, SM_CXVSCROLL);
}
if (MaxWidth > BookmarksList->Width)
{
int CWidth = ClientWidth + (MaxWidth - BookmarksList->Width);
ClientWidth = Min(CWidth, ScaleByTextHeight(this, 700));
}
}
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::UpdateControls(bool ListBoxUpdate)
{
EnableControl(OKBtn, !Directory.IsEmpty());
LocalDirectoryBrowseButton->Visible = (OperationSide == osLocal);
SwitchButton->Visible = AllowSwitch;
SessionBookmarksSheet->TabVisible = (Terminal != NULL);
UpdateBookmarkControls(AddSessionBookmarkButton, RemoveSessionBookmarkButton,
NULL, UpSessionBookmarkButton, DownSessionBookmarkButton,
SessionBookmarksList, ListBoxUpdate);
UpdateBookmarkControls(AddSharedBookmarkButton, RemoveSharedBookmarkButton,
ShortCutSharedBookmarkButton, UpSharedBookmarkButton, DownSharedBookmarkButton,
SharedBookmarksList, ListBoxUpdate);
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::SetDirectories(TStrings * value)
{
dynamic_cast<TCustomComboBox*>(CurrentEdit)->Items = value;
}
//---------------------------------------------------------------------------
TStrings * __fastcall TOpenDirectoryDialog::GetDirectories()
{
return RemoteDirectoryEdit->Items;
}
//---------------------------------------------------------------------------
UnicodeString __fastcall TOpenDirectoryDialog::BookmarkDirectory(TBookmark * Bookmark)
{
return Bookmark->GetSideDirectory(OperationSide);
}
//---------------------------------------------------------------------------
UnicodeString __fastcall TOpenDirectoryDialog::BookmarkText(TBookmark * Bookmark)
{
UnicodeString Result = BookmarkDirectory(Bookmark);
if (!Result.IsEmpty() && (Bookmark->ShortCut != 0))
{
Result = FORMAT(L"%s (%s)", (Result, ShortCutToText(Bookmark->ShortCut)));
}
return Result;
}
//---------------------------------------------------------------------------
TBookmark * __fastcall TOpenDirectoryDialog::GetBookmark(TListBox * BookmarksList, int Index)
{
return dynamic_cast<TBookmark *>(BookmarksList->Items->Objects[Index]);
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::LoadBookmarks(TListBox * ListBox,
TBookmarkList * BookmarkList, TBookmarkList * Source)
{
if (Source != NULL)
{
BookmarkList->Assign(Source);
}
else
{
BookmarkList->Clear();
}
Configuration->Usage->SetMax(L"MaxBookmarks", BookmarkList->Count);
ListBox->Items->Clear();
for (int i = 0; i < BookmarkList->Count; i++)
{
TBookmark * Bookmark = BookmarkList->Bookmarks[i];
UnicodeString Directory = BookmarkDirectory(Bookmark);
if (!Directory.IsEmpty() && (FindBookmark(ListBox, Directory) < 0))
{
UnicodeString Text = BookmarkText(Bookmark);
ListBox->Items->AddObject(Text, Bookmark);
}
}
}
//---------------------------------------------------------------------------
bool __fastcall TOpenDirectoryDialog::Execute()
{
bool Result;
UnicodeString SessionKey;
if (Terminal)
{
// cache session key, in case terminal is closed while the window is open
SessionKey = Terminal->SessionData->SessionKey;
LoadBookmarks(SessionBookmarksList, FSessionBookmarkList, WinConfiguration->Bookmarks[SessionKey]);
}
LoadBookmarks(SharedBookmarksList, FSharedBookmarkList, WinConfiguration->SharedBookmarks);
PageControl->ActivePage =
(Terminal == NULL) || WinConfiguration->UseSharedBookmarks ? SharedBookmarksSheet : SessionBookmarksSheet;
DirectoryEditChange(NULL);
if (Mode == odAddBookmark)
{
AddAsBookmark(PageControl->ActivePage);
}
FBookmarkSelected = false;
Result = (ShowModal() == DefaultResult(this));
if (Terminal)
{
WinConfiguration->SharedBookmarks = FSharedBookmarkList;
if (Terminal != NULL)
{
WinConfiguration->Bookmarks[SessionKey] = FSessionBookmarkList;
// Do not remember that shared page was selected,
// if it was selected implicitly because there's no site page.
WinConfiguration->UseSharedBookmarks = (PageControl->ActivePage == SharedBookmarksSheet);
}
}
if (Result)
{
if (FBookmarkSelected)
{
Configuration->Usage->Inc(L"OpenedBookmark");
}
else
{
Configuration->Usage->Inc(L"OpenedPath");
}
}
return Result;
}
//---------------------------------------------------------------------------
template<class T>
typename T * GetBookmarkObject(TObject * Sender, T * SessionObject, T * SharedObject)
{
TControl * Control = dynamic_cast<TControl *>(Sender);
DebugAssert(Control != NULL);
switch (abs(Control->Tag))
{
case 1: return SessionObject;
case 2: return SharedObject;
default: DebugFail(); return NULL;
}
}
//---------------------------------------------------------------------------
TBookmarkList * TOpenDirectoryDialog::GetBookmarkList(TObject * Sender)
{
return GetBookmarkObject(Sender, FSessionBookmarkList, FSharedBookmarkList);
}
//---------------------------------------------------------------------------
TListBox * TOpenDirectoryDialog::GetBookmarksList(TObject * Sender)
{
return GetBookmarkObject(Sender, SessionBookmarksList, SharedBookmarksList);
}
//---------------------------------------------------------------------------
TListBoxScrollOnDragOver * TOpenDirectoryDialog::GetScrollOnDragOver(TObject * Sender)
{
return GetBookmarkObject(Sender, FSessionScrollOnDragOver, FSharedScrollOnDragOver);
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::AddAsBookmark(TObject * Sender)
{
TBookmarkList * BookmarkList = GetBookmarkList(Sender);
TListBox * BookmarksList = GetBookmarksList(Sender);
if (Directory.IsEmpty() || (FindBookmark(BookmarksList, Directory) >= 0))
{
return;
}
TBookmark * Bookmark = new TBookmark;
if (OperationSide == osRemote)
{
RemoteDirectoryEdit->SelectAll();
Bookmark->Remote = Directory;
}
else
{
LocalDirectoryEdit->SelectAll();
Bookmark->Local = Directory;
}
Bookmark->Name = Directory;
// would alway be equal to Directory atm,
// as only difference can be a shorcut, which is not set
UnicodeString Text = BookmarkText(Bookmark);
if (BookmarksList->ItemIndex >= 0)
{
int PrevItemIndex = BookmarksList->ItemIndex;
BookmarkList->InsertBefore(
GetBookmark(BookmarksList, BookmarksList->ItemIndex), Bookmark);
BookmarksList->Items->InsertObject(BookmarksList->ItemIndex, Text, Bookmark);
BookmarksList->ItemIndex = PrevItemIndex;
}
else
{
BookmarkList->Add(Bookmark);
BookmarksList->Items->AddObject(Text, Bookmark);
BookmarksList->ItemIndex = BookmarksList->Items->Count-1;
}
UpdateControls(true);
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::AddBookmarkButtonClick(TObject * Sender)
{
AddAsBookmark(Sender);
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::RemoveBookmark(TObject * Sender)
{
TBookmarkList * BookmarkList = GetBookmarkList(Sender);
TListBox * BookmarksList = GetBookmarksList(Sender);
int PrevItemIndex = BookmarksList->ItemIndex;
TBookmark * Bookmark = GetBookmark(BookmarksList, PrevItemIndex);
DebugAssert(Bookmark != NULL);
BookmarkList->Delete(Bookmark);
BookmarksList->Items->Delete(PrevItemIndex);
if (PrevItemIndex < BookmarksList->Items->Count)
{
BookmarksList->ItemIndex = PrevItemIndex;
}
else
{
BookmarksList->ItemIndex = BookmarksList->Items->Count-1;
}
UpdateControls(true);
BookmarkSelected(Sender);
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::RemoveBookmarkButtonClick(TObject * Sender)
{
RemoveBookmark(Sender);
}
//---------------------------------------------------------------------------
Integer __fastcall TOpenDirectoryDialog::FindBookmark(TListBox * BookmarksList, const UnicodeString Bookmark)
{
if (OperationSide == osRemote)
{
for (int Index = 0; Index < BookmarksList->Items->Count; Index++)
{
TBookmark * ABookmark = GetBookmark(BookmarksList, Index);
if (AnsiCompareStr(BookmarkDirectory(ABookmark), Bookmark) == 0)
{
return Index;
}
}
}
else
{
for (int Index = 0; Index < BookmarksList->Items->Count; Index++)
{
TBookmark * ABookmark = GetBookmark(BookmarksList, Index);
if (AnsiCompareText(BookmarkDirectory(ABookmark), Bookmark) == 0)
{
return Index;
}
}
}
return -1;
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::BookmarkSelected(TObject * Sender)
{
TListBox * BookmarksList = GetBookmarksList(Sender);
if (BookmarksList->ItemIndex >= 0)
{
Directory = BookmarkDirectory(GetBookmark(BookmarksList, BookmarksList->ItemIndex));
}
UpdateControls();
FBookmarkSelected = true;
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::BookmarksListClick(TObject * Sender)
{
BookmarkSelected(Sender);
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::BookmarkMove(TObject * Sender,
int Source, int Dest)
{
TBookmarkList * BookmarkList = GetBookmarkList(Sender);
TListBox * BookmarksList = GetBookmarksList(Sender);
if (Source >= 0 && Source < BookmarksList->Items->Count &&
Dest >= 0 && Dest < BookmarksList->Items->Count)
{
BookmarkList->MoveTo(
GetBookmark(BookmarksList, Dest),
GetBookmark(BookmarksList, Source),
Source > Dest);
BookmarksList->Items->Move(Source, Dest);
BookmarksList->ItemIndex = Dest;
BookmarksList->SetFocus();
UpdateControls();
}
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::BookmarkButtonClick(TObject * Sender)
{
TControl * Control = dynamic_cast<TControl *>(Sender);
BookmarkMove(Sender,
GetBookmarksList(Sender)->ItemIndex,
GetBookmarksList(Sender)->ItemIndex + (Control->Tag / abs(Control->Tag)));
UpdateControls();
}
//---------------------------------------------------------------------------
bool __fastcall TOpenDirectoryDialog::AllowBookmarkDrag(TObject * Sender, int X, int Y)
{
FBookmarkDragDest = GetBookmarksList(Sender)->ItemAtPos(TPoint(X, Y), true);
return (FBookmarkDragDest >= 0) && (FBookmarkDragDest != FBookmarkDragSource);
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::BookmarksListStartDrag(
TObject * Sender , TDragObject *& /*DragObject*/)
{
FBookmarkDragSource = GetBookmarksList(Sender)->ItemIndex;
FBookmarkDragDest = -1;
GetScrollOnDragOver(Sender)->StartDrag();
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::BookmarksListDragOver(
TObject * Sender, TObject *Source, int X, int Y, TDragState /*State*/,
bool &Accept)
{
if (Source == GetBookmarksList(Sender))
{
Accept = AllowBookmarkDrag(Sender, X, Y);
GetScrollOnDragOver(Sender)->DragOver(TPoint(X, Y));
}
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::BookmarksListDragDrop(
TObject * Sender, TObject *Source, int X, int Y)
{
if (Source == GetBookmarksList(Sender))
{
if (AllowBookmarkDrag(Sender, X, Y))
{
BookmarkMove(Sender, FBookmarkDragSource, FBookmarkDragDest);
}
}
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::SelectBookmark(TListBox * BookmarksList)
{
int ItemIndex = FindBookmark(BookmarksList, Directory);
if (ItemIndex >= 0)
{
BookmarksList->ItemIndex = ItemIndex;
}
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::DirectoryEditChange(TObject * /*Sender*/)
{
SelectBookmark(SessionBookmarksList);
SelectBookmark(SharedBookmarksList);
UpdateControls();
FBookmarkSelected = false;
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::BookmarksListDblClick(TObject * Sender)
{
if (GetBookmarksList(Sender)->ItemIndex >= 0)
{
ModalResult = DefaultResult(this);
}
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::SetMode(TOpenDirectoryMode value)
{
FMode = value;
Caption = LoadStr(Mode == odBrowse ?
OPEN_DIRECTORY_BROWSE_CAPTION : OPEN_DIRECTORY_ADD_BOOMARK_ACTION );
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::FormShow(TObject * /*Sender*/)
{
InstallPathWordBreakProc(LocalDirectoryEdit);
InstallPathWordBreakProc(RemoteDirectoryEdit);
UpdateControls(true);
if (Mode == odBrowse)
{
ActiveControl = CurrentEdit;
}
else
{
ActiveControl = GetBookmarksList(PageControl->ActivePage);
}
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::BookmarksListKeyDown(TObject * Sender,
WORD & Key, TShiftState /*Shift*/)
{
if ((GetBookmarksList(Sender)->ItemIndex >= 0) && (Key == VK_DELETE))
{
RemoveBookmark(Sender);
}
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::LocalDirectoryBrowseButtonClick(
TObject * /*Sender*/)
{
UnicodeString Directory = LocalDirectoryEdit->Text;
if (SelectDirectory(Directory, LoadStr(SELECT_LOCAL_DIRECTORY), true))
{
LocalDirectoryEdit->Text = Directory;
DirectoryEditChange(NULL);
}
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::SwitchButtonClick(TObject * /*Sender*/)
{
WinConfiguration->UseLocationProfiles = true;
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::HelpButtonClick(TObject * /*Sender*/)
{
FormHelp(this);
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::BookmarksListEndDrag(TObject * Sender,
TObject * /*Target*/, int /*X*/, int /*Y*/)
{
GetScrollOnDragOver(Sender)->EndDrag();
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::ShortCutBookmarkButtonClick(
TObject * Sender)
{
TBookmarkList * BookmarkList = GetBookmarkList(Sender);
TListBox * BookmarksList = GetBookmarksList(Sender);
int Index = BookmarksList->ItemIndex;
TBookmark * Bookmark = GetBookmark(BookmarksList, Index);
DebugAssert(Bookmark != NULL);
TShortCuts ShortCuts;
WinConfiguration->CustomCommandShortCuts(ShortCuts);
BookmarkList->ShortCuts(ShortCuts);
TShortCut ShortCut = Bookmark->ShortCut;
if (DoShortCutDialog(ShortCut, ShortCuts, HelpKeyword))
{
Bookmark->ShortCut = ShortCut;
BookmarksList->Items->Strings[Index] = BookmarkText(Bookmark);
UpdateControls(true);
}
}
//---------------------------------------------------------------------------
void __fastcall TOpenDirectoryDialog::PageControlChange(TObject * /*Sender*/)
{
BookmarkSelected(GetBookmarksList(PageControl->ActivePage));
}
//---------------------------------------------------------------------------