Custom.cpp 52 KB

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