Recent

Author Topic: TSaveDialog, ofOverwritePrompt, DefaultExt  (Read 1702 times)

linuxfan

  • Jr. Member
  • **
  • Posts: 60
TSaveDialog, ofOverwritePrompt, DefaultExt
« on: January 14, 2024, 09:10:08 am »
Hello,

I find TSaveDialog has an inconsistency or perhaps a bug, at least under linux (never tried elsewhere). When DefaultExt is set, say, to ".txt", and the option ofOverwritePrompt is on, a user can write for example "atextfile" in the file name (first field of the dialog) and press Enter. If a file "atextfile.txt" exists, NO overwrite warning is triggered by the dialog. The application receives the filename, and overwrites it.

So I implemented my own overwrite check in pascal code. BUT now, if I want to overwrite an existing file, I receive TWO warnings, one from the dialog, and one from my program. Given this, I should unset the ofOverwritePrompt, now useless.

What happens is, I think, that TSaveDialog FIRST checks for overwriting, THEN appends the default extension specified in the properties. If it is so, then it is probably a bug.


dsiders

  • Hero Member
  • *****
  • Posts: 1496
Re: TSaveDialog, ofOverwritePrompt, DefaultExt
« Reply #1 on: January 14, 2024, 02:50:13 pm »
Hello,

I find TSaveDialog has an inconsistency or perhaps a bug, at least under linux (never tried elsewhere). When DefaultExt is set, say, to ".txt", and the option ofOverwritePrompt is on, a user can write for example "atextfile" in the file name (first field of the dialog) and press Enter. If a file "atextfile.txt" exists, NO overwrite warning is triggered by the dialog. The application receives the filename, and overwrites it.

So I implemented my own overwrite check in pascal code. BUT now, if I want to overwrite an existing file, I receive TWO warnings, one from the dialog, and one from my program. Given this, I should unset the ofOverwritePrompt, now useless.

What happens is, I think, that TSaveDialog FIRST checks for overwriting, THEN appends the default extension specified in the properties. If it is so, then it is probably a bug.

I cannot reproduce this on Windows.

Using the following:

Code: Pascal  [Select][+][-]
  1.   // filename.txt already exists
  2.   Dlg := TSaveDialog.Create(Nil);
  3.   with Dlg do
  4.   begin
  5.     InitialDir := ExtractFilePath(Application.ExeName);
  6.     Options := [ofOverwritePrompt];
  7.     DefaultExt := '.txt';
  8.     // FileName := 'filename';
  9.     Execute;
  10.     if ModalResult= mrOK then
  11.       ShowMessage(FileName);
  12.     Free;
  13.   end;
  14.  

It generates the "Confirm Save As" overwrite prompt as expected.
Preview the next Lazarus documentation release at: https://dsiders.gitlab.io/lazdocsnext

paweld

  • Hero Member
  • *****
  • Posts: 1525
Re: TSaveDialog, ofOverwritePrompt, DefaultExt
« Reply #2 on: January 14, 2024, 03:24:39 pm »
Confirm error on Linux (on Windows is OK). Latest Lazarus 3.99 and FPC 3.2.3 x64.
Sample code (put TButton and TSaveDialog on form):
Code: Pascal  [Select][+][-]
  1. var
  2.   sl: TStringList;
  3. begin
  4.   SaveDialog1.DefaultExt := '.txt';
  5.   SaveDialog1.Options := SaveDialog1.Options + [ofOverwritePrompt];
  6.   sl := TStringList.Create;
  7.   sl.Add('test');
  8.   SaveDialog1.FileName := 'test';
  9.   if SaveDialog1.Execute then
  10.     sl.SaveToFile(SaveDialog1.FileName);
  11.   sl.free;
Best regards / Pozdrawiam
paweld

Bart

  • Hero Member
  • *****
  • Posts: 5649
    • Bart en Mariska's Webstek
Re: TSaveDialog, ofOverwritePrompt, DefaultExt
« Reply #3 on: January 14, 2024, 03:42:03 pm »
IIRC then this is already a known issue.

[edit]
issue #38885
[/edit]

Bart
« Last Edit: January 14, 2024, 04:02:55 pm by Bart »

Bart

  • Hero Member
  • *****
  • Posts: 5649
    • Bart en Mariska's Webstek
Re: TSaveDialog, ofOverwritePrompt, DefaultExt
« Reply #4 on: January 14, 2024, 04:15:59 pm »
IIRC then this is caused by the fact that the native GTK2 dialog does not have a DefaultExt property.
So the default extension is applied after the dialog has returned on this WS.
The overwrite prompt dialog is launched by the WS itself and if you reject the filename, you return to the file dialog.
As far as the WS is concerned you entered the filname without extension, and that file does not exist, so it did not prompt you.
Now the LCL adds the default extension and that file actually exists in your case.

I don't think the behaviour of Windows (dialog stays open if you reject the filename) can be achieved on other widgetsets.
The situation can be detected before returning the result of the dialog (I think), either in LCL or in WS code (need to look into that).
But what to do then?
Launch another dialog and if user rejects the filename re-launch the dialog?
Fire some event (or set a flag) to info the programmer that such a condition exists?

Bart

Bart

  • Hero Member
  • *****
  • Posts: 5649
    • Bart en Mariska's Webstek
Re: TSaveDialog, ofOverwritePrompt, DefaultExt
« Reply #5 on: January 14, 2024, 04:37:47 pm »
The logic is in function TOpenDialog.CheckFile in ($lazarus)/lcl/include/filedialog.inc.
If this function returns False, the Execute method of the dialog will return False.

In your use-case you would not want it to return False (meaning the user cancelled file-saving) I guess.

Bart

linuxfan

  • Jr. Member
  • **
  • Posts: 60
Re: TSaveDialog, ofOverwritePrompt, DefaultExt
« Reply #6 on: January 15, 2024, 07:02:21 am »
I think that the best solution would be to re-launch the dialog, if the user refuses the file name; asking again for a file name, even if this seems not too elegant in GTK.

I say so, mainly, because if one develops a program under windows, and then ports it elsewhere (linux), the application behaves the same.


Bart

  • Hero Member
  • *****
  • Posts: 5649
    • Bart en Mariska's Webstek
Re: TSaveDialog, ofOverwritePrompt, DefaultExt
« Reply #7 on: January 15, 2024, 06:21:04 pm »
I think that the best solution would be to re-launch the dialog, if the user refuses the file name; asking again for a file name, even if this seems not too elegant in GTK.

Well, that might be a little complicated, since at this point we are in the Execute method...

Bart

 

TinyPortal © 2005-2018