Fl_preferences inquiry

53 views
Skip to first unread message

anmol....@gmail.com

unread,
Mar 19, 2021, 2:45:12 AM3/19/21
to fltk.general
Hi. I would like to use Fl_preferences as a way to allow the user to change certain aspects of the UI. So, I generate a default prefs file on installation. On later usage, I would like to check if the file already exists and if it does, I would read the new prefs. If it does not, I will write out default prefs.

I can do this with native calls - std::filesystem::exists("file");

However, I have to deal with the full path and that is not a good approach.

Can fltk check if prefs file exists and only write it out if it does not ?

Also, I would like to save the runtime prefs file (different from the default prefs file) and transfer it to another install. Can fltk take a prefs file from a string and write it out ? And can it take the prefs file and read it into a string ?

I am trying to work without knowledge of the actual prefs path, in case it changes in the future.

anmol....@gmail.com

unread,
Mar 19, 2021, 3:23:03 AM3/19/21
to fltk.general
Also, the docs describe a run-time option - A set of Preferences marked "run-time" exists exactly one per application and only as long as the application runs.

Is there an example for this ? I could not figure out how to mark Preferences as run-time.

Philip Rose

unread,
Mar 19, 2021, 5:54:58 AM3/19/21
to fltkg...@googlegroups.com

The way Fl_Preferences seems to work is that if there isn’t a file it creates one, and the first time you “get” a setting, you supply a default value for it. You do not need a default file. I don’t think you need to write the setting back for the file to be written. The file will be in a fixed location depending on OS settings.

 

Phil.

 

--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/6a4a2bc2-7685-4549-94d4-6440d09eba06n%40googlegroups.com.

 

anmol....@gmail.com

unread,
Mar 19, 2021, 7:28:37 AM3/19/21
to fltk.general
Thats the default value we pass in the get() method -
char 

get (const char *entry, int &value, int defaultValue)

Any ideas how the run-time option works ?

Matthias Melcher

unread,
Mar 19, 2021, 8:07:56 AM3/19/21
to fltk.general
Runtime Prefs are a database that works exactly like regular preferences, except that they are not backed by a file. So when the app quits, all data in the database is lost. You access the root entry of the runtime prefs using the constructor FLTK 1.3.5: Fl_Preferences Class Reference with ```nullptr``` as the ```parent``` argument. An untested example would be:

void makePancakes() {
  Fl_Preferences pancakes(nullptr, "Pancakes");
  pancakes.set("Milk", 1);
  pancakes.set("Flour", 1);
  pancakes.set("Sugar", 2);
}
void howToMakeDinner() {
  int cupOfMilk;
  int cupOfFlour;
  int tbspOfSugar;

  Fl_Preferences pancakes(nullptr, "Pancakes");
  pancakes.get("Milk", cupOfMilk, 1);
  pancakes.get("Flour", cupOfFlour, 1);
  pancakes.get("Sugar", tbspOfSugar, 2);
}

If you want to know if a preferences file already existed, you can do this
 int justCreated = 0;
 prefs.get("justCreated", justCreated, 1);
 prefs.set("justCreated", 0);
 if (justCreated) { ... }

But it is not really needed because default values are part of the API anyway.

lifeatt...@gmail.com

unread,
Mar 19, 2021, 10:16:50 AM3/19/21
to fltk.general
>I am trying to work without knowledge of the actual prefs path, in case it changes in the future.
The method Fl_Preferences::getUserdataPath can provide you with the path, so you can use that to deal with location changes.

>Also, I would like to save the runtime prefs file (different from the default prefs file) and transfer it to another install. Can fltk take a prefs file from a string and write it out ? And can it take the prefs file and read it into a string ?

I don't see built-in import/export functions. Others might be able to point to others who have done this.

I think it'd be easier to copy the file - whether that be via the file system, or grabbing the file contents into a buffer.

The preferences file is a set of "groups" containing key/value pairs. You'll want to iterate across the groups and then across the keys. Probably not hard to generate JSON or something ...

Matthias Melcher

unread,
Mar 19, 2021, 10:57:24 AM3/19/21
to fltk.general
lifeatt... schrieb am Freitag, 19. März 2021 um 15:16:50 UTC+1:
>I am trying to work without knowledge of the actual prefs path, in case it changes in the future.
The method Fl_Preferences::getUserdataPath can provide you with the path, so you can use that to deal with location changes.

That method returns a path to a place where userdata can be stored in addition to preferences. It does not reference the preference file itself (however, the paths are almost the same, and the filename can be derived from however the preferences were created). The documentation does not guarantee this. OTOH, the system has not changed in 10+ years either.
 
>Also, I would like to save the runtime prefs file (different from the default prefs file) and transfer it to another install. Can fltk take a prefs file from a string and write it out ? And can it take the prefs file and read it into a string ?
I don't see built-in import/export functions. Others might be able to point to others who have done this.

No, there is no provision for that.  Also, there is a misunderstanding between "runtime prefs" and "prefs files". Preferences files are usually only read or written in a very brief period, for example a subroutine, to gather or change aspects of the UI. For example, you would read the preferences once to find out where the user wants his window. You should not leave the preferences item allocated.

When the user closes the app, you again briefly open the preferences database, write your changes (no need to write anything else), for example, where was the window, when the user closed it, and then close the database again. This will all be stored in a file on disk in a simple Windows config file kind of format. Don't keep references to an Fl_Preferences instance around outside of a simple subroutine.

"Runtime Preferences" are a database that uses the same calls to read and write structured data, however, it is not linked to a file. So whenever the app crashes or exits, your data is lost. It can't be copied or redirected to a file. It was originally planned to support plugins for Fluid. 
 
The preferences file is a set of "groups" containing key/value pairs. You'll want to iterate across the groups and then across the keys. Probably not hard to generate JSON or something ...

Yes, you can iterate through the entire database. Data/value pairs are untyped, so reading into a char* buffer and writing that back into another database will preserve all information. I had an implementation for XML and JSON, but the Fl_Preferences API is less than ideal for accessing those formats, and the feature is definitely beyond the scope of a UI library. There are great cross-platform JSON and XML libraries out there for free.

Untested:


copyGroup(Fl_Preferences &src, Fl_Preferences &dst)
{
  for (int i=0; i<src.groups(), ++i) {
    Fl_Preferences s(src, i);
    Fl_Preferences d(dst, s->name());
    copyGroup(s, d);
  }
  for (int i=0; i<src.entries(); ++i) {
    char *name = src.entry(i);
    char *data;
    src.get(name, data, "");
    dst.set(name, data);
    ::free(data);
  }
}

copyPrefs() {
  Fl_Preferences srcFile(Fl_Preferences::USER, "fltk.org", "Hello");
  Fl_Preferences dstFile("/Users/matt/test.cfg", "matthiasm.com", "export");
  copyGroup(srcFile, dstFile);
}

lifeatt...@gmail.com

unread,
Mar 19, 2021, 11:08:46 AM3/19/21
to fltk.general
>"Runtime Preferences" are a database that uses the same calls to read and write structured data, however, it is not linked to a file. So whenever the app crashes or exits, your data is lost. It can't be copied or redirected to a file. It was originally planned to support plugins for Fluid. 

My thanks for the clarification. That makes sense to me - easy to use the "preferences" mechanism to maintain "current state". Or, e.g. with plugins, the currently available entities which are subject to change and require re-scanning on every startup.

Squirting runtime preferences between running apps might allow app instances to get "in sync". Interesting idea.

Philip Rose

unread,
Mar 19, 2021, 11:25:20 AM3/19/21
to fltkg...@googlegroups.com

From: 'Matthias Melcher' via fltk.general
Sent: 19 March 2021 14:57
To: fltk.general
Subject: [fltk.general] Re: Fl_preferences inquiry

 

, there is no provision for that.  Also, there is a misunderstanding between "runtime prefs" and "prefs files". Preferences files are usually only read or written in a very brief period, for example a subroutine, to gather or change aspects of the UI. For example, you would read the preferences once to find out where the user wants his window. You should not leave the preferences item allocated.

 

When the user closes the app, you again briefly open the preferences database, write your changes (no need to write anything else), for example, where was the window, when the user closed it, and then close the database again. This will all be stored in a file on disk in a simple Windows config file kind of format. Don't keep references to an Fl_Preferences instance around outside of a simple subroutine.

 

I had assumed that when you create the Fl_Preferences item at the start of the app it reads all the file into a local data structure and when the app closes it writes it back. I use the Fl_Preferences item throughout the existence of the app. It does not appear to update the file after every call to set(). I’ve had to explicitly use flush() for information I want to preserve after a crash.

anmol....@gmail.com

unread,
Mar 19, 2021, 11:31:09 AM3/19/21
to fltk.general
The copyGroup example copies from one group to another - basically one file to another. I may need to store the preferences to keep the state between different computers. In this case, copying the entire file to a string is my best option. Is there a way that the prefs file can be copied to a string and then restored on another computer ?

As an example, if you use fltk to create a plugin, the state of your plugin will be saved along with the app. Now if the user opens the project file elsewhere, the fltk state also has to be restored.

pvr...@btinternet.com

unread,
Mar 19, 2021, 11:52:31 AM3/19/21
to fltk.general
I have just looked in the source for Fl_Preferences, and the constructor reads the file in then closes it, the destructor, opens it and writes it back, if the data structure is dirty.

Phil.
Reply all
Reply to author
Forward
0 new messages