feat: prevent loading an SQL file multiple times into an editor

Shows an information dialog when a loaded file is being selected again through the various load-file mechanism: load-file dialog, recent files menu, dropping on editor, passing on command line

Refs #1403
This commit is contained in:
Ansgar Becker
2026-02-25 20:10:21 +01:00
parent 86a96bd5b2
commit 153e61d654
2 changed files with 58 additions and 36 deletions

View File

@@ -37,6 +37,7 @@ type
TStringsHelper = class helper for TStrings
public
function Contains(const S: String): Boolean;
function IsEmpty: Boolean;
end;
const
@@ -251,5 +252,10 @@ begin
Result := IndexOf(S) >= 0;
end;
function TStringsHelper.IsEmpty: Boolean;
begin
Result := Count = 0;
end;
end.

View File

@@ -1324,6 +1324,7 @@ type
procedure SetSnippetFilenames;
function TreeClickHistoryPrevious(MayBeNil: Boolean=False): PVirtualNode;
procedure OperationRunning(Runs: Boolean);
procedure OpenQueryFiles(Filenames: TStrings; Encoding: TEncoding; ForceRun: Boolean);
function RunQueryFiles(Filenames: TStrings; Encoding: TEncoding; ForceRun: Boolean): Boolean;
function RunQueryFile(Filename: String; Encoding: TEncoding; Conn: TDBConnection;
FilesizeSum: Int64; var CurrentPosition: Int64): Boolean;
@@ -2143,7 +2144,6 @@ var
StatsCall: THttpDownload;
StatsURL: String;
SessionPaths: TStringlist;
Tab: TQueryTab;
begin
// Check for connection parameters on commandline or show connections form.
if AppSettings.ReadBool(asUpdatecheck) then begin
@@ -2259,14 +2259,7 @@ begin
end;
// Load SQL file(s) by command line
if not RunQueryFiles(FileNames, nil, false) then begin
for i:=0 to FileNames.Count-1 do begin
Tab := GetOrCreateEmptyQueryTab(False);
Tab.LoadContents(FileNames[i], True, nil);
if i = FileNames.Count-1 then
SetMainTab(Tab.TabSheet);
end;
end;
OpenQueryFiles(FileNames, nil, False);
MainFormAfterCreateDone := True;
end;
@@ -3936,10 +3929,9 @@ end;
// Load SQL-file, make sure that SheetQuery is activated
procedure TMainForm.actLoadSQLExecute(Sender: TObject);
var
i, ProceedResult: Integer;
ProceedResult: Integer;
Dialog: TExtFileOpenDialog;
Encoding: TEncoding;
Tab: TQueryTab;
begin
AppSettings.ResetPath;
Dialog := TExtFileOpenDialog.Create(Self);
@@ -3961,14 +3953,7 @@ begin
end;
if ProceedResult = mrYes then begin
if not RunQueryFiles(Dialog.Files, Encoding, Sender=actRunSQL) then begin
for i:=0 to Dialog.Files.Count-1 do begin
Tab := GetOrCreateEmptyQueryTab(False);
Tab.LoadContents(Dialog.Files[i], True, Encoding);
if i = Dialog.Files.Count-1 then
SetMainTab(Tab.TabSheet);
end;
end;
OpenQueryFiles(Dialog.Files, Encoding, Sender=actRunSQL);
end;
AppSettings.WriteInt(asFileDialogEncoding, Dialog.EncodingIndex, Self.Name);
end;
@@ -3976,6 +3961,51 @@ begin
end;
procedure TMainForm.OpenQueryFiles(Filenames: TStrings; Encoding: TEncoding; ForceRun: Boolean);
var
Tab, FileInTab: TQueryTab;
FileHints: TStringList;
i: Integer;
begin
// Decides whether to run or load files, prevents duplicates etc.
if RunQueryFiles(Filenames, Encoding, ForceRun) then
Exit;
FileHints := TStringList.Create;
for i:=0 to Filenames.Count-1 do begin
FileInTab := nil;
for Tab in QueryTabs do begin
if Tab.MemoFilename = Filenames[i] then begin
FileInTab := Tab;
FileHints.Add(f_('This file is already open in query tab #%d.', [FileInTab.Number]) + ' ' + ExtractFileName(Filenames[i]));
if i = Filenames.Count-1 then
SetMainTab(FileInTab.TabSheet);
Break;
end;
end;
if not Assigned(FileInTab) then begin
Tab := GetOrCreateEmptyQueryTab(False);
Tab.LoadContents(Filenames[i], True, Encoding);
if i = Filenames.Count-1 then
SetMainTab(Tab.TabSheet);
end;
end;
if not FileHints.IsEmpty then begin
if MainFormAfterCreateDone then
MessageDialog(FileHints.Text, mtInformation, [mbOK])
else begin
for i:=0 to FileHints.Count-1 do
LogSQL(FileHints[i]);
end;
end;
FileHints.Free;
end;
function TMainForm.RunQueryFiles(Filenames: TStrings; Encoding: TEncoding; ForceRun: Boolean): Boolean;
var
i, FilesProcessed: Integer;
@@ -5189,7 +5219,6 @@ var
Filename: String;
FileList: TStringList;
p: Integer;
Tab: TQueryTab;
begin
// Click on the popupQueryLoad
Filename := (Sender as TMenuItem).Caption;
@@ -5202,10 +5231,7 @@ begin
end;
FileList := TStringList.Create;
FileList.Add(Filename);
if not RunQueryFiles(FileList, nil, false) then begin
Tab := GetOrCreateEmptyQueryTab(True);
Tab.LoadContents(Filename, True, nil);
end;
OpenQueryFiles(FileList, nil, False);
FileList.Free;
end;
@@ -7769,12 +7795,7 @@ begin
// query-memo - load their contents into seperate tabs
Files := TStringList.Create;
Files.AddStrings(FileNames);
if not RunQueryFiles(Files, nil, False) then begin
for i:=0 to Files.Count-1 do begin
Tab := GetOrCreateEmptyQueryTab(True);
Tab.LoadContents(Files[i], False, nil);
end;
end;
OpenQueryFiles(Files, nil, False);
Files.Free;
end;
@@ -13637,12 +13658,7 @@ begin
LogSQL(f_('Preventing second application instance - disabled in %s > %s > %s.', [_('Tools'), _('Preferences'), _('General')]), lcInfo);
ConnectionParams := nil;
ParseCommandLine(ParamBlobToStr(Msg.CopyDataStruct.lpData), ConnectionParams, FileNames, RunFrom);
if not RunQueryFiles(FileNames, nil, False) then begin
for i:=0 to FileNames.Count-1 do begin
Tab := GetOrCreateEmptyQueryTab(True);
Tab.LoadContents(FileNames[i], True, nil);
end;
end;
OpenQueryFiles(FileNames, nil, False);
if ConnectionParams <> nil then
InitConnection(ConnectionParams, True, Connection);
end else