JohnLM 14 Posted December 22, 2023 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
Remy Lebeau 1393 Posted December 22, 2023 (edited) 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 December 22, 2023 by Remy Lebeau 2 Share this post Link to post
dummzeuch 1505 Posted December 22, 2023 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
JohnLM 14 Posted December 22, 2023 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
mvanrijnen 123 Posted December 22, 2023 (edited) 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 December 22, 2023 by mvanrijnen Share this post Link to post
Remy Lebeau 1393 Posted December 22, 2023 (edited) 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 December 23, 2023 by Remy Lebeau Share this post Link to post
JohnLM 14 Posted December 22, 2023 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
Remy Lebeau 1393 Posted December 23, 2023 (edited) 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 December 23, 2023 by Remy Lebeau 1 Share this post Link to post
David Schwartz 426 Posted December 26, 2023 (edited) 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 December 26, 2023 by David Schwartz Share this post Link to post