Page 3 of 4

Re: PrefsObject

Posted: Sat Sep 19, 2015 6:48 pm
by jaokim
I don't have much application library knowledge, so I don't know which six types there are. But, if I'm allowed to elaborate, I'm thinking one might want to support more types in the future. Therefore I think that an attribute would be better suited... Although, on the other hand, we'd get a less "typed" and uncontrolled structure.
My thought was that one would perhaps want, as an application programmer, to store application specific "blobs", with some sort of XML CDATA thingie, especially wen porting software. I'm imagining that the ported program has its own binary format, which we then could save using minimal Amiga application specific code, but still take advantage of Amiga specific functionality.

Like I said, I don't have any deep insight in exactly what application library supports for the prefs objects, so I might be proposing unsuitable stuff.

But either way, I'd prefer a format where the data type is an attribute, and not a static tag.

Re: PrefsObject

Posted: Sat Sep 19, 2015 7:06 pm
by trixie
@jaokim
I don't have much application library knowledge, so I don't know which six types there are.
See here:
http://wiki.amigaos.net/wiki/PrefsObjects#Object_Types

Re: PrefsObject

Posted: Mon Oct 05, 2015 6:46 pm
by mritter0
I haven't heard back from my PM to Trixie on getting some example code. Does anyone have an example to get me started?

Re: PrefsObject

Posted: Mon Oct 05, 2015 8:58 pm
by javierdlr
Not sure if its what you want, but I use an XML file to store Mixer.docky prefs (SoundVolume and Mute), here it's a snnipet:

XML looks like this:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pobjects PUBLIC "-//Amiga Inc.//DTD POBJECTS 1.0//EN" "http://www.amiga.com/DTDs/PrefsObjects-1.0.dtd">
<pobjects version="1.0">
<dict>
	<key>Volume-Mute</key>
	<array>
		<integer>100</integer>
		<bool>FALSE</bool>
		<integer>100</integer>
		<bool>FALSE</bool>
		<integer>100</integer>
		<bool>FALSE</bool>
		<integer>100</integer>
		<bool>FALSE</bool>
	</array>
</dict>
</pobjects>
And source for reading such xml:

Code: Select all

extern uint32 sliderVal[SC_MAX];
extern BOOL buttonMute[SC_MAX];
...
void ReadXMLcfg(char *filename, struct DockyData *dd)
{
 PrefsObject *dict;
 uint32 err = 0;

 dict = IPrefsObjects->PrefsDictionary(NULL, NULL, ALPO_Alloc,0, TAG_DONE);

 err = IPrefsObjects->ReadPrefs(dict, READPREFS_FileName,(ULONG)filename, TAG_DONE);
 if(err!=0 && err!=ALPOEF_FILEERROR)
  DoMessage("Warning: Can't read/load XML settings.", REQIMAGE_WARNING, dd);
 else
 {
  PrefsObject *soundcard = IPrefsObjects->DictGetObjectForKey(dict, "Volume-Mute");
  if(soundcard)
  {
   int32 count;
   struct ALPOObjIndex oi;

   IPrefsObjects->PrefsArray(soundcard, NULL, ALPOARR_GetCount,&count, TAG_DONE);
   for(oi.index = 0; oi.index < count; oi.index++)
   {
    IPrefsObjects->PrefsArray(soundcard, NULL, ALPOARR_GetObjAtIndex,&oi, TAG_DONE);
    if(oi.obj)
    {
     int32 vol;
     BOOL mut;
//IDOS->Printf("[XML]object %2ld: ",oi.index);
     IPrefsObjects->PrefsNumber(oi.obj, &err, ALPONUM_GetLong,&vol, TAG_DONE);
     if(!err)
      sliderVal[oi.index>>1] = vol;

     oi.index++;
     IPrefsObjects->PrefsArray(soundcard, NULL, ALPOARR_GetObjAtIndex,&oi, TAG_DONE);
     IPrefsObjects->PrefsNumber(oi.obj, &err, ALPONUM_GetBool,&mut, TAG_DONE);
     if(!err)
      buttonMute[oi.index>>1] = mut;
//IDOS->Printf("[R:%ld]sliderVal=%ld buttonMute=%ld\n",oi.index>>1,sliderVal[oi.index>>1],buttonMute[oi.index>>1]);
    }
   }
  } // END soundcard
 }
 IPrefsObjects->PrefsDictionary(dict, NULL, ALPO_Release,0, TAG_DONE);
}
(full sources are Mixer archive(openamiga, os4depot)

Re: PrefsObject

Posted: Tue Oct 06, 2015 2:49 pm
by trixie
@mritter0
mritter0 wrote:I haven't heard back from my PM to Trixie on getting some example code. Does anyone have an example to get me started?
Sorry I forgot to check my PM. Was the current example in the wiki not enough? The easiest way is really to register your app with REGAPP_LoadPrefs, TRUE, get the prefs dictionary object via GetApplicationAttrs(), and then manipulate the settings via the respective getter functions - DictGetBoolForKey(), DictGetIntegerForKey() etc. Values are set using DictSetObjectForKey(). Saving to the XML file is done through WritePrefs().

What Javier is suggesting is an alternative: you allocate your own prefs dictionary through PrefsDictionary() and then ReadPrefs() into it. The rest is pretty much the same.

I'm still working on improving the wiki page but it takes time, unfortunately :(

EDIT: This is what I use in WordNet to load/save settings:

Code: Select all

int load_settings(uint32 appID)
{
 PrefsObject *prefsObj = NULL;

 // Obtain the prefs dictionary.
 IApplication->GetApplicationAttrs(appID, APPATTR_MainPrefsDict, &prefsObj, TAG_DONE);

 if ( prefsObj )
  {
   // Load prefs (or use defaults).
   settings.width      = IPrefsObjects->DictGetIntegerForKey(prefsObj, PREFSKEY_WINWIDTH, WINWIDTH_DEFAULT);
   settings.height     = IPrefsObjects->DictGetIntegerForKey(prefsObj, PREFSKEY_WINHEIGHT, WINHEIGHT_DEFAULT);
   settings.histlen    = IPrefsObjects->DictGetIntegerForKey(prefsObj, PREFSKEY_HISTLEN, HISTLEN_DEFAULT);
   settings.lingmode   = IPrefsObjects->DictGetBoolForKey(prefsObj, PREFSKEY_LINGMODE, LINGMODE_DEFAULT);
   settings.fulldesc   = IPrefsObjects->DictGetBoolForKey(prefsObj, PREFSKEY_FULLDESC, FULLDESC_DEFAULT);
   settings.unfold     = IPrefsObjects->DictGetBoolForKey(prefsObj, PREFSKEY_UNFOLD, UNFOLD_DEFAULT);
   settings.dclick     = IPrefsObjects->DictGetBoolForKey(prefsObj, PREFSKEY_DCLICK, DCLICK_DEFAULT);
   settings.showfreq   = IPrefsObjects->DictGetBoolForKey(prefsObj, PREFSKEY_SHOWFREQ, SHOWFREQ_DEFAULT);
   settings.escquit    = IPrefsObjects->DictGetBoolForKey(prefsObj, PREFSKEY_ESCQUIT, ESCQUIT_DEFAULT);
   settings.helptips   = IPrefsObjects->DictGetBoolForKey(prefsObj, PREFSKEY_HELPTIPS, HELPTIPS_DEFAULT);

   return RETURN_OK;
  }

 else return RETURN_FAIL;
}



int save_settings(uint32 appID)
{
 PrefsObject *prefsObj    = NULL;
 int          retValue    = RETURN_FAIL;

 // Obtain the prefs dictionary.
 IApplication->GetApplicationAttrs(appID, APPATTR_MainPrefsDict, &prefsObj, TAG_DONE);

 if ( prefsObj )
  {
   IPrefsObjects->DictSetObjectForKey(prefsObj, IPrefsObjects->PrefsNumber(NULL, NULL,
         ALPONUM_AllocSetLong, settings.width,
         TAG_DONE), PREFSKEY_WINWIDTH);
   IPrefsObjects->DictSetObjectForKey(prefsObj, IPrefsObjects->PrefsNumber(NULL, NULL,
         ALPONUM_AllocSetLong, settings.height,
         TAG_DONE), PREFSKEY_WINHEIGHT);
   IPrefsObjects->DictSetObjectForKey(prefsObj, IPrefsObjects->PrefsNumber(NULL, NULL,
         ALPONUM_AllocSetLong, settings.histlen,
         TAG_DONE), PREFSKEY_HISTLEN);
   IPrefsObjects->DictSetObjectForKey(prefsObj, IPrefsObjects->PrefsNumber(NULL, NULL,
         ALPONUM_AllocSetBool, settings.lingmode,
         TAG_DONE), PREFSKEY_LINGMODE);
   IPrefsObjects->DictSetObjectForKey(prefsObj, IPrefsObjects->PrefsNumber(NULL, NULL,
         ALPONUM_AllocSetBool, settings.fulldesc,
         TAG_DONE), PREFSKEY_FULLDESC);
   IPrefsObjects->DictSetObjectForKey(prefsObj, IPrefsObjects->PrefsNumber(NULL, NULL,
         ALPONUM_AllocSetBool, settings.unfold,
         TAG_DONE), PREFSKEY_UNFOLD);
   IPrefsObjects->DictSetObjectForKey(prefsObj, IPrefsObjects->PrefsNumber(NULL, NULL,
         ALPONUM_AllocSetBool, settings.dclick,
         TAG_DONE), PREFSKEY_DCLICK);
   IPrefsObjects->DictSetObjectForKey(prefsObj, IPrefsObjects->PrefsNumber(NULL, NULL,
         ALPONUM_AllocSetBool, settings.showfreq,
         TAG_DONE), PREFSKEY_SHOWFREQ);
   IPrefsObjects->DictSetObjectForKey(prefsObj, IPrefsObjects->PrefsNumber(NULL, NULL,
         ALPONUM_AllocSetBool, settings.escquit,
         TAG_DONE), PREFSKEY_ESCQUIT);
   IPrefsObjects->DictSetObjectForKey(prefsObj, IPrefsObjects->PrefsNumber(NULL, NULL,
         ALPONUM_AllocSetBool, settings.helptips,
         TAG_DONE), PREFSKEY_HELPTIPS);
   IPrefsObjects->DictSetObjectForKey(prefsObj, IPrefsObjects->PrefsString(NULL, NULL,
         ALPOSTR_AllocSetString, settings.homepage,
         TAG_DONE), PREFSKEY_HOMEPAGE);
   IPrefsObjects->DictSetObjectForKey(prefsObj, IPrefsObjects->PrefsString(NULL, NULL,
         ALPOSTR_AllocSetString, settings.docfile,
         TAG_DONE), PREFSKEY_DOCFILE);

      // Write preferences.
   if ( IPrefsObjects->WritePrefs(prefsObj,
         WRITEPREFS_AppID, appID,
         WRITEPREFS_WriteENVARC, TRUE,
         TAG_DONE) == 0 ) retValue = RETURN_OK;
  }

 return retValue;
}

Re: PrefsObject

Posted: Wed Oct 07, 2015 2:03 am
by mritter0
Thanks guys. The loading code on the wiki doesn't do me any good if I can't save my prefs first. ;)

I would still like to see a fully loaded example that saves/loads a complicated prefs file. As in, Screen settings grouped, Window settings grouped, etc. Not just a straight list of items.

This will get me started.

Re: PrefsObject

Posted: Wed Oct 07, 2015 2:16 am
by mritter0
Now I am going to get nit-picky:

To be consistent across applications, what is the prefs filename extension? Xxxx.prefs or Xxxxx.xml

I already see a mix of the two. I like .xml. Pick one, Style Guide maintainer. :P

Re: PrefsObject

Posted: Wed Oct 07, 2015 12:41 pm
by broadblues
#?.prefs ofcourse you don't call older prefs formats in IFF #?.iff

But it doesn't matter really.

Re: PrefsObject

Posted: Wed Oct 07, 2015 3:10 pm
by trixie
@mritter0
mritter0 wrote:To be consistent across applications, what is the prefs filename extension? Xxxx.prefs or Xxxxx.xml
The Application Library uses .xml by default.
I would still like to see a fully loaded example that saves/loads a complicated prefs file. As in, Screen settings grouped, Window settings grouped, etc. Not just a straight list of items. This will get me started.
This is why it's important to specify what exactly you are after. If you say things like "to get me started", it appears that you need to learn the basics. So you've got what you've got: examples describing the basics :-) Anyway, I'll try to dig out something more complex for you.

Re: PrefsObject

Posted: Sun Oct 11, 2015 11:46 pm
by mritter0
I am leaning more towards what BroadBlues suggested. But what salass00 suggested is just as good. But I would like to see some other tags added:

Code: Select all

<pobjects version="2.0">
<dict>
	<Application>MyProgram</Application>
	<Version>1.0</Version>
	<!-- some other tags -->

	<!-- this is more compact -->	
	<integer key="WindowX">79</integer>
	<integer key="WindowY">33</integer>
	<integer key="WindowWidth">1066</integer>
	<integer key="WindowHeight">631</integer>
	<string key="SomeText">Text message</string>
	<bool key="Verify">TRUE</bool>
	
	
	<!-- Be able to add comment lines and blank lines -->	
	<item key="Window">
		<array>
			<item key="WindowX">
				<integer>79</integer>
			</item>
			<item key="WindowY">
				<integer>33</integer>
			</item>
			<item key="WindowWidth">
				<integer>1066</integer>
			</item>
			<item key="WindowHeight">
				<integer>631</integer>
			</item>
		</array>
	</item>
</dict>
</pobjects>
Name and version, comment lines, and blank lines to group better and for easier reading.

For an array, you loop through the count of items. Not good. Should "search" by name like do for individual items. That way if items are added/removed with new version of program it won't affect anything. Then can also be added/removed in any order/place. At least that is what the Mixer code shows.

Then can do this:

Code: Select all

PrefsObject *MainDict, *WindowArray;

Name=IPrefsObjects->DictGetIntegerForKey(MainDict,"Application","");
Version=IPrefsObjects->DictGetIntegerForKey(MainDict,"Version","");

WindowArray=IPrefsObjects->DictGetIntegerForKey(MainDict,"Window",NULL);  // find the Window array
if (WindowArray)
{
    Prefs->WindowX=IPrefsObjects->DictGetIntegerForKey(WindowArray,"WindowX",10);
}
else
{
    // fill in default values
}
.....
Prefs->Verify=IPrefsObjects->DictGetIntegerForKey(MainDict,"Verify",TRUE);
.....