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

Found files can be deleted on the Find dialog + Fixing selection management bug when deleting a single item/file in view (could probably manifest when local file was deleted externally)

Source commit: db63d72d979a6adfb9f308f36f933f181ea152e9
This commit is contained in:
Martin Prikryl
2016-09-27 15:28:55 +00:00
parent c3e71689d0
commit ae83e7e1d4
7 changed files with 265 additions and 53 deletions

View File

@@ -169,6 +169,7 @@ __fastcall TCustomScpExplorerForm::TCustomScpExplorerForm(TComponent* Owner):
DebugAssert(NonVisualDataModule && !NonVisualDataModule->ScpExplorer);
NonVisualDataModule->ScpExplorer = this;
FAutoOperation = false;
FOnFileOperationFinished = NULL;
FForceExecution = false;
FIgnoreNextDialogChar = 0;
FErrorList = NULL;
@@ -1418,22 +1419,21 @@ void __fastcall TCustomScpExplorerForm::DoOperationFinished(
Visible && (Operation != foCalculateSize) &&
(Operation != foGetProperties) && (Operation != foCalculateChecksum))
{
TCustomDirView * DView = DirView(Side);
UnicodeString FileNameOnly = ExtractFileName(FileName, (Side == osRemote));
TListItem *Item = DView->FindFileItem(FileNameOnly);
// this can happen when local drive is unplugged in the middle of the operation
if (Item != NULL)
if (FOnFileOperationFinished != NULL)
{
if (Success) Item->Selected = false;
if (DView->ViewStyle == vsReport)
FOnFileOperationFinished(FileName, Success);
}
else
{
TCustomDirView * DView = DirView(Side);
UnicodeString FileNameOnly = ExtractFileName(FileName, (Side == osRemote));
TListItem *Item = DView->FindFileItem(FileNameOnly);
// this can happen when local drive is unplugged in the middle of the operation
if (Item != NULL)
{
TRect DisplayRect = Item->DisplayRect(drBounds);
if (DisplayRect.Bottom > DView->ClientHeight)
{
DView->Scroll(0, Item->Top - DView->TopItem->Top);
}
if (Success) Item->Selected = false;
DView->MakeProgressVisible(Item);
}
Item->MakeVisible(false);
}
}
@@ -8685,10 +8685,30 @@ void __fastcall TCustomScpExplorerForm::DoFocusRemotePath(TTerminal * ATerminal,
}
}
//---------------------------------------------------------------------------
void __fastcall TCustomScpExplorerForm::DoDeleteFoundFiles(
TTerminal * ATerminal, TStrings * FileList, TFileOperationFinishedEvent OnFileOperationFinished)
{
if (!NonVisualDataModule->Busy)
{
TTerminalManager::Instance()->ActiveTerminal = ATerminal;
DebugAssert(FOnFileOperationFinished == NULL);
FOnFileOperationFinished = OnFileOperationFinished;
try
{
ExecuteFileOperation(foDelete, osRemote, FileList, false, NULL);
}
__finally
{
FOnFileOperationFinished = NULL;
}
}
}
//---------------------------------------------------------------------------
void __fastcall TCustomScpExplorerForm::RemoteFindFiles()
{
FFileFindTerminal = Terminal;
ShowFileFindDialog(Terminal, RemoteDirView->Path, DoFindFiles, DoFocusRemotePath);
ShowFileFindDialog(Terminal, RemoteDirView->Path, DoFindFiles, DoFocusRemotePath, DoDeleteFoundFiles);
}
//---------------------------------------------------------------------------
void __fastcall TCustomScpExplorerForm::UpdateTaskbarList(ITaskbarList3 * TaskbarList)

View File

@@ -198,6 +198,7 @@ private:
bool FQueueItemInvalidated;
bool FFormRestored;
bool FAutoOperation;
TFileOperationFinishedEvent FOnFileOperationFinished;
bool FForceExecution;
unsigned short FIgnoreNextDialogChar;
TStringList * FErrorList;
@@ -520,6 +521,7 @@ protected:
void __fastcall DoFindFiles(TTerminal * Terminal, UnicodeString Directory, const TFileMasks & FileMask,
TFileFoundEvent OnFileFound, TFindingFileEvent OnFindingFile);
virtual void __fastcall DoFocusRemotePath(TTerminal * Terminal, const UnicodeString & Path);
void __fastcall DoDeleteFoundFiles(TTerminal * Terminal, TStrings * FileList, TFileOperationFinishedEvent OnFileOperationFinished);
bool __fastcall ExecuteFileOperation(TFileOperation Operation, TOperationSide Side,
bool OnFocused, bool NoConfirmation = false, void * Param = NULL);
void __fastcall UpdateCopyParamCounters(const TCopyParamType & CopyParam);

View File

@@ -25,13 +25,13 @@
TFileFindDialog * FileFindDialog = NULL;
//---------------------------------------------------------------------------
void __fastcall ShowFileFindDialog(
TTerminal * Terminal, UnicodeString Directory, TFindEvent OnFind, TFocusFileEvent OnFocusFile)
TTerminal * Terminal, UnicodeString Directory, TFindEvent OnFind, TFocusFileEvent OnFocusFile, TDeleteFilesEvent OnDeleteFiles)
{
if (FileFindDialog == NULL)
{
FileFindDialog = new TFileFindDialog(Application);
}
FileFindDialog->Init(Terminal, Directory, OnFind, OnFocusFile);
FileFindDialog->Init(Terminal, Directory, OnFind, OnFocusFile, OnDeleteFiles);
FileFindDialog->Show();
}
//---------------------------------------------------------------------------
@@ -39,7 +39,7 @@ void __fastcall HideFileFindDialog()
{
if (FileFindDialog != NULL)
{
FileFindDialog->Close();
delete FileFindDialog;
}
}
//---------------------------------------------------------------------------
@@ -109,8 +109,11 @@ void __fastcall TFileFindDialog::UpdateControls()
}
StartStopButton->Caption = StartStopCaption;
EnableControl(FilterGroup, !Finding);
EnableControl(FocusButton, (FileView->ItemFocused != NULL));
EnableControl(CopyButton, (FileView->Items->Count > 0));
FocusAction->Enabled = (FileView->ItemFocused != NULL);
DeleteAction->Enabled = (FileView->SelCount > 0);
CopyAction->Enabled = (FileView->Items->Count > 0);
SelectAllAction->Enabled = (FileView->SelCount < FileView->Items->Count);
switch (FState)
{
case ffInit:
@@ -141,6 +144,9 @@ void __fastcall TFileFindDialog::UpdateControls()
DebugFail();
break;
}
FocusButton->Default = FileView->Focused() && (FState != ffInit);
StartStopButton->Default = !FocusButton->Default;
}
//---------------------------------------------------------------------------
void __fastcall TFileFindDialog::ControlChange(TObject * /*Sender*/)
@@ -149,7 +155,7 @@ void __fastcall TFileFindDialog::ControlChange(TObject * /*Sender*/)
}
//---------------------------------------------------------------------------
void __fastcall TFileFindDialog::Init(
TTerminal * Terminal, UnicodeString Directory, TFindEvent OnFind, TFocusFileEvent OnFocusFile)
TTerminal * Terminal, UnicodeString Directory, TFindEvent OnFind, TFocusFileEvent OnFocusFile, TDeleteFilesEvent OnDeleteFiles)
{
if (FTerminal != Terminal)
{
@@ -162,6 +168,7 @@ void __fastcall TFileFindDialog::Init(
FOnFind = OnFind;
FOnFocusFile = OnFocusFile;
FOnDeleteFiles = OnDeleteFiles;
MaskEdit->Text = WinConfiguration->SelectMask;
RemoteDirectoryEdit->Text = UnixExcludeTrailingBackslash(Directory);
@@ -174,14 +181,18 @@ void __fastcall TFileFindDialog::CreateParams(TCreateParams & Params)
Params.WndParent = GetDesktopWindow();
}
//---------------------------------------------------------------------------
void __fastcall TFileFindDialog::ClearItem(TListItem * Item)
{
TRemoteFile * File = static_cast<TRemoteFile *>(Item->Data);
Item->Data = NULL;
delete File;
}
//---------------------------------------------------------------------------
void __fastcall TFileFindDialog::Clear()
{
for (int Index = 0; Index < FileView->Items->Count; Index++)
{
TListItem * Item = FileView->Items->Item[Index];
TRemoteFile * File = static_cast<TRemoteFile *>(Item->Data);
Item->Data = NULL;
delete File;
ClearItem(FileView->Items->Item[Index]);
}
FileView->Items->Clear();
@@ -456,7 +467,7 @@ void __fastcall TFileFindDialog::FileViewDblClick(TObject * /*Sender*/)
}
}
//---------------------------------------------------------------------------
void __fastcall TFileFindDialog::FocusButtonClick(TObject * /*Sender*/)
void __fastcall TFileFindDialog::FocusActionExecute(TObject * /*Sender*/)
{
FocusFile();
}
@@ -489,7 +500,7 @@ void __fastcall TFileFindDialog::CopyToClipboard()
::CopyToClipboard(Strings.get());
}
//---------------------------------------------------------------------------
void __fastcall TFileFindDialog::CopyButtonClick(TObject * /*Sender*/)
void __fastcall TFileFindDialog::CopyActionExecute(TObject * /*Sender*/)
{
CopyToClipboard();
}
@@ -500,3 +511,60 @@ void __fastcall TFileFindDialog::FormClose(TObject * /*Sender*/, TCloseAction &
Action = caFree;
}
//---------------------------------------------------------------------------
void __fastcall TFileFindDialog::FileViewContextPopup(TObject * Sender, TPoint & MousePos, bool & Handled)
{
// to update source popup menu before TBX menu is created
UpdateControls();
MenuPopup(Sender, MousePos, Handled);
}
//---------------------------------------------------------------------------
void __fastcall TFileFindDialog::FileDeleteFinished(const UnicodeString & FileName, bool Success)
{
TFileItemMap::iterator I = FFileItemMap.find(FileName);
if (DebugAlwaysTrue(I != FFileItemMap.end()))
{
TListItem * Item = I->second;
FileView->MakeProgressVisible(Item);
if (Success)
{
ClearItem(Item);
Item->Delete();
}
FFileItemMap.erase(I);
}
}
//---------------------------------------------------------------------------
void __fastcall TFileFindDialog::DeleteActionExecute(TObject * /*Sender*/)
{
std::unique_ptr<TStrings> FileList(new TStringList());
DebugAssert(FFileItemMap.empty());
TListItem * Item = FileView->Selected;
while (Item != NULL)
{
TRemoteFile * File = static_cast<TRemoteFile *>(Item->Data);
FileList->AddObject(File->FullFileName, File);
FFileItemMap.insert(std::make_pair(File->FullFileName, Item));
Item = FileView->GetNextItem(Item, sdAll, TItemStates() << isSelected);
}
try
{
FOnDeleteFiles(FTerminal, FileList.get(), FileDeleteFinished);
}
__finally
{
// can be non-empty only when not all files were deleted
FFileItemMap.clear();
}
UpdateControls();
}
//---------------------------------------------------------------------------
void __fastcall TFileFindDialog::SelectAllActionExecute(TObject * /*Sender*/)
{
FileView->SelectAll(smAll);
}
//---------------------------------------------------------------------------

View File

@@ -1371,13 +1371,13 @@ object FileFindDialog: TFileFindDialog
object FilterGroup: TGroupBox
Left = 8
Top = 6
Width = 461
Width = 434
Height = 127
Anchors = [akLeft, akTop, akRight]
Caption = 'Filter'
TabOrder = 0
DesignSize = (
461
434
127)
object MaskLabel: TLabel
Left = 49
@@ -1404,7 +1404,7 @@ object FileFindDialog: TFileFindDialog
object RemoteDirectoryEdit: THistoryComboBox
Left = 49
Top = 87
Width = 401
Width = 374
Height = 21
AutoComplete = False
Anchors = [akLeft, akTop, akRight]
@@ -1416,7 +1416,7 @@ object FileFindDialog: TFileFindDialog
object MaskEdit: THistoryComboBox
Left = 49
Top = 36
Width = 315
Width = 288
Height = 21
AutoComplete = False
Anchors = [akLeft, akTop, akRight]
@@ -1427,7 +1427,7 @@ object FileFindDialog: TFileFindDialog
OnExit = MaskEditExit
end
object MaskHintText: TStaticText
Left = 240
Left = 213
Top = 59
Width = 124
Height = 17
@@ -1439,7 +1439,7 @@ object FileFindDialog: TFileFindDialog
TabStop = True
end
object MaskButton: TButton
Left = 370
Left = 343
Top = 33
Width = 80
Height = 25
@@ -1450,9 +1450,9 @@ object FileFindDialog: TFileFindDialog
end
end
object StartStopButton: TButton
Left = 476
Left = 448
Top = 11
Width = 80
Width = 108
Height = 25
Anchors = [akTop, akRight]
Caption = '&StartX'
@@ -1461,9 +1461,9 @@ object FileFindDialog: TFileFindDialog
OnClick = StartStopButtonClick
end
object HelpButton: TButton
Left = 476
Left = 448
Top = 42
Width = 80
Width = 108
Height = 25
Anchors = [akTop, akRight]
Caption = '&Help'
@@ -1473,16 +1473,19 @@ object FileFindDialog: TFileFindDialog
object FileView: TIEListView
Left = 8
Top = 142
Width = 461
Width = 434
Height = 252
Anchors = [akLeft, akTop, akRight, akBottom]
ColumnClick = False
FullDrag = True
ReadOnly = True
RowSelect = True
PopupMenu = FileViewPopupMenu
TabOrder = 3
ViewStyle = vsReport
OnDblClick = FileViewDblClick
OnEnter = ControlChange
OnExit = ControlChange
NortonLike = nlOff
Columns = <
item
@@ -1502,7 +1505,7 @@ object FileFindDialog: TFileFindDialog
Caption = 'Changed'
Width = 90
end>
MultiSelect = False
OnContextPopup = FileViewContextPopup
OnSelectItem = FileViewSelectItem
end
object StatusBar: TStatusBar
@@ -1514,23 +1517,81 @@ object FileFindDialog: TFileFindDialog
SimplePanel = True
end
object FocusButton: TButton
Left = 476
Left = 448
Top = 142
Width = 80
Width = 108
Height = 25
Action = FocusAction
Anchors = [akTop, akRight]
Caption = 'Fo&cus'
TabOrder = 4
OnClick = FocusButtonClick
end
object CopyButton: TButton
Left = 475
Top = 173
Width = 80
Left = 448
Top = 369
Width = 106
Height = 25
Action = CopyAction
Anchors = [akRight, akBottom]
TabOrder = 6
end
object DeleteButton: TButton
Left = 448
Top = 173
Width = 108
Height = 25
Action = DeleteAction
Anchors = [akTop, akRight]
Caption = '&Copy'
TabOrder = 5
OnClick = CopyButtonClick
end
object FileViewPopupMenu: TPopupMenu
Left = 478
Top = 237
object Focus1: TMenuItem
Action = FocusAction
Default = True
end
object N1: TMenuItem
Caption = '-'
end
object Delete1: TMenuItem
Action = DeleteAction
end
object N2: TMenuItem
Caption = '-'
end
object SelectAllItem: TMenuItem
Action = SelectAllAction
end
object N3: TMenuItem
Caption = '-'
end
object CopyResults1: TMenuItem
Action = CopyAction
end
end
object ActionList: TActionList
Left = 478
Top = 293
object DeleteAction: TAction
Caption = '&Delete'
SecondaryShortCuts.Strings = (
'F8')
ShortCut = 46
OnExecute = DeleteActionExecute
end
object FocusAction: TAction
Caption = '&Focus'
OnExecute = FocusActionExecute
end
object SelectAllAction: TAction
Caption = 'Select &All'
ShortCut = 16449
OnExecute = SelectAllActionExecute
end
object CopyAction: TAction
Caption = '&Copy Results'
ShortCut = 16451
OnExecute = CopyActionExecute
end
end
end

View File

@@ -17,6 +17,9 @@
#include <Vcl.Imaging.pngimage.hpp>
#include <Vcl.ImgList.hpp>
#include "PngImageList.hpp"
#include <System.Actions.hpp>
#include <Vcl.ActnList.hpp>
#include <Vcl.Menus.hpp>
//---------------------------------------------------------------------------
class TFileFindDialog : public TForm
{
@@ -35,6 +38,20 @@ __published:
TButton *MaskButton;
TPaintBox *AnimationPaintBox;
TButton *CopyButton;
TButton *DeleteButton;
TPopupMenu *FileViewPopupMenu;
TMenuItem *N2;
TMenuItem *SelectAllItem;
TActionList *ActionList;
TAction *SelectAllAction;
TAction *DeleteAction;
TAction *FocusAction;
TAction *CopyAction;
TMenuItem *Focus1;
TMenuItem *Delete1;
TMenuItem *N1;
TMenuItem *N3;
TMenuItem *CopyResults1;
void __fastcall ControlChange(TObject *Sender);
void __fastcall StartStopButtonClick(TObject *Sender);
void __fastcall StopButtonClick(TObject *Sender);
@@ -45,19 +62,22 @@ __published:
TShiftState Shift);
void __fastcall MaskEditExit(TObject *Sender);
void __fastcall FileViewDblClick(TObject *Sender);
void __fastcall FocusButtonClick(TObject *Sender);
void __fastcall FileViewSelectItem(TObject *Sender, TListItem *Item,
bool Selected);
void __fastcall MaskButtonClick(TObject *Sender);
void __fastcall CopyButtonClick(TObject *Sender);
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
void __fastcall FileViewContextPopup(TObject *Sender, TPoint &MousePos, bool &Handled);
void __fastcall DeleteActionExecute(TObject *Sender);
void __fastcall CopyActionExecute(TObject *Sender);
void __fastcall FocusActionExecute(TObject *Sender);
void __fastcall SelectAllActionExecute(TObject *Sender);
public:
__fastcall TFileFindDialog(TComponent * Owner);
virtual __fastcall ~TFileFindDialog();
void __fastcall Init(
TTerminal * Terminal, UnicodeString Directory, TFindEvent OnFind, TFocusFileEvent OnFocusFile);
TTerminal * Terminal, UnicodeString Directory, TFindEvent OnFind, TFocusFileEvent OnFocusFile, TDeleteFilesEvent OnDeleteFiles);
protected:
void __fastcall Clear();
@@ -81,9 +101,12 @@ private:
UnicodeString FWindowParams;
TFindEvent FOnFind;
TFocusFileEvent FOnFocusFile;
TDeleteFilesEvent FOnDeleteFiles;
TImageList * FSystemImageList;
TFrameAnimation FFrameAnimation;
UnicodeString FFocusPath;
typedef std::map<UnicodeString, TListItem *> TFileItemMap;
TFileItemMap FFileItemMap;
void __fastcall FileFound(TTerminal * Terminal,
const UnicodeString FileName, const TRemoteFile * File, bool & Cancel);
@@ -93,6 +116,8 @@ private:
void __fastcall FocusFile();
void __fastcall DoFocusFile(const UnicodeString & Path);
void __fastcall CMDialogKey(TWMKeyDown & Message);
void __fastcall ClearItem(TListItem * Item);
void __fastcall FileDeleteFinished(const UnicodeString & FileName, bool Success);
};
//---------------------------------------------------------------------------
#endif

View File

@@ -89,6 +89,7 @@ type
procedure SelectCurrentItem(FocusNext: Boolean);
function GetNextItem(StartItem: TListItem; Direction: TSearchDirection;
States: TItemStates): TListItem;
procedure MakeProgressVisible(Item: TListItem);
property ColProperties: TCustomListViewColProperties read FColProperties write FColProperties stored False;
@@ -216,10 +217,24 @@ begin
end;
procedure TCustomNortonLikeListView.Delete(Item: TListItem);
var
Index: Integer;
begin
if (FLastDeletedItem <> Item) and Item.Selected then
if FLastDeletedItem <> Item then
begin
ItemUnselected(Item, -1);
Index := Item.Index;
if Item.Selected then
ItemUnselected(Item, Index);
if FManageSelection then
begin
if (FLastSelected >= 0) and (Index <= FLastSelected) then
Dec(FLastSelected);
if (FFirstSelected >= 0) and (Index <= FFirstSelected) then
Dec(FFirstSelected);
end;
end;
FLastDeletedItem := Item;
inherited;
@@ -961,4 +976,21 @@ begin
Message.Result := 1;
end;
procedure TCustomNortonLikeListView.MakeProgressVisible(Item: TListItem);
var
DisplayRect: TRect;
begin
if ViewStyle = vsReport then
begin
DisplayRect := Item.DisplayRect(drBounds);
if DisplayRect.Bottom > ClientHeight then
begin
Scroll(0, Item.Top - TopItem.Top);
end;
end;
Item.MakeVisible(False);
end;
end.

View File

@@ -416,8 +416,12 @@ typedef void __fastcall (__closure *TFindEvent)
TFileFoundEvent OnFileFound, TFindingFileEvent OnFindingFile);
typedef void __fastcall (__closure *TFocusFileEvent)
(TTerminal * Terminal, const UnicodeString & Path);
typedef void __fastcall (__closure *TFileOperationFinishedEvent)
(const UnicodeString & FileName, bool Success);
typedef void __fastcall (__closure *TDeleteFilesEvent)
(TTerminal * Terminal, TStrings * FileList, TFileOperationFinishedEvent OnFileOperationFinished);
void __fastcall ShowFileFindDialog(
TTerminal * Terminal, UnicodeString Directory, TFindEvent OnFind, TFocusFileEvent OnFocusFile);
TTerminal * Terminal, UnicodeString Directory, TFindEvent OnFind, TFocusFileEvent OnFocusFile, TDeleteFilesEvent OnDeleteFiles);
void __fastcall HideFileFindDialog();
// forms\GenerateUrl.cpp