User Tools

Site Tools


pcb:preferences_subsystem

This is an old revision of the document!


Presently there are a couple. There’s GTK has one, and of course there’s the one that loads command line preferences. There’s also the menu system, which could be considered a preferences system.

I’d like to centralize this system so that other parts of the code can take advantage of it.

Several ideas come to mind about how to do this.

Requirements: The system should be able to interact with specified preferences files. This allows subsystems to create their own if they want. It will also allow the user to specify such a file at startup. The system should manage the reading and writing of the files transparently. We don’t want developers to have to think too hard about how this works. The system should not put constraints on what can be contained by the preference. It should be allowed to be anything. Ultimately it’s a string when it’s stored and read, but it should be convertible into any data type. The files should be human readable. There’s an interesting question here about locales…

Thoughts on format: 1 preference per line. First word on the line (everything up to the first white space) is the name of the preference. Everything after the first word is the value of the preference.

Somehow the file needs to delimit different preferences. Using lines seems like the natural thing to do, but this would preclude multiline strings. Perhaps that’s okay? I’m going to go with that for now.

Thoughts on processing: I’d like to use function pointers for this purpose. That way subsystems can implement special converters if they want to.

I’ve also considered if there should be some type of hierarchical structure. Like for example, subsystems could register prefixes like “gtk-” with the system, and then the system passes them the preferences with that prefix. With the function calling system, I don’t think this is necessary. Although it is a good idea for subsystems to use such a prefix to make editing the files easier.

Thoughts on implementation: There is a preference index structure (probably an object list) that contains: The index (name) of the preference This is a string that identifies it. Help text This is perhaps a carry over from the old systems, but is possibly a good idea. It’s original purpose was for generating the help text on the command line. The function that should take the string and make it useful (reader) There will be several standard “readers” for things like floats, integers, strings, etc. This function should also *assign* the converted value to a data structure. What the return value is remains open for discussion. The prototype will be something like: void pref_float(char* index_str, char* input_str, void* ptr) The function that should take the value and make it a string (writer) Again, there will be several standard writers for various standard types. The prototype will be something like: char* float_pref(index_str, ptr) A user pointer This is what gets passed to the functions in the ptr slot A default value This should be a *string* that can be an input to the reader function.

typedef struct { char * name; char * help_text; void (*reader)(char *, char *, void *); void (*writer)(char *, void *); void * ptr; char * default_str; } PreferenceItem

The pointer is probably often going to be the item that should be populated with the preference value, but doesn’t have to be. It could be the general preferences structure, for example, if there’s more than one parameter that needs to be updated.

Implement several “default” handlers: pref_float, pref_integer, pref_double, pref_coord… etc that take the preference value, convert into whatever type, and then assign. Similarly several default “writers” will be needed.

Then we’ll create an object list of these preference items. It will have to be initialized early in the startup process, before processing the preference related command line arguments.

There will be a function for reading a preferences file, and a function for writing a preferences file.

void read_pref_file (char * fname) { FILE * fp; /* open the file for reading */ }

/* void pref_float (char * index_str, char * input_str, void *ptr) * This function takes an input string, converts it to a float, and assigns it to ptr. * Return type is void only because I haven’t figured out what to do with it, or to remind you * that you have to set the value with the function. */ void pref_float (index_str, input_str, ptr) {

/* this function doesn’t care about index_str */
float fval = 0, *fptr=0;
fptr = (float*) ptr; /* cast the pointer as a float */
fval = atof(input_str); /* do the ascii to float conversion*/
/* do any checking to see if it worked? */
*fptr = fval;
/* return 0; */

}

/* char * float_pref(index_str, float fval) * This function takes an input float and converts it to a string for storage in a preferences file. * The caller owns the string memory that the result is stored in. * Should the float be a pointer to a float, or the float value itself? */ char * float_pref (index_str, float fval) {

char tstr[128]; /* This ought to be big enough for anything we’re going to realistically throw at it. */
char * fstr;
int len = 0;
len = sprintf(fstr, “%f”, fval);
fstr = malloc(len+1); /* allocate a buffer that’s exactly the right size */
strncpy(fstr, tstr, len); /* copy the new string into it */
fstr[len] = ‘\0’;
return fstr;

}

Questions: If a user loads a new preferences file, does it need to notify anything that this happened? Presently, with preferences, values are updated immediately. This means that all preferences need to be such that changing them at any given moment doesn’t lead to disaster. However, this model also provides the flexibility that, if there isn’t such a preference, it can specify its own handler function which could take care of any of the necessary tasks to enact the change.

pcb/preferences_subsystem.1593373697.txt.gz · Last modified: 2020/06/28 15:48 by cparker