Jump to content
JohnLM

Creating a recent folder location list in an INI file

Recommended Posts

I'm building a front-end gui to a dos console app.  And I am utilizing the TIniFile to read/write to a settings.ini file.

 

I need help with ideas of typical methods or algorithms for creating a rolling or recent folder location list, of say, the last 5 folder locations for a 'dos console app' that I call.  The location can be the hdd, flash drive, or another laptop/tablet. The folder locations will be obtained through the FileOpenDialog, so flash drives, mem sticks, etc., could change in a given scenario. 

 

I currently have a small settings.ini file that holds just a few things at the moment, thus..

 

[app settings:]
app path=H:\D11\VCL\Misc\enc_gui\v01\Win32\Debug\
last video src path:=J:\Tools\portable\
last video dst path:=F:\dst\

But I would like to add a recent list of last folder locations for this ini file for where the 'dos console app' will be pickd and stored so that I can extract that from the ini file and load it into a listbox and have a quick pick-list to choose from when I move from one device or folder location.  I sometimes jump from my laptop to my tablet, or throw in a flash/mem drive, and having this quick picklist would work well in my work-flow.  TIA.

Share this post


Link to post

I would do something like this:

[mru]
count=N
path1=...
path2=...
...
pathN=...

Keep adding new paths to the front of the list until the desired count is reached, then remove the oldest path from the end of the list each time a new path is added.

Edited by Remy Lebeau
  • Like 2

Share this post


Link to post
3 hours ago, Remy Lebeau said:

I would do something like this:


[mru]
count=N
path1=...
path2=...
...
pathN=...

Keep adding new paths to the front of the list until the desired count is reached, then remove the oldest path from the end of the list each time a new path is added.

Alternatively omit the Count entry and simply read all entries in the section [mru].

Share this post


Link to post

I have never worked with ini files in Delphi, so this is the first time for me to dive into it, add to that, I want to incorporate a rolling list feature that I have to control with some logic (algo).

Share this post


Link to post
8 hours ago, Remy Lebeau said:

I would do something like this:


[mru]
count=N
path1=...
path2=...
...
pathN=...

Keep adding new paths to the front of the list until the desired count is reached, then remove the oldest path from the end of the list each time a new path is added.

i have a ini helpers for this ....

 

Edited by mvanrijnen

Share this post


Link to post
18 hours ago, dummzeuch said:

Alternatively omit the Count entry and simply read all entries in the section [mru].

I suppose so.

14 hours ago, JohnLM said:

I have never worked with ini files in Delphi, so this is the first time for me to dive into it, add to that, I want to incorporate a rolling list feature that I have to control with some logic (algo).

For example:

procedure TMyForm.FormCreate(Sender: TObject);
begin
  LoadMRUFromINI;
end;

procedure TMyForm.LoadMRUFromINI;
var
  Ini: TIniFile;
  tempMRU: TStringList;
  I: Integer;
begin
  Ini := TIniFile.Create('C:\path\settings.ini');
  try
    tempMRU := TStringList.Create;
    try
      Ini.ReadSectionValues('mru' tempMRU);
      for I := 0 to tempMRU.Count-1 do begin
        AddPathToMRU(tempMRU[I], False);
      end;
    finally
      tempMRU.Free;
    end;
  finally
    Ini.Free;
  end;
end;

procedure TMyForm.SaveMRUToINI;
var
  Ini: TIniFile;
  I: Integer;
begin
  Ini := TIniFile.Create('C:\path\settings.ini');
  try
    Ini.EraseSection('mru');
    for I := 0 to PathsListBox.Items.Count-1 do begin
      Ini.WriteString('mru', 'path'+IntToStr(I+1), PathsListBox.Items[I]);
    end;
    Ini.UpdateFile;
  finally
    Ini.Free;
  end;
end;

procedure TMyForm.AddPathToMRU(const APath: string; AUpdateINI: Boolean = True);
const
  MaxMRUItems = 5;
var
  Idx: Integer;
begin
  while PathsListBox.Items.Count >= MaxMRUItems do begin
    PathsListBox.Items.Delete(PathsListBox.Items.Count-1);
  end;
  Idx := PathsListBox.Items.IndexOf(APath);
  if Idx <> -1 then begin
    PathsListBox.Items.Delete(Idx);
  end;
  PathsListBox.Items.Insert(0, APath);
  if AUpdateINI then
    SaveMRUToINI;
end;

procedure TMyForm.DoSomething;
var
  LPath: string;
  ...
begin
  LPath := ...;
  ...
  AddPathToMRU(LPath);
  ...
end;

 

Edited by Remy Lebeau

Share this post


Link to post

Thanks to dummzeuch for the hint he made: '..read all entries in the section [mru].'

 

I googled and found that there is a function, ReadSectionValue() that I can call and read the values into a list.  But continuing after that point I ran into some roadblocks. I need to check for duplicates and exclude them from being added back into the ini file. I eventually figured that portion out using a TStringList: { setting .sorted:=true } and { setting .duplicates:=dupIgnore }. I don't want the final list sorted, so I will have to maintain another list to keep the original unsorted list for the updated ini file. 

 

Remy I will look into your suggestion(s) for the remaining parts. Thanks. 

 

I will post the finished portions of how I managed it when I figure the rest out. 

 

Share this post


Link to post
3 hours ago, JohnLM said:

I need to check for duplicates and exclude them from being added back into the ini file. I eventually figured that portion out using a TStringList: { setting .sorted:=true } and { setting .duplicates:=dupIgnore }. I don't want the final list sorted, so I will have to maintain another list to keep the original unsorted list for the updated ini file. 

There is a simpler way that doesn't involve keeping a second list.  You can simply read in the INI values into a temporary unsorted TStringList first, and then you can loop through that list adding each entry to the live MRU normally, where the MRU insertion function looks for a duplicate in the live list and if found then removes it before then adding the new entry to the top of the list.  I have updated my earlier example to demonstrate this.

 

Edited by Remy Lebeau
  • Thanks 1

Share this post


Link to post

There's a version of Raize Components in GetIt, and they have an MRUCombobox that uses their INI files logic. You could look at that for some ideas.

 

It's named something like Bonus KSVC 6.2.3 

 

I work with INI files a lot, and there's a file I came across years ago named BigINI.pas that's got a bunch of higher-level functions added to the basic ones. I've added several things to it as well over the years. It makes using INI files a LOT easier!

 

FWIW, the biggest PITA I've found with the basic INI file support is the fact that reading and writing uses different approaches, which is common in lots of places. I tried to add something to this to make it simpler, but it's not quite as robust as I'd like.

 

What I'm referring to is this: you read a value from an INI file to a var somewhat like this:

var myvar := myini.ReadString( 'section_name', 'the_var_name', 'the value' );

 

but you set it like this:

 

myini.WriteString( 'section_name', 'the_var_name', myvar );

 

If you have a bunch of things to read and write, it's not very simple to copy one and paste the code and then edit it to do the opposite.

 

I've been able to get ChatGPT to rewrite this code fairly reliably, but it's just a side-effect of using a language where assignments always are made from right to left. You can moderate that by creating some fancy methods, which is what I tried here at one time, but I'm not happy with the result. Treat them as experimental. 🙂

 

I've attached the file to this message.

 

 

BigIni.pas

Edited by David Schwartz

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×