//--------------------------------------------------------------------------- #include #pragma hdrstop #include #include "WinInterface.h" #include "Synchronize.h" #include "VCLCommon.h" #include "CopyParams.h" #include "Terminal.h" #include "GUITools.h" #include #include #include #include #include //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "XPThemes" #pragma link "HistoryComboBox" #pragma link "GrayedCheckBox" #pragma resource "*.dfm" //--------------------------------------------------------------------------- const int WM_USER_STOP = WM_WINSCP_USER + 2; //--------------------------------------------------------------------------- bool __fastcall DoSynchronizeDialog(TSynchronizeParamType & Params, const TCopyParamType * CopyParams, TSynchronizeStartStopEvent OnStartStop, bool & SaveSettings, int Options, TGetSynchronizeOptionsEvent OnGetOptions) { bool Result; TSynchronizeDialog * Dialog = new TSynchronizeDialog(Application, OnStartStop, OnGetOptions); try { Dialog->Options = Options; Dialog->Params = Params; Dialog->CopyParams = *CopyParams; Dialog->SaveSettings = SaveSettings; Result = Dialog->Execute(); if (Result) { SaveSettings = Dialog->SaveSettings; Params = Dialog->Params; } } __finally { delete Dialog; } return Result; } //--------------------------------------------------------------------------- const TSynchronizeDialog::MaxLogItems = 1000; //--------------------------------------------------------------------------- __fastcall TSynchronizeDialog::TSynchronizeDialog(TComponent * Owner, TSynchronizeStartStopEvent OnStartStop, TGetSynchronizeOptionsEvent OnGetOptions) : TForm(Owner) { UseSystemSettings(this); FOptions = 0; FSynchronizing = false; FMinimizedByMe = false; FPresetsMenu = new TPopupMenu(this); FOnStartStop = OnStartStop; FOnGetOptions = OnGetOptions; FSynchronizeOptions = NULL; InstallPathWordBreakProc(LocalDirectoryEdit); InstallPathWordBreakProc(RemoteDirectoryEdit); } //--------------------------------------------------------------------------- __fastcall TSynchronizeDialog::~TSynchronizeDialog() { delete FSynchronizeOptions; delete FPresetsMenu; } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::UpdateControls() { EnableControl(StartButton, !LocalDirectoryEdit->Text.IsEmpty() && !RemoteDirectoryEdit->Text.IsEmpty()); TButton * OldButton = FSynchronizing ? StartButton : StopButton; TButton * NewButton = FSynchronizing ? StopButton : StartButton; if (!NewButton->Visible || OldButton->Visible) { NewButton->Visible = true; if (OldButton->Focused()) { NewButton->SetFocus(); } OldButton->Default = false; NewButton->Default = true; OldButton->Visible = false; // some of the above steps hides accelerators when start button is pressed with mouse ResetSystemSettings(this); } Caption = LoadStr(FSynchronizing ? SYNCHRONIZE_SYCHRONIZING : SYNCHRONIZE_TITLE); EnableControl(TransferSettingsButton, !FSynchronizing); CancelButton->Visible = !FSynchronizing || FLAGSET(FOptions, soNoMinimize); EnableControl(CancelButton, !FSynchronizing); EnableControl(DirectoriesGroup, !FSynchronizing); EnableControl(OptionsGroup, !FSynchronizing); EnableControl(CopyParamGroup, !FSynchronizing); MinimizeButton->Visible = FSynchronizing && FLAGCLEAR(FOptions, soNoMinimize); EnableControl(SynchronizeSelectedOnlyCheck, OptionsGroup->Enabled && FLAGSET(FOptions, soAllowSelectedOnly)); AnsiString InfoStr = CopyParams.GetInfoStr("; "); CopyParamLabel->Caption = InfoStr; CopyParamLabel->Hint = InfoStr; CopyParamLabel->ShowHint = (CopyParamLabel->Canvas->TextWidth(InfoStr) > (CopyParamLabel->Width * 3 / 2)); if (LogPanel->Visible != FSynchronizing) { if (FSynchronizing) { LogPanel->Visible = true; ClientHeight = ClientHeight + LogPanel->Height; } else { ClientHeight = ClientHeight - LogPanel->Height; LogPanel->Visible = false; } } } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::ControlChange(TObject * /*Sender*/) { UpdateControls(); } //--------------------------------------------------------------------------- bool __fastcall TSynchronizeDialog::Execute() { // at start assume that copy param is current preset FPreset = GUIConfiguration->CopyParamCurrent; LocalDirectoryEdit->Items = CustomWinConfiguration->History["LocalDirectory"]; RemoteDirectoryEdit->Items = CustomWinConfiguration->History["RemoteDirectory"]; ShowModal(); return true; } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::SetParams(const TSynchronizeParamType& value) { FParams = value; RemoteDirectoryEdit->Text = value.RemoteDirectory; LocalDirectoryEdit->Text = value.LocalDirectory; SynchronizeDeleteCheck->Checked = FLAGSET(value.Params, spDelete); SynchronizeExistingOnlyCheck->Checked = FLAGSET(value.Params, spExistingOnly); SynchronizeSelectedOnlyCheck->Checked = FLAGSET(value.Params, spSelectedOnly); SynchronizeRecursiveCheck->Checked = FLAGSET(value.Options, soRecurse); SynchronizeSynchronizeCheck->State = FLAGSET(value.Options, soSynchronizeAsk) ? cbGrayed : (FLAGSET(value.Options, soSynchronize) ? cbChecked : cbUnchecked); } //--------------------------------------------------------------------------- TSynchronizeParamType __fastcall TSynchronizeDialog::GetParams() { TSynchronizeParamType Result = FParams; Result.RemoteDirectory = RemoteDirectoryEdit->Text; Result.LocalDirectory = LocalDirectoryEdit->Text; Result.Params = (Result.Params & ~(spDelete | spExistingOnly | spSelectedOnly | spTimestamp)) | FLAGMASK(SynchronizeDeleteCheck->Checked, spDelete) | FLAGMASK(SynchronizeExistingOnlyCheck->Checked, spExistingOnly) | FLAGMASK(SynchronizeSelectedOnlyCheck->Checked, spSelectedOnly); Result.Options = (Result.Options & ~(soRecurse | soSynchronize | soSynchronizeAsk)) | FLAGMASK(SynchronizeRecursiveCheck->Checked, soRecurse) | FLAGMASK(SynchronizeSynchronizeCheck->State == cbChecked, soSynchronize) | FLAGMASK(SynchronizeSynchronizeCheck->State == cbGrayed, soSynchronizeAsk); return Result; } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::LocalDirectoryBrowseButtonClick( TObject * /*Sender*/) { AnsiString Directory = LocalDirectoryEdit->Text; if (SelectDirectory(Directory, LoadStr(SELECT_LOCAL_DIRECTORY), false)) { LocalDirectoryEdit->Text = Directory; } } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::SetOptions(int value) { if (Options != value) { FOptions = value; UpdateControls(); } } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::TransferSettingsButtonClick( TObject * /*Sender*/) { if (FLAGCLEAR(FOptions, soDoNotUsePresets)) { CopyParamListPopup( TransferSettingsButton->ClientToScreen(TPoint(0, TransferSettingsButton->Height)), FPresetsMenu, FCopyParams, FPreset, CopyParamClick, cplCustomize); } else { CopyParamGroupDblClick(NULL); } } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::DoStartStop(bool Start, bool Synchronize) { if (FOnStartStop) { TSynchronizeParamType SParams = GetParams(); SParams.Options = (SParams.Options & ~(soSynchronize | soSynchronizeAsk)) | FLAGMASK(Synchronize, soSynchronize); if (Start) { delete FSynchronizeOptions; FSynchronizeOptions = new TSynchronizeOptions; FOnGetOptions(SParams.Params, *FSynchronizeOptions); } FOnStartStop(this, Start, SParams, CopyParams, FSynchronizeOptions, DoAbort, NULL, DoLog); } } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::Dispatch(void * Message) { assert(Message); if ((reinterpret_cast(Message)->Msg == WM_USER_STOP) && FAbort) { if (FSynchronizing) { Stop(); } if (FClose) { FClose = false; ModalResult = mrCancel; } } else { TForm::Dispatch(Message); } } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::DoAbort(TObject * /*Sender*/, bool Close) { FAbort = true; FClose = Close; PostMessage(Handle, WM_USER_STOP, 0, 0); } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::DoLog(TSynchronizeController * /*Controller*/, TSynchronizeLogEntry Entry, const AnsiString Message) { LogView->Items->BeginUpdate(); try { TListItem * Item = LogView->Items->Add(); Item->Caption = Now().TimeString(); Item->SubItems->Add(Message); Item->MakeVisible(false); while (LogView->Items->Count > MaxLogItems) { LogView->Items->Delete(0); } } __finally { LogView->Items->EndUpdate(); if (Entry == slScan) { // redraw log before the scanning block update LogView->Repaint(); } } } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::StartButtonClick(TObject * /*Sender*/) { bool Synchronize; bool Continue = true; if (SynchronizeSynchronizeCheck->State == cbGrayed) { TMessageParams Params(mpNeverAskAgainCheck); switch (MoreMessageDialog(LoadStr(SYNCHRONISE_BEFORE_KEEPUPTODATE), NULL, qtConfirmation, qaYes | qaNo | qaCancel, HELP_KEEPUPTODATE_SYNCHRONIZE, &Params)) { case qaNeverAskAgain: SynchronizeSynchronizeCheck->State = cbChecked; // fall thru break; case qaYes: Synchronize = true; break; case qaNo: Synchronize = false; break; default: case qaCancel: Continue = false; break; }; } else { Synchronize = SynchronizeSynchronizeCheck->Checked; } if (Continue) { assert(!FSynchronizing); LocalDirectoryEdit->SaveToHistory(); CustomWinConfiguration->History["LocalDirectory"] = LocalDirectoryEdit->Items; RemoteDirectoryEdit->SaveToHistory(); CustomWinConfiguration->History["RemoteDirectory"] = RemoteDirectoryEdit->Items; FSynchronizing = true; try { UpdateControls(); Repaint(); FAbort = false; DoStartStop(true, Synchronize); } catch(...) { FSynchronizing = false; UpdateControls(); throw; } } } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::StopButtonClick(TObject * /*Sender*/) { Stop(); } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::Stop() { FSynchronizing = false; DoStartStop(false, false); UpdateControls(); Repaint(); if (IsIconic(Application->Handle) && FMinimizedByMe) { FMinimizedByMe = false; Application->Restore(); } } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::MinimizeButtonClick(TObject * /*Sender*/) { Application->Minimize(); FMinimizedByMe = true; } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::SetSaveSettings(bool value) { SaveSettingsCheck->Checked = value; } //--------------------------------------------------------------------------- bool __fastcall TSynchronizeDialog::GetSaveSettings() { return SaveSettingsCheck->Checked; } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::FormShow(TObject * /*Sender*/) { ClearLog(); UpdateControls(); } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::FormCloseQuery(TObject * /*Sender*/, bool & /*CanClose*/) { if (FSynchronizing) { Stop(); } } //--------------------------------------------------------------------------- TCopyParamType __fastcall TSynchronizeDialog::GetCopyParams() { TCopyParamType Result = FCopyParams; Result.PreserveTime = true; return Result; } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::SetCopyParams(const TCopyParamType & value) { FCopyParams = value; UpdateControls(); } //--------------------------------------------------------------------------- int __fastcall TSynchronizeDialog::CopyParamCustomDialogOptions() { return cfAllowTransferMode | cfAllowExcludeMask | cfAllowClearArchive | cfDisablePreserveTime; } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::CopyParamClick(TObject * Sender) { assert(FLAGCLEAR(FOptions, soDoNotUsePresets)); if (CopyParamListPopupClick(Sender, FCopyParams, FPreset, CopyParamCustomDialogOptions())) { UpdateControls(); } } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::CopyParamGroupContextPopup( TObject * /*Sender*/, TPoint & MousePos, bool & Handled) { if (FLAGCLEAR(FOptions, soDoNotUsePresets)) { CopyParamListPopup(CopyParamGroup->ClientToScreen(MousePos), FPresetsMenu, FCopyParams, FPreset, CopyParamClick, cplCustomize | cplCustomizeDefault); Handled = true; } } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::CopyParamGroupDblClick(TObject * /*Sender*/) { if (DoCopyParamCustomDialog(FCopyParams, CopyParamCustomDialogOptions())) { UpdateControls(); } } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::HelpButtonClick(TObject * /*Sender*/) { FormHelp(this); } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::ClearLog() { // TListItems::Clear() does nothing without allocated handle LogView->HandleNeeded(); LogView->Items->Clear(); } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::CopyLog() { AnsiString Content; for (int i = 0; i < LogView->Items->Count; i++) { TListItem * Item = LogView->Items->Item[i]; Content += Item->Caption + "\t" + Item->SubItems->Strings[0] + "\r\n"; } CopyToClipboard(Content); } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::LogViewKeyDown(TObject * /*Sender*/, WORD & Key, TShiftState Shift) { if (Key == VK_DELETE) { ClearLog(); Key = 0; } else if ((Key == 'C') && Shift.Contains(ssCtrl) && (LogView->Items->Count > 0)) { CopyLog(); Key = 0; } } //--------------------------------------------------------------------------- void __fastcall TSynchronizeDialog::FormKeyDown(TObject * /*Sender*/, WORD & Key, TShiftState /*Shift*/) { if ((Key == VK_ESCAPE) && FSynchronizing) { Stop(); Key = 0; } } //---------------------------------------------------------------------------