Custom.cpp 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593
  1. //---------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <Dialogs.hpp>
  5. //---------------------------------------------------------------------
  6. #include <Common.h>
  7. #include <CustomWinConfiguration.h>
  8. #include <WinInterface.h>
  9. #include <VCLCommon.h>
  10. #include <TextsWin.h>
  11. #include <HelpWin.h>
  12. #include <CoreMain.h>
  13. #include <PasTools.hpp>
  14. #include <ProgParams.h>
  15. #include <Tools.h>
  16. #include <GUITools.h>
  17. #include <HistoryComboBox.hpp>
  18. #include <Math.hpp>
  19. #include "Custom.h"
  20. //---------------------------------------------------------------------
  21. #pragma link "PasswordEdit"
  22. #pragma resource "*.dfm"
  23. //---------------------------------------------------------------------
  24. __fastcall TCustomDialog::TCustomDialog(UnicodeString AHelpKeyword)
  25. : TForm(GetFormOwner())
  26. {
  27. UseSystemSettings(this);
  28. FControlPadding = ScaleByTextHeight(this, 8);
  29. FPos = ScaleByTextHeight(this, 8);
  30. FPrePos = FPos;
  31. FHorizontalMargin = ScaleByTextHeight(this, 8);
  32. FIndent = FHorizontalMargin;
  33. FGroupBox = NULL;
  34. HelpKeyword = AHelpKeyword;
  35. TBorderIcons BI = BorderIcons;
  36. if (HelpKeyword.IsEmpty())
  37. {
  38. BI >> biHelp;
  39. OKButton->Left = CancelButton->Left;
  40. CancelButton->Left = HelpButton->Left;
  41. HelpButton->Visible = false;
  42. }
  43. else
  44. {
  45. BI << biHelp;
  46. }
  47. BorderIcons = BI;
  48. }
  49. //---------------------------------------------------------------------
  50. bool __fastcall TCustomDialog::Execute()
  51. {
  52. Changed();
  53. return (ShowModal() == DefaultResult(this));
  54. }
  55. //---------------------------------------------------------------------
  56. void __fastcall TCustomDialog::DoChange(bool & /*CanSubmit*/)
  57. {
  58. // noop
  59. }
  60. //---------------------------------------------------------------------
  61. void __fastcall TCustomDialog::Changed()
  62. {
  63. bool CanSubmit = true;
  64. DoChange(CanSubmit);
  65. EnableControl(OKButton, CanSubmit);
  66. }
  67. //---------------------------------------------------------------------
  68. void __fastcall TCustomDialog::Change(TObject * /*Sender*/)
  69. {
  70. Changed();
  71. }
  72. //---------------------------------------------------------------------------
  73. void __fastcall TCustomDialog::DoHelp()
  74. {
  75. FormHelp(this);
  76. }
  77. //---------------------------------------------------------------------------
  78. void __fastcall TCustomDialog::HelpButtonClick(TObject * /*Sender*/)
  79. {
  80. DoHelp();
  81. }
  82. //---------------------------------------------------------------------------
  83. void __fastcall TCustomDialog::DoShow()
  84. {
  85. OKButton->TabOrder = FCount;
  86. CancelButton->TabOrder = static_cast<short>(FCount + 1);
  87. HelpButton->TabOrder = static_cast<short>(FCount + 2);
  88. Changed();
  89. TForm::DoShow();
  90. }
  91. //---------------------------------------------------------------------------
  92. void __fastcall TCustomDialog::DoValidate()
  93. {
  94. // noop
  95. }
  96. //---------------------------------------------------------------------------
  97. bool __fastcall TCustomDialog::CloseQuery()
  98. {
  99. if (ModalResult == DefaultResult(this))
  100. {
  101. DoValidate();
  102. }
  103. return TForm::CloseQuery();
  104. }
  105. //---------------------------------------------------------------------------
  106. void __fastcall TCustomDialog::RemoveCancelButton()
  107. {
  108. CancelButton->Visible = false;
  109. OKButton->Left = CancelButton->Left;
  110. OKButton->Cancel = true;
  111. DebugAssert(OKButton->Width == CancelButton->Width);
  112. DebugAssert(OKButton->Top == CancelButton->Top);
  113. }
  114. //---------------------------------------------------------------------------
  115. void __fastcall TCustomDialog::AddDialogButton(TButton * Button)
  116. {
  117. Button->Parent = this;
  118. Button->Top = OKButton->Top;
  119. Button->Left = FHorizontalMargin;
  120. Button->Height = OKButton->Height;
  121. AddWinControl(Button);
  122. }
  123. //---------------------------------------------------------------------------
  124. void __fastcall TCustomDialog::AddImage(const UnicodeString & ImageName)
  125. {
  126. TImage * Image = new TImage(this);
  127. Image->Name = L"Image";
  128. Image->Parent = GetDefaultParent();
  129. LoadDialogImage(Image, ImageName);
  130. Image->SetBounds(FIndent, FPos + ScaleByTextHeight(this, 3), Image->Picture->Width, Image->Picture->Height);
  131. FIndent += Image->Width + ScaleByTextHeight(this, 12);
  132. }
  133. //---------------------------------------------------------------------------
  134. int __fastcall TCustomDialog::GetMaxControlWidth(TControl * Control)
  135. {
  136. return GetDefaultParent()->ClientWidth - Control->Left - FHorizontalMargin;
  137. }
  138. //---------------------------------------------------------------------------
  139. TWinControl * __fastcall TCustomDialog::GetDefaultParent()
  140. {
  141. return (FGroupBox != NULL) ? FGroupBox : static_cast<TWinControl *>(this);
  142. }
  143. //---------------------------------------------------------------------------
  144. void __fastcall TCustomDialog::AdjustHeight(TControl * Control)
  145. {
  146. FPos = Control->Top + Control->Height + FControlPadding;
  147. int Delta = (FPos - FPrePos);
  148. ClientHeight = ClientHeight + Delta;
  149. if (FGroupBox != NULL)
  150. {
  151. FGroupBox->Height = FGroupBox->Height + Delta;
  152. }
  153. FPrePos = FPos;
  154. }
  155. //---------------------------------------------------------------------------
  156. void __fastcall TCustomDialog::AddWinControl(TWinControl * Control)
  157. {
  158. Control->TabOrder = FCount;
  159. FCount++;
  160. }
  161. //---------------------------------------------------------------------------
  162. TCheckBox * __fastcall TCustomDialog::CreateAndAddCheckBox(const UnicodeString & Caption)
  163. {
  164. TCheckBox * CheckBox = new TCheckBox(this);
  165. CheckBox->Caption = Caption;
  166. AddButtonControl(CheckBox);
  167. return CheckBox;
  168. }
  169. //---------------------------------------------------------------------------
  170. TLabel * __fastcall TCustomDialog::CreateLabel(UnicodeString Label)
  171. {
  172. TLabel * Result = new TLabel(this);
  173. Result->Caption = Label;
  174. return Result;
  175. }
  176. //---------------------------------------------------------------------------
  177. void __fastcall TCustomDialog::AddEditLikeControl(TWinControl * Edit, TLabel * Label, bool OneLine)
  178. {
  179. Edit->Parent = GetDefaultParent();
  180. // this updates Height property to real value
  181. Edit->HandleNeeded();
  182. if (Label != NULL)
  183. {
  184. Label->Parent = GetDefaultParent();
  185. Label->Left = FIndent;
  186. if (OneLine)
  187. {
  188. DebugAssert(Edit->Height > Label->Height);
  189. Label->Top = FPos + ((Edit->Height - Label->Height) / 2);
  190. }
  191. else
  192. {
  193. Label->Top = FPos;
  194. FPos += Label->Height + ScaleByTextHeight(this, 4);
  195. }
  196. }
  197. Edit->Top = FPos;
  198. if (OneLine)
  199. {
  200. Edit->Left = GetDefaultParent()->ClientWidth - FHorizontalMargin - Edit->Width;
  201. }
  202. else
  203. {
  204. Edit->Left = FIndent;
  205. Edit->Width = GetMaxControlWidth(Edit);
  206. }
  207. AdjustHeight(Edit);
  208. if (Label != NULL)
  209. {
  210. if (Label->FocusControl == NULL)
  211. {
  212. Label->FocusControl = Edit;
  213. }
  214. else
  215. {
  216. DebugAssert(Label->FocusControl == Edit);
  217. }
  218. }
  219. AddWinControl(Edit);
  220. }
  221. //---------------------------------------------------------------------------
  222. void __fastcall TCustomDialog::AddEdit(TCustomEdit * Edit, TLabel * Label, bool OneLine)
  223. {
  224. AddEditLikeControl(Edit, Label, OneLine);
  225. TEdit * PublicEdit = reinterpret_cast<TEdit *>(Edit);
  226. if (PublicEdit->OnChange == NULL)
  227. {
  228. PublicEdit->OnChange = Change;
  229. }
  230. }
  231. //---------------------------------------------------------------------------
  232. void __fastcall TCustomDialog::SetUpComboBox(TCustomCombo * Combo, TStrings * Items, bool OneLine)
  233. {
  234. if (Items != NULL)
  235. {
  236. Combo->Items = Items;
  237. }
  238. if (OneLine)
  239. {
  240. int Width = 0;
  241. for (int Index = 0; Index < Combo->Items->Count; Index++)
  242. {
  243. Width = Max(Width, Combo->Canvas->TextWidth(Combo->Items->Strings[Index]));
  244. }
  245. Width += ScaleByTextHeight(Combo, 4 + 16 + 14);
  246. Width = Max(Width, HelpButton->Width);
  247. Combo->Width = Width;
  248. Combo->Left = GetDefaultParent()->ClientWidth - FHorizontalMargin - Width;
  249. }
  250. TComboBox * PublicCombo = reinterpret_cast<TComboBox *>(Combo);
  251. if (PublicCombo->OnChange == NULL)
  252. {
  253. PublicCombo->OnChange = Change;
  254. }
  255. }
  256. //---------------------------------------------------------------------------
  257. void __fastcall TCustomDialog::AddComboBox(TCustomCombo * Combo, TLabel * Label, TStrings * Items, bool OneLine)
  258. {
  259. AddEditLikeControl(Combo, Label, OneLine);
  260. SetUpComboBox(Combo, Items, OneLine);
  261. }
  262. //---------------------------------------------------------------------------
  263. void __fastcall TCustomDialog::AddShortCutComboBox(TComboBox * Combo, TLabel * Label, const TShortCuts & ShortCuts)
  264. {
  265. AddEditLikeControl(Combo, Label, true);
  266. InitializeShortCutCombo(Combo, ShortCuts);
  267. SetUpComboBox(Combo, NULL, true);
  268. }
  269. //---------------------------------------------------------------------------
  270. void __fastcall TCustomDialog::ScaleButtonControl(TButtonControl * Control)
  271. {
  272. // this updates Height property to real value
  273. Control->HandleNeeded();
  274. // buttons do not scale with text on their own
  275. Control->Height = ScaleByTextHeight(Control, Control->Height);
  276. }
  277. //---------------------------------------------------------------------------
  278. void __fastcall TCustomDialog::AddButtonControl(TButtonControl * Control)
  279. {
  280. Control->Parent = GetDefaultParent();
  281. Control->Left = FIndent + ScaleByTextHeight(this, 6);
  282. Control->Top = FPos;
  283. Control->Width = GetMaxControlWidth(Control);
  284. ScaleButtonControl(Control);
  285. AdjustHeight(Control);
  286. AddWinControl(Control);
  287. TCheckBox * PublicControl = reinterpret_cast<TCheckBox *>(Control);
  288. if (PublicControl->OnClick == NULL)
  289. {
  290. PublicControl->OnClick = Change;
  291. }
  292. }
  293. //---------------------------------------------------------------------------
  294. void __fastcall TCustomDialog::AddText(TLabel * Label)
  295. {
  296. Label->Parent = GetDefaultParent();
  297. DebugAssert(Label->AutoSize);
  298. Label->WordWrap = true;
  299. Label->Left = FIndent;
  300. Label->Width = GetMaxControlWidth(Label);
  301. Label->Top = FPos;
  302. Label->ShowAccelChar = false;
  303. TRect TextRect;
  304. SetRect(&TextRect, 0, 0, Label->Width, 0);
  305. DrawText(Label->Canvas->Handle, Label->Caption.c_str(), Label->Caption.Length() + 1, &TextRect,
  306. DT_EXPANDTABS | DT_CALCRECT | DT_WORDBREAK | DT_NOPREFIX |
  307. Label->DrawTextBiDiModeFlagsReadingOnly());
  308. if (TextRect.Height() > Label->Height)
  309. {
  310. Label->Height = TextRect.Height();
  311. Label->AutoSize = false;
  312. }
  313. else
  314. {
  315. Label->WordWrap = false;
  316. }
  317. AdjustHeight(Label);
  318. }
  319. //---------------------------------------------------------------------------
  320. void __fastcall TCustomDialog::AddText(TStaticText * Label)
  321. {
  322. Label->Parent = GetDefaultParent();
  323. DebugAssert(Label->AutoSize);
  324. Label->Left = FIndent;
  325. Label->Top = FPos;
  326. Label->ShowAccelChar = false;
  327. AdjustHeight(Label);
  328. AddWinControl(Label);
  329. }
  330. //---------------------------------------------------------------------------
  331. void __fastcall TCustomDialog::AddSeparator()
  332. {
  333. TBevel * Bevel = new TBevel(this);
  334. Bevel->Parent = GetDefaultParent();
  335. Bevel->Left = FIndent;
  336. Bevel->Top = FPos;
  337. Bevel->Height = 2;
  338. Bevel->Width = GetMaxControlWidth(Bevel);
  339. AdjustHeight(Bevel);
  340. }
  341. //---------------------------------------------------------------------------
  342. void __fastcall TCustomDialog::StartGroup(const UnicodeString & Caption)
  343. {
  344. if (FGroupBox != NULL)
  345. {
  346. FIndent = FGroupBox->Left;
  347. FPos = FGroupBox->Top + FGroupBox->Height + FControlPadding;
  348. FPrePos = FPos;
  349. FGroupBox = NULL;
  350. }
  351. TGroupBox * GroupBox = new TGroupBox(this);
  352. GroupBox->Parent = this;
  353. GroupBox->Caption = Caption;
  354. GroupBox->Left = FIndent;
  355. GroupBox->Top = FPos;
  356. GroupBox->Height = ScaleByTextHeight(GroupBox, 20);
  357. GroupBox->Width = GetMaxControlWidth(GroupBox);
  358. AdjustHeight(GroupBox);
  359. AddWinControl(GroupBox);
  360. FPos = ScaleByTextHeight(this, 16);
  361. FPrePos = FPos;
  362. FIndent = FHorizontalMargin;
  363. FGroupBox = GroupBox;
  364. }
  365. //---------------------------------------------------------------------------
  366. //---------------------------------------------------------------------------
  367. class TSaveSessionDialog : public TCustomDialog
  368. {
  369. public:
  370. __fastcall TSaveSessionDialog(TComponent* AOwner);
  371. void __fastcall Init(bool CanSavePassword, bool NotRecommendedSavingPassword,
  372. TStrings * AdditionalFolders);
  373. bool __fastcall Execute(UnicodeString & SessionName, bool & SavePassword,
  374. bool & CreateShortcut, const UnicodeString & OriginalSessionName);
  375. protected:
  376. virtual void __fastcall DoValidate();
  377. virtual void __fastcall DoChange(bool & CanSubmit);
  378. private:
  379. UnicodeString FOriginalSessionName;
  380. TEdit * SessionNameEdit;
  381. TComboBox * FolderCombo;
  382. TCheckBox * SavePasswordCheck;
  383. TCheckBox * CreateShortcutCheck;
  384. UnicodeString FRootFolder;
  385. UnicodeString __fastcall GetSessionName();
  386. };
  387. //---------------------------------------------------------------------------
  388. // Need to have an Owner argument for SafeFormCreate
  389. __fastcall TSaveSessionDialog::TSaveSessionDialog(TComponent* /*AOwner*/) :
  390. TCustomDialog(HELP_SESSION_SAVE)
  391. {
  392. }
  393. //---------------------------------------------------------------------------
  394. void __fastcall TSaveSessionDialog::Init(bool CanSavePassword,
  395. bool NotRecommendedSavingPassword, TStrings * AdditionalFolders)
  396. {
  397. Caption = LoadStr(SAVE_SESSION_CAPTION);
  398. SessionNameEdit = new TEdit(this);
  399. AddEdit(SessionNameEdit, CreateLabel(LoadStr(SAVE_SESSION_PROMPT)));
  400. FRootFolder = LoadStr(SAVE_SESSION_ROOT_FOLDER2);
  401. std::unique_ptr<TStringList> Folders(new TStringList());
  402. if (AdditionalFolders != NULL)
  403. {
  404. Folders->AddStrings(AdditionalFolders);
  405. }
  406. for (int Index = 0; Index < StoredSessions->Count; Index++)
  407. {
  408. TSessionData * Data = StoredSessions->Sessions[Index];
  409. if (!Data->Special && !Data->IsWorkspace)
  410. {
  411. UnicodeString Folder = Data->FolderName;
  412. if (!Folder.IsEmpty() && Folders->IndexOf(Folder) < 0)
  413. {
  414. Folders->Add(Folder);
  415. }
  416. }
  417. }
  418. DebugAssert(!Folders->CaseSensitive);
  419. Folders->Sort();
  420. FolderCombo = new TComboBox(this);
  421. AddComboBox(FolderCombo, CreateLabel(LoadStr(SAVE_SESSION_FOLDER)));
  422. FolderCombo->DropDownCount = Max(FolderCombo->DropDownCount, 16);
  423. FolderCombo->Items->Add(FRootFolder);
  424. FolderCombo->Items->AddStrings(Folders.get());
  425. SavePasswordCheck = CreateAndAddCheckBox(
  426. LoadStr(NotRecommendedSavingPassword ? SAVE_SESSION_PASSWORD :
  427. (CustomWinConfiguration->UseMasterPassword ? SAVE_SESSION_PASSWORD_MASTER : SAVE_SESSION_PASSWORD_RECOMMENDED)));
  428. CreateShortcutCheck = CreateAndAddCheckBox(LoadStr(SAVE_SITE_WORKSPACE_SHORTCUT));
  429. EnableControl(SavePasswordCheck, CanSavePassword);
  430. }
  431. //---------------------------------------------------------------------------
  432. bool __fastcall TSaveSessionDialog::Execute(
  433. UnicodeString & SessionName, bool & SavePassword, bool & CreateShortcut,
  434. const UnicodeString & OriginalSessionName)
  435. {
  436. FOriginalSessionName = OriginalSessionName;
  437. SessionNameEdit->Text = TSessionData::ExtractLocalName(SessionName);
  438. UnicodeString Folder = TSessionData::ExtractFolderName(SessionName);
  439. if (Folder.IsEmpty())
  440. {
  441. FolderCombo->Text = FRootFolder;
  442. }
  443. else
  444. {
  445. FolderCombo->Text = Folder;
  446. }
  447. SavePasswordCheck->Checked = SavePassword;
  448. CreateShortcutCheck->Checked = CreateShortcut;
  449. bool Result = TCustomDialog::Execute();
  450. if (Result)
  451. {
  452. SessionName = GetSessionName();
  453. SavePassword = SavePasswordCheck->Checked;
  454. CreateShortcut = CreateShortcutCheck->Checked;
  455. }
  456. return Result;
  457. }
  458. //---------------------------------------------------------------------------
  459. UnicodeString __fastcall TSaveSessionDialog::GetSessionName()
  460. {
  461. UnicodeString Folder;
  462. if (FolderCombo->Text != FRootFolder)
  463. {
  464. Folder = FolderCombo->Text;
  465. }
  466. return TSessionData::ComposePath(Folder, SessionNameEdit->Text);
  467. }
  468. //---------------------------------------------------------------------------
  469. void __fastcall TSaveSessionDialog::DoValidate()
  470. {
  471. TSessionData::ValidateName(SessionNameEdit->Text);
  472. SessionNameValidate(GetSessionName(), FOriginalSessionName);
  473. UnicodeString Folder = TSessionData::ExtractFolderName(GetSessionName());
  474. if (!Folder.IsEmpty() && StoredSessions->IsWorkspace(Folder))
  475. {
  476. throw Exception(FMTLOAD(WORKSPACE_NOT_FOLDER, (Folder)));
  477. }
  478. if (SavePasswordCheck->Enabled && SavePasswordCheck->Checked &&
  479. CustomWinConfiguration->UseMasterPassword)
  480. {
  481. CustomWinConfiguration->AskForMasterPasswordIfNotSet();
  482. }
  483. TCustomDialog::DoValidate();
  484. }
  485. //---------------------------------------------------------------------------
  486. void __fastcall TSaveSessionDialog::DoChange(bool & CanSubmit)
  487. {
  488. CanSubmit = !SessionNameEdit->Text.IsEmpty();
  489. TCustomDialog::DoChange(CanSubmit);
  490. }
  491. //---------------------------------------------------------------------------
  492. TSessionData * __fastcall DoSaveSession(TSessionData * SessionData,
  493. TSessionData * OriginalSession, bool ForceDialog,
  494. TStrings * AdditionalFolders)
  495. {
  496. bool SavePassword = false;
  497. bool * PSavePassword;
  498. bool NotRecommendedSavingPassword =
  499. !CustomWinConfiguration->UseMasterPassword &&
  500. !SameText(SessionData->UserName, AnonymousUserName);
  501. if (Configuration->DisablePasswordStoring ||
  502. !SessionData->HasAnySessionPassword())
  503. {
  504. PSavePassword = NULL;
  505. }
  506. else
  507. {
  508. PSavePassword = &SavePassword;
  509. SavePassword =
  510. ((OriginalSession != NULL) && OriginalSession->HasAnySessionPassword()) ||
  511. !NotRecommendedSavingPassword;
  512. }
  513. UnicodeString SessionName = SessionData->SessionName;
  514. bool Result;
  515. bool CreateShortcut = false;
  516. if (!ForceDialog && ((PSavePassword == NULL) || SavePassword))
  517. {
  518. // This is probably here to ask before session is started saving.
  519. // Otherwise we would ask implicitly, when saving passwords, but at that moment,
  520. // part of the site is already saved and when the user cancel the prompt it's too late.
  521. CustomWinConfiguration->AskForMasterPasswordIfNotSetAndNeededToPersistSessionData(SessionData);
  522. Result = true;
  523. }
  524. else
  525. {
  526. // This can be a standalone dialog when used with save URL (from GetLoginData)
  527. TSaveSessionDialog * Dialog = SafeFormCreate<TSaveSessionDialog>();
  528. try
  529. {
  530. Dialog->Init((PSavePassword != NULL), NotRecommendedSavingPassword, AdditionalFolders);
  531. Result = Dialog->Execute(SessionName, SavePassword, CreateShortcut, SessionData->Name);
  532. }
  533. __finally
  534. {
  535. delete Dialog;
  536. }
  537. }
  538. TSessionData * NewSession = NULL;
  539. if (Result)
  540. {
  541. if ((PSavePassword != NULL) && !SavePassword)
  542. {
  543. SessionData->ClearSessionPasswords();
  544. }
  545. NewSession =
  546. StoredSessions->NewSession(SessionName, SessionData);
  547. // modified only, explicit
  548. StoredSessions->Save(false, true);
  549. if (!SessionData->HostKey.IsEmpty())
  550. {
  551. SessionData->CacheHostKeyIfNotCached();
  552. }
  553. if (CreateShortcut)
  554. {
  555. TOperationVisualizer Visualizer;
  556. UnicodeString AdditionalParams =
  557. TProgramParams::FormatSwitch(DESKTOP_SWITCH) + L" " +
  558. TProgramParams::FormatSwitch(UPLOAD_IF_ANY_SWITCH);
  559. CreateDesktopSessionShortCut(SessionName, L"", AdditionalParams, -1, SITE_ICON);
  560. }
  561. }
  562. return NewSession;
  563. }
  564. //---------------------------------------------------------------------------
  565. void __fastcall SessionNameValidate(const UnicodeString & Text,
  566. const UnicodeString & OriginalName)
  567. {
  568. TSessionData::ValidatePath(Text);
  569. DebugAssert(StoredSessions);
  570. TSessionData * Data = (TSessionData *)StoredSessions->FindByName(Text);
  571. if (Data && Data->Special)
  572. {
  573. MessageDialog(FMTLOAD(CANNOT_OVERWRITE_SPECIAL_SESSION, (Text)),
  574. qtError, qaOK, HELP_NONE);
  575. Abort();
  576. }
  577. else if ((Data != NULL) && !Data->IsSameName(OriginalName) &&
  578. MessageDialog(MainInstructions(FMTLOAD(CONFIRM_OVERWRITE_SESSION, (Text))),
  579. qtConfirmation, qaYes | qaNo, HELP_SESSION_SAVE_OVERWRITE) != qaYes)
  580. {
  581. Abort();
  582. }
  583. }
  584. //---------------------------------------------------------------------------
  585. //---------------------------------------------------------------------------
  586. class TSaveWorkspaceDialog : public TCustomDialog
  587. {
  588. public:
  589. __fastcall TSaveWorkspaceDialog(bool CanSavePasswords,
  590. bool NotRecommendedSavingPasswords);
  591. bool __fastcall Execute(
  592. UnicodeString & WorkspaceName, bool & SavePasswords, bool & CreateShortcut,
  593. bool & EnableAutoSave);
  594. protected:
  595. virtual void __fastcall DoValidate();
  596. virtual void __fastcall DoChange(bool & CanSubmit);
  597. private:
  598. TComboBox * WorkspaceNameCombo;
  599. TCheckBox * SavePasswordsCheck;
  600. TCheckBox * CreateShortcutCheck;
  601. TCheckBox * EnableAutoSaveCheck;
  602. };
  603. //---------------------------------------------------------------------------
  604. __fastcall TSaveWorkspaceDialog::TSaveWorkspaceDialog(
  605. bool CanSavePasswords, bool NotRecommendedSavingPasswords) :
  606. TCustomDialog(HELP_WORKSPACE_SAVE)
  607. {
  608. Caption = LoadStr(SAVE_WORKSPACE_CAPTION);
  609. WorkspaceNameCombo = new TComboBox(this);
  610. WorkspaceNameCombo->AutoComplete = false;
  611. AddComboBox(WorkspaceNameCombo, CreateLabel(LoadStr(SAVE_WORKSPACE_PROMPT)));
  612. WorkspaceNameCombo->DropDownCount = Max(WorkspaceNameCombo->DropDownCount, 16);
  613. std::unique_ptr<TStrings> Workspaces(StoredSessions->GetWorkspaces());
  614. WorkspaceNameCombo->Items->AddStrings(Workspaces.get());
  615. SavePasswordsCheck = CreateAndAddCheckBox(
  616. LoadStr(NotRecommendedSavingPasswords ? SAVE_WORKSPACE_PASSWORDS :
  617. (CustomWinConfiguration->UseMasterPassword ?
  618. SAVE_WORKSPACE_PASSWORDS_MASTER : SAVE_WORKSPACE_PASSWORDS_RECOMMENDED)));
  619. EnableControl(SavePasswordsCheck, CanSavePasswords);
  620. CreateShortcutCheck = CreateAndAddCheckBox(LoadStr(SAVE_SITE_WORKSPACE_SHORTCUT));
  621. EnableAutoSaveCheck = CreateAndAddCheckBox(LoadStr(SAVE_WORKSPACE_AUTO));
  622. }
  623. //---------------------------------------------------------------------------
  624. bool __fastcall TSaveWorkspaceDialog::Execute(
  625. UnicodeString & WorkspaceName, bool & SavePasswords, bool & CreateShortcut,
  626. bool & EnableAutoSave)
  627. {
  628. WorkspaceNameCombo->Text = WorkspaceName;
  629. SavePasswordsCheck->Checked = SavePasswords;
  630. CreateShortcutCheck->Checked = CreateShortcut;
  631. EnableAutoSaveCheck->Checked = EnableAutoSave;
  632. bool Result = TCustomDialog::Execute();
  633. if (Result)
  634. {
  635. WorkspaceName = WorkspaceNameCombo->Text;
  636. SavePasswords = SavePasswordsCheck->Checked;
  637. CreateShortcut = CreateShortcutCheck->Checked;
  638. EnableAutoSave = EnableAutoSaveCheck->Checked;
  639. }
  640. return Result;
  641. }
  642. //---------------------------------------------------------------------------
  643. void __fastcall TSaveWorkspaceDialog::DoValidate()
  644. {
  645. TSessionData::ValidateName(WorkspaceNameCombo->Text);
  646. if (StoredSessions->IsFolder(WorkspaceNameCombo->Text))
  647. {
  648. throw Exception(FMTLOAD(FOLDER_NOT_WORKSPACE, (WorkspaceNameCombo->Text)));
  649. }
  650. if (SavePasswordsCheck->Enabled && SavePasswordsCheck->Checked &&
  651. CustomWinConfiguration->UseMasterPassword)
  652. {
  653. CustomWinConfiguration->AskForMasterPasswordIfNotSet();
  654. }
  655. TCustomDialog::DoValidate();
  656. }
  657. //---------------------------------------------------------------------------
  658. void __fastcall TSaveWorkspaceDialog::DoChange(bool & CanSubmit)
  659. {
  660. CanSubmit = !WorkspaceNameCombo->Text.IsEmpty();
  661. TCustomDialog::DoChange(CanSubmit);
  662. }
  663. //---------------------------------------------------------------------------
  664. bool __fastcall DoSaveWorkspaceDialog(UnicodeString & WorkspaceName,
  665. bool * SavePasswords, bool NotRecommendedSavingPasswords,
  666. bool & CreateShortcut, bool & EnableAutoSave)
  667. {
  668. std::unique_ptr<TSaveWorkspaceDialog> Dialog(
  669. new TSaveWorkspaceDialog((SavePasswords != NULL), NotRecommendedSavingPasswords));
  670. bool Dummy = false;
  671. if (SavePasswords == NULL)
  672. {
  673. SavePasswords = &Dummy;
  674. }
  675. return
  676. Dialog->Execute(
  677. WorkspaceName, *SavePasswords, CreateShortcut, EnableAutoSave);
  678. }
  679. //---------------------------------------------------------------------------
  680. //---------------------------------------------------------------------------
  681. class TShortCutDialog : public TCustomDialog
  682. {
  683. public:
  684. __fastcall TShortCutDialog(const TShortCuts & ShortCuts, UnicodeString HelpKeyword);
  685. bool __fastcall Execute(TShortCut & ShortCut);
  686. private:
  687. TComboBox * ShortCutCombo;
  688. };
  689. //---------------------------------------------------------------------------
  690. __fastcall TShortCutDialog::TShortCutDialog(const TShortCuts & ShortCuts, UnicodeString HelpKeyword) :
  691. TCustomDialog(HelpKeyword)
  692. {
  693. Caption = LoadStr(SHORTCUT_CAPTION);
  694. ShortCutCombo = new TComboBox(this);
  695. AddShortCutComboBox(ShortCutCombo, CreateLabel(LoadStr(SHORTCUT_LABEL)), ShortCuts);
  696. }
  697. //---------------------------------------------------------------------------
  698. bool __fastcall TShortCutDialog::Execute(TShortCut & ShortCut)
  699. {
  700. SetShortCutCombo(ShortCutCombo, ShortCut);
  701. bool Result = TCustomDialog::Execute();
  702. if (Result)
  703. {
  704. ShortCut = GetShortCutCombo(ShortCutCombo);
  705. }
  706. return Result;
  707. }
  708. //---------------------------------------------------------------------------
  709. bool __fastcall DoShortCutDialog(TShortCut & ShortCut,
  710. const TShortCuts & ShortCuts, UnicodeString HelpKeyword)
  711. {
  712. bool Result;
  713. TShortCutDialog * Dialog = new TShortCutDialog(ShortCuts, HelpKeyword);
  714. try
  715. {
  716. Result = Dialog->Execute(ShortCut);
  717. }
  718. __finally
  719. {
  720. delete Dialog;
  721. }
  722. return Result;
  723. }
  724. //---------------------------------------------------------------------------
  725. //---------------------------------------------------------------------------
  726. class TRemoteMoveDialog : public TCustomDialog
  727. {
  728. public:
  729. __fastcall TRemoteMoveDialog(bool Multi);
  730. bool __fastcall Execute(UnicodeString & Target, UnicodeString & FileMask);
  731. protected:
  732. DYNAMIC void __fastcall DoShow();
  733. virtual void __fastcall DoValidate();
  734. UnicodeString __fastcall GetFileMask();
  735. private:
  736. THistoryComboBox * Combo;
  737. bool FMulti;
  738. };
  739. //---------------------------------------------------------------------------
  740. __fastcall TRemoteMoveDialog::TRemoteMoveDialog(bool Multi) :
  741. TCustomDialog(HELP_REMOTE_MOVE)
  742. {
  743. Caption = LoadStr(REMOTE_MOVE_TITLE);
  744. // The same as TRemoteTransferDialog
  745. ClientWidth = ScaleByTextHeight(this, 420);
  746. FMulti = Multi;
  747. AddImage(L"Move To");
  748. Combo = new THistoryComboBox(this);
  749. Combo->AutoComplete = false;
  750. AddComboBox(Combo, CreateLabel(LoadStr(REMOTE_TRANSFER_PROMPT2)));
  751. }
  752. //---------------------------------------------------------------------------
  753. bool __fastcall TRemoteMoveDialog::Execute(UnicodeString & Target, UnicodeString & FileMask)
  754. {
  755. Combo->Items = CustomWinConfiguration->History[L"RemoteTarget"];
  756. Combo->Text = UnixIncludeTrailingBackslash(Target) + FileMask;
  757. bool Result = TCustomDialog::Execute();
  758. if (Result)
  759. {
  760. Target = UnixExtractFilePath(Combo->Text);
  761. FileMask = GetFileMask();
  762. Combo->SaveToHistory();
  763. CustomWinConfiguration->History[L"RemoteTarget"] = Combo->Items;
  764. }
  765. return Result;
  766. }
  767. //---------------------------------------------------------------------------
  768. UnicodeString __fastcall TRemoteMoveDialog::GetFileMask()
  769. {
  770. return UnixExtractFileName(Combo->Text);
  771. }
  772. //---------------------------------------------------------------------------
  773. void __fastcall TRemoteMoveDialog::DoShow()
  774. {
  775. TCustomDialog::DoShow();
  776. InstallPathWordBreakProc(Combo);
  777. }
  778. //---------------------------------------------------------------------------
  779. void __fastcall TRemoteMoveDialog::DoValidate()
  780. {
  781. if (!IsFileNameMask(GetFileMask()) && FMulti)
  782. {
  783. UnicodeString Message =
  784. FormatMultiFilesToOneConfirmation(Combo->Text, true);
  785. if (MessageDialog(Message, qtConfirmation, qaOK | qaCancel, HELP_NONE) == qaCancel)
  786. {
  787. Abort();
  788. }
  789. }
  790. TCustomDialog::DoValidate();
  791. }
  792. //---------------------------------------------------------------------------
  793. bool __fastcall DoRemoteMoveDialog(bool Multi, UnicodeString & Target, UnicodeString & FileMask)
  794. {
  795. std::unique_ptr<TRemoteMoveDialog> Dialog(new TRemoteMoveDialog(Multi));
  796. return Dialog->Execute(Target, FileMask);
  797. }
  798. //---------------------------------------------------------------------------
  799. //---------------------------------------------------------------------------
  800. class TCustomCommandOptionsDialog : public TCustomDialog
  801. {
  802. public:
  803. __fastcall TCustomCommandOptionsDialog(
  804. const TCustomCommandType * Command, TStrings * CustomCommandOptions, unsigned int Flags,
  805. TCustomCommand * CustomCommandForOptions, const UnicodeString & Site, const TShortCuts * ShortCuts);
  806. bool __fastcall Execute(TShortCut * ShortCut);
  807. protected:
  808. virtual void __fastcall DoHelp();
  809. DYNAMIC void __fastcall DoShow();
  810. private:
  811. const TCustomCommandType * FCommand;
  812. TStrings * FCustomCommandOptions;
  813. std::vector<TControl *> FControls;
  814. std::vector<std::vector<UnicodeString> > FValues;
  815. unsigned int FFlags;
  816. UnicodeString FSite;
  817. TComboBox * FShortCutCombo;
  818. UnicodeString __fastcall HistoryKey(const TCustomCommandType::TOption & Option);
  819. THistoryComboBox * __fastcall CreateHistoryComboBox(const TCustomCommandType::TOption & Option, const UnicodeString & Value);
  820. void __fastcall BrowseButtonClick(TObject * Sender);
  821. void __fastcall LinkLabelClick(TObject * Sender);
  822. UnicodeString __fastcall SaveHistoryComboBoxValue(TControl * Control, const TCustomCommandType::TOption & Option);
  823. void __fastcall AddOptionComboBox(
  824. TComboBox * ComboBox, const UnicodeString & Value, const TCustomCommandType::TOption & Option,
  825. std::vector<UnicodeString> & Values);
  826. UnicodeString __fastcall GetComboBoxValue(TControl * Control, const UnicodeString & Default);
  827. int __fastcall GetOptionIndex(TControl * Control);
  828. int __fastcall GetControlIndex(TControl * Control);
  829. };
  830. //---------------------------------------------------------------------------
  831. __fastcall TCustomCommandOptionsDialog::TCustomCommandOptionsDialog(
  832. const TCustomCommandType * Command, TStrings * CustomCommandOptions,
  833. unsigned int Flags, TCustomCommand * CustomCommandForOptions,
  834. const UnicodeString & Site, const TShortCuts * ShortCuts) :
  835. TCustomDialog(HELP_EXTENSION_OPTIONS)
  836. {
  837. FCommand = Command;
  838. FFlags = Flags;
  839. FCustomCommandOptions = CustomCommandOptions;
  840. FSite = Site;
  841. Caption = StripEllipsis(StripHotkey(FCommand->Name));
  842. Width = ScaleByTextHeight(this, 400);
  843. bool HasGroups = false;
  844. int ControlIndex = 0;
  845. for (int OptionIndex = 0; OptionIndex < FCommand->OptionsCount; OptionIndex++)
  846. {
  847. const TCustomCommandType::TOption & Option = FCommand->GetOption(OptionIndex);
  848. if ((Option.Flags & FFlags) != 0)
  849. {
  850. UnicodeString OptionKey = FCommand->GetOptionKey(Option, FSite);
  851. UnicodeString Value;
  852. if ((CustomCommandForOptions != NULL) &&
  853. Option.HasPatterns(CustomCommandForOptions))
  854. {
  855. Value = CustomCommandForOptions->Complete(Option.Default, true);
  856. }
  857. else
  858. {
  859. if (FCustomCommandOptions->IndexOfName(OptionKey) >= 0)
  860. {
  861. Value = FCustomCommandOptions->Values[OptionKey];
  862. }
  863. else
  864. {
  865. Value = Option.Default;
  866. }
  867. }
  868. int Tag = (OptionIndex << 16) + ControlIndex;
  869. TControl * Control = NULL;
  870. std::vector<UnicodeString> Values;
  871. if (Option.Kind == TCustomCommandType::okUnknown)
  872. {
  873. Control = NULL;
  874. }
  875. else if (Option.Kind == TCustomCommandType::okLabel)
  876. {
  877. TLabel * Label = CreateLabel(Option.Caption);
  878. AddText(Label);
  879. Control = Label;
  880. }
  881. else if (Option.Kind == TCustomCommandType::okLink)
  882. {
  883. TStaticText * Label = new TStaticText(this);
  884. Label->Caption = Option.Caption;
  885. if (IsHttpOrHttpsUrl(Label->Caption))
  886. {
  887. Label->Caption = SecureUrl(Label->Caption);
  888. LinkLabel(Label);
  889. Label->TabStop = true;
  890. }
  891. else if (!Option.Default.IsEmpty() && IsHttpOrHttpsUrl(Option.Default))
  892. {
  893. Label->OnClick = LinkLabelClick;
  894. LinkLabel(Label);
  895. Label->TabStop = true;
  896. }
  897. else
  898. {
  899. // keep it plain text, as we have no URL
  900. }
  901. AddText(Label);
  902. Control = Label;
  903. }
  904. else if (Option.Kind == TCustomCommandType::okGroup)
  905. {
  906. StartGroup(Option.Caption);
  907. HasGroups = true;
  908. }
  909. else if (Option.Kind == TCustomCommandType::okSeparator)
  910. {
  911. AddSeparator();
  912. }
  913. else if (Option.Kind == TCustomCommandType::okTextBox)
  914. {
  915. Control = CreateHistoryComboBox(Option, Value);
  916. }
  917. else if (Option.Kind == TCustomCommandType::okFile)
  918. {
  919. THistoryComboBox * ComboBox = CreateHistoryComboBox(Option, Value);
  920. TButton * Button = new TButton(this);
  921. Button->Parent = GetDefaultParent();
  922. Button->Width = HelpButton->Width;
  923. Button->Left = GetDefaultParent()->ClientWidth - Button->Width - HorizontalMargin;
  924. ComboBox->Width = Button->Left - ComboBox->Left - ScaleByTextHeight(this, 6);
  925. Button->Top = ComboBox->Top - ScaleByTextHeight(this, 2);
  926. Button->Tag = Tag;
  927. Button->Caption = LoadStr(EXTENSION_OPTIONS_BROWSE);
  928. Button->OnClick = BrowseButtonClick;
  929. ScaleButtonControl(Button);
  930. AddWinControl(Button);
  931. Control = ComboBox;
  932. }
  933. else if (Option.Kind == TCustomCommandType::okDropDownList)
  934. {
  935. TComboBox * ComboBox = new TComboBox(this);
  936. ComboBox->Style = csDropDownList;
  937. AddOptionComboBox(ComboBox, Value, Option, Values);
  938. Control = ComboBox;
  939. }
  940. else if (Option.Kind == TCustomCommandType::okComboBox)
  941. {
  942. TComboBox * ComboBox = new TComboBox(this);
  943. ComboBox->Style = csDropDown;
  944. AddOptionComboBox(ComboBox, Value, Option, Values);
  945. if (ComboBox->ItemIndex < 0)
  946. {
  947. ComboBox->Text = Value;
  948. }
  949. Control = ComboBox;
  950. }
  951. else if (Option.Kind == TCustomCommandType::okCheckBox)
  952. {
  953. TCheckBox * CheckBox = CreateAndAddCheckBox(Option.Caption);
  954. CheckBox->Checked =
  955. (Option.Params.size() >= 1) &&
  956. (Value == Option.Params[0]);
  957. Control = CheckBox;
  958. }
  959. else
  960. {
  961. DebugFail();
  962. }
  963. if (Control != NULL)
  964. {
  965. Control->Tag = Tag;
  966. }
  967. FControls.push_back(Control);
  968. FValues.push_back(Values);
  969. ControlIndex++;
  970. DebugAssert(static_cast<int>(FControls.size()) == ControlIndex);
  971. }
  972. }
  973. if (ShortCuts != NULL)
  974. {
  975. if (HasGroups)
  976. {
  977. StartGroup(LoadStr(EXTENSION_GENERAL_GROUP));
  978. }
  979. else if (ControlIndex > 0)
  980. {
  981. AddSeparator();
  982. }
  983. FShortCutCombo = new TComboBox(this);
  984. AddShortCutComboBox(FShortCutCombo, CreateLabel(LoadStr(EXTENSION_SHORTCUT)), *ShortCuts);
  985. }
  986. }
  987. //---------------------------------------------------------------------------
  988. void __fastcall TCustomCommandOptionsDialog::AddOptionComboBox(
  989. TComboBox * ComboBox, const UnicodeString & Value, const TCustomCommandType::TOption & Option, std::vector<UnicodeString> & Values)
  990. {
  991. std::unique_ptr<TStringList> Items(new TStringList());
  992. int ItemIndex = -1;
  993. TCustomCommandType::TOption::TParams::const_iterator ParamI = Option.Params.begin();
  994. while (ParamI != Option.Params.end())
  995. {
  996. UnicodeString Item = (*ParamI);
  997. int P = Item.Pos(L"=");
  998. UnicodeString ParamValue;
  999. if (P > 0)
  1000. {
  1001. ParamValue = Item.SubString(1, P - 1);
  1002. Item.Delete(1, P);
  1003. }
  1004. else
  1005. {
  1006. ParamValue = Item;
  1007. }
  1008. Item = WinConfiguration->ExtensionStringTranslation(FCommand->Id, Item);
  1009. Items->Add(Item);
  1010. if (Value == ParamValue)
  1011. {
  1012. ItemIndex = Items->Count - 1;
  1013. }
  1014. Values.push_back(ParamValue);
  1015. ParamI++;
  1016. }
  1017. AddComboBox(ComboBox, CreateLabel(Option.Caption), Items.get(), true);
  1018. ComboBox->ItemIndex = ItemIndex;
  1019. }
  1020. //---------------------------------------------------------------------------
  1021. int __fastcall TCustomCommandOptionsDialog::GetOptionIndex(TControl * Control)
  1022. {
  1023. return (Control->Tag >> 16);
  1024. }
  1025. //---------------------------------------------------------------------------
  1026. int __fastcall TCustomCommandOptionsDialog::GetControlIndex(TControl * Control)
  1027. {
  1028. return (Control->Tag & 0xFFFF);
  1029. }
  1030. //---------------------------------------------------------------------------
  1031. void __fastcall TCustomCommandOptionsDialog::LinkLabelClick(TObject * Sender)
  1032. {
  1033. TStaticText * Label = DebugNotNull(dynamic_cast<TStaticText *>(Sender));
  1034. const TCustomCommandType::TOption & Option = FCommand->GetOption(GetOptionIndex(Label));
  1035. OpenBrowser(SecureUrl(Option.Default));
  1036. }
  1037. //---------------------------------------------------------------------------
  1038. void __fastcall TCustomCommandOptionsDialog::BrowseButtonClick(TObject * Sender)
  1039. {
  1040. TButton * Button = DebugNotNull(dynamic_cast<TButton *>(Sender));
  1041. int OptionIndex = GetOptionIndex(Button);
  1042. const TCustomCommandType::TOption & Option = FCommand->GetOption(OptionIndex);
  1043. int ControlIndex = GetControlIndex(Button);
  1044. THistoryComboBox * ComboBox = dynamic_cast<THistoryComboBox *>(FControls[ControlIndex]);
  1045. std::unique_ptr<TOpenDialog> OpenDialog(new TOpenDialog(Application));
  1046. UnicodeString Title;
  1047. if (!Option.FileCaption.IsEmpty())
  1048. {
  1049. Title = Option.FileCaption;
  1050. }
  1051. else
  1052. {
  1053. UnicodeString Caption = Option.Caption;
  1054. Caption = StripHotkey(Caption);
  1055. if (!Caption.IsEmpty() && (Caption[Caption.Length()] == L':'))
  1056. {
  1057. Caption.SetLength(Caption.Length() - 1);
  1058. }
  1059. Title = FMTLOAD(EXTENSION_OPTIONS_BROWSE_TITLE, (Caption));
  1060. }
  1061. OpenDialog->Title = Title;
  1062. UnicodeString Value;
  1063. if (ComboBox->Text.IsEmpty())
  1064. {
  1065. Value = Option.FileInitial;
  1066. }
  1067. else
  1068. {
  1069. Value = ComboBox->Text;
  1070. }
  1071. UnicodeString ExpandedValue = ExpandEnvironmentVariables(Value);
  1072. OpenDialog->FileName = ExpandedValue;
  1073. UnicodeString InitialDir = ExtractFilePath(ExpandedValue);
  1074. if (!InitialDir.IsEmpty())
  1075. {
  1076. OpenDialog->InitialDir = InitialDir;
  1077. }
  1078. OpenDialog->Filter = Option.FileFilter;
  1079. OpenDialog->DefaultExt = Option.FileExt;
  1080. if (OpenDialog->Execute())
  1081. {
  1082. if (OpenDialog->FileName != ExpandedValue)
  1083. {
  1084. ComboBox->Text = OpenDialog->FileName;
  1085. }
  1086. // If user just confirms the initial value, persist it
  1087. else if (ComboBox->Text.IsEmpty())
  1088. {
  1089. DebugAssert(Option.FileInitial == Value);
  1090. ComboBox->Text = Value;
  1091. }
  1092. }
  1093. }
  1094. //---------------------------------------------------------------------------
  1095. THistoryComboBox * __fastcall TCustomCommandOptionsDialog::CreateHistoryComboBox(
  1096. const TCustomCommandType::TOption & Option, const UnicodeString & Value)
  1097. {
  1098. THistoryComboBox * ComboBox = new THistoryComboBox(this);
  1099. ComboBox->AutoComplete = false;
  1100. AddComboBox(ComboBox, CreateLabel(Option.Caption));
  1101. ComboBox->Items = CustomWinConfiguration->History[HistoryKey(Option)];
  1102. ComboBox->Text = Value;
  1103. return ComboBox;
  1104. }
  1105. //---------------------------------------------------------------------------
  1106. UnicodeString __fastcall TCustomCommandOptionsDialog::HistoryKey(const TCustomCommandType::TOption & Option)
  1107. {
  1108. UnicodeString Result = FCommand->GetOptionKey(Option, FSite);
  1109. Result = CustomWinConfiguration->GetValidHistoryKey(Result);
  1110. return L"CustomCommandOption_" + Result;
  1111. }
  1112. //---------------------------------------------------------------------------
  1113. bool __fastcall TCustomCommandOptionsDialog::Execute(TShortCut * ShortCut)
  1114. {
  1115. if (ShortCut != NULL)
  1116. {
  1117. SetShortCutCombo(FShortCutCombo, *ShortCut);
  1118. }
  1119. bool Result = TCustomDialog::Execute();
  1120. if (Result)
  1121. {
  1122. int ControlIndex = 0;
  1123. for (int OptionIndex = 0; OptionIndex < FCommand->OptionsCount; OptionIndex++)
  1124. {
  1125. const TCustomCommandType::TOption & Option = FCommand->GetOption(OptionIndex);
  1126. if ((Option.Flags & FFlags) != 0)
  1127. {
  1128. if ((Option.Kind != TCustomCommandType::okUnknown) &&
  1129. Option.IsControl)
  1130. {
  1131. UnicodeString OptionKey = FCommand->GetOptionKey(Option, FSite);
  1132. TControl * Control = FControls[ControlIndex];
  1133. UnicodeString Value;
  1134. if (Option.Kind == TCustomCommandType::okTextBox)
  1135. {
  1136. Value = SaveHistoryComboBoxValue(Control, Option);
  1137. }
  1138. else if (Option.Kind == TCustomCommandType::okFile)
  1139. {
  1140. Value = SaveHistoryComboBoxValue(Control, Option);
  1141. }
  1142. else if (Option.Kind == TCustomCommandType::okDropDownList)
  1143. {
  1144. Value = GetComboBoxValue(Control, Option.Default);
  1145. }
  1146. else if (Option.Kind == TCustomCommandType::okComboBox)
  1147. {
  1148. TComboBox * ComboBox = DebugNotNull(dynamic_cast<TComboBox *>(Control));
  1149. Value = GetComboBoxValue(Control, ComboBox->Text);
  1150. }
  1151. else if (Option.Kind == TCustomCommandType::okCheckBox)
  1152. {
  1153. TCheckBox * CheckBox = DebugNotNull(dynamic_cast<TCheckBox *>(Control));
  1154. int Index = (CheckBox->Checked ? 0 : 1);
  1155. Value = (Index < static_cast<int>(Option.Params.size())) ? Option.Params[Index] : UnicodeString();
  1156. }
  1157. else
  1158. {
  1159. DebugFail();
  1160. }
  1161. // The default value setter deletes the "name" when the value is empty.
  1162. // It would cause us to fall back to the default value, but we want to remember the empty value.
  1163. SetStringValueEvenIfEmpty(FCustomCommandOptions, OptionKey, Value);
  1164. }
  1165. ControlIndex++;
  1166. }
  1167. }
  1168. if (ShortCut != NULL)
  1169. {
  1170. *ShortCut = GetShortCutCombo(FShortCutCombo);
  1171. }
  1172. }
  1173. return Result;
  1174. }
  1175. //---------------------------------------------------------------------------
  1176. UnicodeString __fastcall TCustomCommandOptionsDialog::GetComboBoxValue(
  1177. TControl * Control, const UnicodeString & Default)
  1178. {
  1179. TComboBox * ComboBox = DebugNotNull(dynamic_cast<TComboBox *>(Control));
  1180. UnicodeString Result;
  1181. if (ComboBox->ItemIndex < 0)
  1182. {
  1183. Result = Default;
  1184. }
  1185. else
  1186. {
  1187. Result = FValues[GetControlIndex(Control)][ComboBox->ItemIndex];
  1188. }
  1189. return Result;
  1190. }
  1191. //---------------------------------------------------------------------------
  1192. UnicodeString __fastcall TCustomCommandOptionsDialog::SaveHistoryComboBoxValue(
  1193. TControl * Control, const TCustomCommandType::TOption & Option)
  1194. {
  1195. THistoryComboBox * ComboBox = DebugNotNull(dynamic_cast<THistoryComboBox *>(Control));
  1196. ComboBox->SaveToHistory();
  1197. CustomWinConfiguration->History[HistoryKey(Option)] = ComboBox->Items;
  1198. return ComboBox->Text;
  1199. }
  1200. //---------------------------------------------------------------------------
  1201. void __fastcall TCustomCommandOptionsDialog::DoHelp()
  1202. {
  1203. UnicodeString HelpPage;
  1204. if (!FCommand->OptionsPage.IsEmpty())
  1205. {
  1206. HelpPage = FCommand->OptionsPage;
  1207. }
  1208. else
  1209. {
  1210. HelpPage = FCommand->HomePage;
  1211. }
  1212. if (!HelpPage.IsEmpty())
  1213. {
  1214. OpenBrowser(HelpPage);
  1215. }
  1216. else
  1217. {
  1218. TCustomDialog::DoHelp();
  1219. }
  1220. }
  1221. //---------------------------------------------------------------------------
  1222. void __fastcall TCustomCommandOptionsDialog::DoShow()
  1223. {
  1224. TCustomDialog::DoShow();
  1225. int ControlIndex = 0;
  1226. for (int OptionIndex = 0; OptionIndex < FCommand->OptionsCount; OptionIndex++)
  1227. {
  1228. const TCustomCommandType::TOption & Option = FCommand->GetOption(OptionIndex);
  1229. if ((Option.Flags & FFlags) != 0)
  1230. {
  1231. if (Option.Kind == TCustomCommandType::okFile)
  1232. {
  1233. TControl * Control = FControls[ControlIndex];
  1234. InstallPathWordBreakProc(DebugNotNull(dynamic_cast<TWinControl *>(Control)));
  1235. }
  1236. ControlIndex++;
  1237. }
  1238. }
  1239. }
  1240. //---------------------------------------------------------------------------
  1241. bool __fastcall DoCustomCommandOptionsDialog(
  1242. const TCustomCommandType * Command, TStrings * CustomCommandOptions, TShortCut * ShortCut,
  1243. unsigned int Flags, TCustomCommand * CustomCommandForOptions,
  1244. const UnicodeString & Site, const TShortCuts * ShortCuts)
  1245. {
  1246. std::unique_ptr<TCustomCommandOptionsDialog> Dialog(
  1247. new TCustomCommandOptionsDialog(Command, CustomCommandOptions, Flags, CustomCommandForOptions, Site, ShortCuts));
  1248. return Dialog->Execute(ShortCut);
  1249. }
  1250. //---------------------------------------------------------------------------
  1251. //---------------------------------------------------------------------------
  1252. class TUsageStatisticsDialog : public TCustomDialog
  1253. {
  1254. public:
  1255. __fastcall TUsageStatisticsDialog();
  1256. protected:
  1257. virtual void __fastcall DoChange(bool & CanSubmit);
  1258. private:
  1259. TEdit * FilterEdit;
  1260. TMemo * UsageMemo;
  1261. TButton * ClipboardButton;
  1262. void __fastcall ClipboardButtonClick(TObject * Sender);
  1263. };
  1264. //---------------------------------------------------------------------------
  1265. __fastcall TUsageStatisticsDialog::TUsageStatisticsDialog() :
  1266. TCustomDialog(HELP_USAGE)
  1267. {
  1268. Caption = LoadStr(USAGE_CAPTION);
  1269. Width = ScaleByTextHeight(this, 400);
  1270. TLabel * Label = new TLabel(this);
  1271. // UnformatMessage is called, because previously, ** markup was used and translations may still contain that
  1272. Label->Caption = UnformatMessage(LoadStr(USAGE_DATA2));
  1273. AddText(Label);
  1274. FilterEdit = new TEdit(this);
  1275. FilterEdit->Width = ScaleByTextHeight(this, 250);
  1276. TLabel * FilterLabel = new TLabel(this);
  1277. FilterLabel->Caption = LoadStr(USAGE_FILTER);
  1278. AddEdit(FilterEdit, FilterLabel, true);
  1279. UsageMemo = new TMemo(this);
  1280. UsageMemo->Height = ScaleByTextHeight(this, 300);
  1281. UsageMemo->ScrollBars = ssVertical;
  1282. AddEdit(UsageMemo, NULL);
  1283. ReadOnlyControl(UsageMemo);
  1284. ClipboardButton = new TButton(this);
  1285. ClipboardButton->Caption = LoadStr(USAGE_COPY);
  1286. ClipboardButton->Width = ScaleByTextHeight(this, 161);
  1287. ClipboardButton->OnClick = ClipboardButtonClick;
  1288. AddDialogButton(ClipboardButton);
  1289. RemoveCancelButton();
  1290. }
  1291. //---------------------------------------------------------------------------
  1292. void __fastcall TUsageStatisticsDialog::ClipboardButtonClick(TObject * /*Sender*/)
  1293. {
  1294. TInstantOperationVisualizer Visualizer;
  1295. CopyToClipboard(UsageMemo->Lines);
  1296. }
  1297. //---------------------------------------------------------------------------
  1298. void __fastcall TUsageStatisticsDialog::DoChange(bool & CanSubmit)
  1299. {
  1300. TCustomDialog::DoChange(CanSubmit);
  1301. UnicodeString Text = Configuration->Usage->Serialize(L"\n", FilterEdit->Text);
  1302. bool NoUsage = Text.IsEmpty();
  1303. ClipboardButton->Enabled = !NoUsage;
  1304. if (NoUsage)
  1305. {
  1306. Text = LoadStr(USAGE_DATA_NONE2);
  1307. }
  1308. UsageMemo->Lines->Text = Text;
  1309. }
  1310. //---------------------------------------------------------------------------
  1311. void __fastcall DoUsageStatisticsDialog()
  1312. {
  1313. std::unique_ptr<TUsageStatisticsDialog> Dialog(new TUsageStatisticsDialog());
  1314. Dialog->Execute();
  1315. }
  1316. //---------------------------------------------------------------------------
  1317. //---------------------------------------------------------------------------
  1318. class TSiteRawDialog : public TCustomDialog
  1319. {
  1320. public:
  1321. __fastcall TSiteRawDialog();
  1322. bool __fastcall Execute(TSessionData * Data);
  1323. protected:
  1324. DYNAMIC void __fastcall DoShow();
  1325. private:
  1326. TMemo * SettingsMemo;
  1327. void __fastcall AddButtonClick(TObject * Sender);
  1328. void __fastcall SettingsMemoKeyDown(TObject * Sender, WORD & Key, TShiftState Shift);
  1329. void DeleteNames(TStrings * Names, TStrings * Options);
  1330. };
  1331. //---------------------------------------------------------------------------
  1332. __fastcall TSiteRawDialog::TSiteRawDialog() :
  1333. TCustomDialog(HELP_SITE_RAW)
  1334. {
  1335. Caption = LoadStr(SITE_RAW_CAPTION);
  1336. Width = ScaleByTextHeight(this, 400);
  1337. SettingsMemo = new TMemo(this);
  1338. SettingsMemo->Height = ScaleByTextHeight(this, 300);
  1339. SettingsMemo->OnKeyDown = SettingsMemoKeyDown;
  1340. AddEdit(SettingsMemo, NULL);
  1341. TButton * AddButton = new TButton(this);
  1342. AddButton->Caption = LoadStr(SITE_RAW_ADD);
  1343. AddButton->Width = OKButton->Width;
  1344. AddButton->OnClick = AddButtonClick;
  1345. AddDialogButton(AddButton);
  1346. }
  1347. //---------------------------------------------------------------------------
  1348. void __fastcall TSiteRawDialog::DoShow()
  1349. {
  1350. TCustomDialog::DoShow();
  1351. InstallPathWordBreakProc(SettingsMemo);
  1352. }
  1353. //---------------------------------------------------------------------------
  1354. bool __fastcall TSiteRawDialog::Execute(TSessionData * Data)
  1355. {
  1356. std::unique_ptr<TSessionData> FactoryDefaults(new TSessionData(L""));
  1357. std::unique_ptr<TSessionData> RawData(new TSessionData(L""));
  1358. RawData->Assign(Data);
  1359. // SFTP-only is not reflected by the protocol prefix, we have to use rawsettings for that
  1360. if (RawData->FSProtocol != fsSFTPonly)
  1361. {
  1362. RawData->FSProtocol = FactoryDefaults->FSProtocol;
  1363. }
  1364. RawData->HostName = FactoryDefaults->HostName;
  1365. RawData->PortNumber = FactoryDefaults->PortNumber;
  1366. RawData->UserName = FactoryDefaults->UserName;
  1367. RawData->Password = FactoryDefaults->Password;
  1368. RawData->Ftps = FactoryDefaults->Ftps;
  1369. std::unique_ptr<TStrings> Options(RawData->SaveToOptions(FactoryDefaults.get(), false, false));
  1370. SettingsMemo->Lines = Options.get();
  1371. bool Result = TCustomDialog::Execute();
  1372. if (Result)
  1373. {
  1374. std::unique_ptr<TSessionData> BackupData(new TSessionData(L""));
  1375. BackupData->Assign(Data);
  1376. Data->DefaultSettings();
  1377. Data->FSProtocol = BackupData->FSProtocol;
  1378. Data->HostName = BackupData->HostName;
  1379. Data->PortNumber = BackupData->PortNumber;
  1380. Data->UserName = BackupData->UserName;
  1381. Data->Password = BackupData->Password;
  1382. Data->Ftps = BackupData->Ftps;
  1383. Data->ApplyRawSettings(SettingsMemo->Lines, false);
  1384. }
  1385. return Result;
  1386. }
  1387. //---------------------------------------------------------------------------
  1388. void __fastcall TSiteRawDialog::SettingsMemoKeyDown(TObject * Sender, WORD & Key, TShiftState Shift)
  1389. {
  1390. MemoKeyDown(Sender, Key, Shift);
  1391. }
  1392. //---------------------------------------------------------------------------
  1393. void __fastcall TSiteRawDialog::AddButtonClick(TObject *)
  1394. {
  1395. std::unique_ptr<TSessionData> FactoryDefaults(new TSessionData(L""));
  1396. std::unique_ptr<TSessionData> BasicData(new TSessionData(L""));
  1397. BasicData->FSProtocol = TFSProtocol(FactoryDefaults->FSProtocol + 1);
  1398. UnicodeString RandomAppendix(L"_");
  1399. BasicData->HostName = FactoryDefaults->HostName + RandomAppendix;
  1400. BasicData->Ftps = TFtps(FactoryDefaults->Ftps + 1);
  1401. BasicData->PortNumber = BasicData->GetDefaultPort() + 1;
  1402. BasicData->UserName = FactoryDefaults->UserName + RandomAppendix;
  1403. BasicData->Password = FactoryDefaults->Password + RandomAppendix;
  1404. std::unique_ptr<TStrings> BasicOptions(BasicData->SaveToOptions(FactoryDefaults.get(), false, false));
  1405. std::unique_ptr<TStrings> AllOptions(TSessionData::GetAllOptionNames(false));
  1406. std::unique_ptr<TStrings> Names(CreateSortedStringList());
  1407. for (int Index = 0; Index < AllOptions->Count; Index++)
  1408. {
  1409. Names->Add(AllOptions->Names[Index]);
  1410. }
  1411. DeleteNames(Names.get(), BasicOptions.get());
  1412. DeleteNames(Names.get(), SettingsMemo->Lines);
  1413. std::unique_ptr<TCustomDialog> AddDialog(new TCustomDialog(HelpKeyword));
  1414. AddDialog->Caption = LoadStr(SITE_RAW_ADD_CAPTION);
  1415. TComboBox * AddComboBox = new TComboBox(AddDialog.get());
  1416. AddComboBox->Style = csDropDownList;
  1417. AddComboBox->DropDownCount = Max(AddComboBox->DropDownCount, 16);
  1418. AddDialog->AddComboBox(AddComboBox, CreateLabel(LoadStr(SITE_RAW_ADD_LABEL)), Names.get(), true);
  1419. AddComboBox->ItemIndex = 0;
  1420. if (AddDialog->Execute())
  1421. {
  1422. UnicodeString Name = AddComboBox->Items->Strings[AddComboBox->ItemIndex];
  1423. UnicodeString Value = AllOptions->Values[Name];
  1424. UnicodeString NameAndSeparator = Name + SettingsMemo->Lines->NameValueSeparator;
  1425. int Start = (SettingsMemo->Lines->Text + NameAndSeparator).Length();
  1426. SettingsMemo->Lines->Add(NameAndSeparator + Value);
  1427. SettingsMemo->SetFocus();
  1428. SettingsMemo->SelStart = Start;
  1429. SettingsMemo->SelLength = Value.Length();
  1430. }
  1431. }
  1432. //---------------------------------------------------------------------------
  1433. void TSiteRawDialog::DeleteNames(TStrings * Names, TStrings * Options)
  1434. {
  1435. for (int Index = 0; Index < Options->Count; Index++)
  1436. {
  1437. UnicodeString Name = Options->Names[Index];
  1438. if (!Name.IsEmpty())
  1439. {
  1440. int I = Names->IndexOf(Name);
  1441. if (I >= 0)
  1442. {
  1443. Names->Delete(I);
  1444. }
  1445. }
  1446. }
  1447. }
  1448. //---------------------------------------------------------------------------
  1449. void __fastcall DoSiteRawDialog(TSessionData * Data)
  1450. {
  1451. std::unique_ptr<TSiteRawDialog> Dialog(new TSiteRawDialog());
  1452. Dialog->Execute(Data);
  1453. }