Saving and restoring program settings and states (classes for doing this..?)


#1

I’m talking about where the user changes settings in the program (and maybe even the state of the program itself) and they automagically remain when the user restarts the program. I know this can be done with file i/o but this involves choosing a format and various design decisions that have probably been done a lot better than what I would come up with… So I’m wondering about classes in JUCE that are there for this purpose, or to make it easier etc?
Thanks for any help.


#2

Search the forum for ApplicationProperties uses. I have a post about a class I wrote called ScopedValueSaver that you might be interested in.


#3

Thank you!
looking at it now…


#4

if this can help:

class MainComponent   : public Component
{
public:
    //==============================================================================
    MainComponent()
    {
        initProperties();
        int w,h;
        w = props.getUserSettings()->getIntValue("Width");
        if(w==0)
            w=640;
        h = props.getUserSettings()->getIntValue("Height");
        if(h==0)
            h=480;
        setSize(w,h);
     
    }
    ~MainComponent()
    {
       props.getUserSettings()->setValue("Width", getWidth());
       props.getUserSettings()->setValue("Height", getHeight());
    }
    
    void initProperties()
    {
        PropertiesFile::Options options;
        options.applicationName = ProjectInfo::projectName;
        options.filenameSuffix = ".settings";
        options.osxLibrarySubFolder = "Application Support";
        options.folderName = File::getSpecialLocation(File::SpecialLocationType::userApplicationDataDirectory).getChildFile(ProjectInfo::projectName).getFullPathName();
        options.storageFormat = PropertiesFile::storeAsXML;
        
        props.setStorageParameters(options);
    }
    
    void paint (Graphics& g) override
    {
        g.setColour(Colours::white);
        g.drawText (currentSizeAsString, getLocalBounds(), Justification::centred, true);
    }
    void resized() override
    {
         currentSizeAsString = "Width: " + String (getWidth()) + " x Height: " + String (getHeight());
    }

private:
        ApplicationProperties props;
    String currentSizeAsString;
  
    //==============================================================================
    // Your private member variables go here...


    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};

#5

Thanks for the replies.
The ApplicationProperties approach is simpler for a JUCE newby to follow but I appreciate the awkwardness that gets encountered in more sophisticated situations that matkatmusic describes in his description of ScopedValueSaver.
I would lake to save a colour pallette of potentially large numbers of colours that are in an array. Simply restoring the whole array at init and saving it in the destructor would probably be sufficient. Are there any tips for working with arrays? For example ApplicationProperties uses a unique string to identify the variable in the file. So would I generate a string that embeds the array index inside the string?
Thanks for any help


#6

I implemented a restore and save method for my data structure (using ApplicationProperties) which turned out to be quite forward. The identifier strings that are used by ApplicationProperties are constructed from the stringified array index and tags that identify the structure elements (its an array of structs).
I’d be interested if there were any more general classes for doing this.


#7

Since C++ does not have reflection and if you are not using the JUCE ValueTrees, there’s no “elegant” solution for serialization and deserialization of your states. You will just have to manually manage with whatever you come up with…


#8

My ScopedValueSaver is pretty easy to use if you look at the examples included with it.