ValueTree fromXml() and Listeners

I’d like my ValueTree::Listener to know when the ValueTree changes (is loaded from XML), is it possible at all, since the fromXml() method is static it does not work within the ValueTree i’m listening on, is there some other way to have valueTreeChildAdded() and others called during the restoration of a ValueTree from a XML document (this document is created only with the createXml() method, no bogus data in it).

well i did a copy of fromXml method in my own code (it’s just a few lines) and i got the behavior i want, almost i get the callback only for the first added child and not for children further down the tree.

masterTree = ValueTree (savedState.getTagName());
	
	for (int i=0; i<savedState.getNumAttributes(); i++)
		masterTree.setProperty (savedState.getAttributeName(i), savedState.getAttributeValue(i), 0);

    forEachXmlChildElement (savedState, e)
		masterTree.addChild (ValueTree::fromXml (*e), -1, 0);

is there some easier way to have those callback, or do i need to override the ValueTree methods to achieve this ?

Well, loading a tree from XML creates an entirely new node. You can’t really load an XML representation into an existing node (what would be done with the old root?), so you replace the contents of the original. Perhaps that’s what you need a new callback for? (valueTreeContentReplaced).

As the entire structure is replaced with loaded data, surely you’re better off just traversing the tree and putting the new data to use? I.e. All the stuff that happens when things get added, do them all at once for the stuff that is already there.

The approach you’re describing doesn’t sound very practical!

it doesn’t i agree, and i’m moving away from it. i think i’ll go through the whole tree adding the relevant data with my own methods.

Sorry to resurrect this old thread, but in my quest to better understand ValueTrees, I came across this exact issue, with no apparent answer.

In the initialization of my app, I create my main state ValueTree with all the children and properties that I need throughout my app. (Btw, they’re all basically inner voicing variables that I want to adjust, not really user parameters). At some point I have the app save the ValueTree to a file like this:

void saveSettings()
{
	File file("~/Desktop/foo.xml");
	if(file.exists())
		file.deleteFile();
	
	auto innerState = state.getChildWithName(IDs::InnerSettings);		
	ScopedPointer<XmlElement> xml = innerState.createXml();
	xml->writeToFile(file, String());
}

After quitting the app and restarting, I load my settings from that file with this:

void loadSettings()
{
	File file("~/Desktop/foo.xml");
	ScopedPointer<XmlElement> element = XmlDocument::parse(file);
	auto newMap = ValueTree::fromXml(*element);
    auto innerState = state.getChildWithName(IDs::InnerSettings);
	innerState.copyPropertiesAndChildren(newMap, nullptr);  // listeners not called!
}

First off, I’m not sure I understand why my listeners aren’t called, but the bigger issue is…what’s the proper way to do this? Am I supposed to loop through all the nodes and properties in the loaded ValueTree and update all my properties one by one by hand? Or should I reregister all the listeners throughout my app? I must be missing something obvious.

I‘m also wondering whats the way to do this, if I got you Right, I think I asked the same question about a week ago:

As I got no answer I went the route of iteating over all properties, however this feels wrong to me too

Sorry I missed your post or I would have replied there. Thanks for sharing your code. I was afraid I’d have to do something just like came up with, recursively restoring each child and property.

It seems strange that with all the love for ValueTrees that restoring one isn’t part of the built-in functionality. Or are we both missing something?