ValueTree question / feature request


#1

Hello all.

I can’t see a direct way to get a property from a ValueTree by index. you can do:

for (int i = 0; i < ValueTree.getNumProperties(); ++i) ValueTree.getProperty (ValueTree.getPropertyName (i));

…which is rather wordy. ValueTree.getProperty (i) would be useful.

Secondly, and related, an iterator for the properties as well as children of the ValueTree would be useful.

Apologies if I’m looking over something obvious.

Thank you.


#2

It seems like you’re missing the WHOLE point of __Value__Tree.

  • This isn’t an array. so i is for Identifier (key/value). so it should be meaningful and not tied to index position.
  • If you’d like to Iterate you should use Iterator like concept which would be written better.

Check the ValueTree::Iterator:
https://www.juce.com/doc/structValueTree_1_1Iterator


#3

Thank you for your reply ttg, I do understand that ValueTree is not an array, but for occasional purposes I do find it useful to be able to do something like call all the var objects in a ValueTree, or find a different identifier within it rather that it’s ValueTree Type. The iterator only iterates through children of the ValueTree (i.e. other ValueTrees), it would be useful to do so with the properties.


#4

The problem here is, that a ValueTree follows the paradigmata of XML, where the sequence of properties is undefined. So if it would allow to access properties by index, save it to XML and read it back, you get inconsistent behaviour.
But what could be really handy to get all properties as StringArray, so you can iterate over them, but still access the properties by name.
But String and Identifier are also two different things…


#5

That indeed would be extremely useful! String and Identifier are different, but a function to return all of the id’s as a StringArray is certainly doable. For now I’ll create my own function to do so, but it would be nice to have the capacity to do so from the ValueTree directly.


#6
/** Provides an STL compatible iterator for the properties of ValueTree. */
class ValueTreePropertyConnector
{
public:
    ValueTreePropertyConnector(const ValueTree & tree) : tree(tree) {}

    class Iterator
    {
    public:
        Iterator(const ValueTree & tree, int position) : tree(tree), pos(position) {}
        Iterator & operator++() { ++pos; return *this; }
        bool operator!= (const Iterator & other) const { return other.pos != pos || other.tree != tree; }
		std::pair<Identifier, var> operator * () const
		{
			auto propertyName = tree.getPropertyName(pos);
			return { propertyName, tree.getProperty(propertyName) };
		}

    private:
        Iterator & operator=(const Iterator &) = delete;
        const ValueTree & tree;
        int pos;
    };

    Iterator begin()    { return Iterator(tree, 0); }
    Iterator end()      { return Iterator(tree, tree.getNumProperties()); }

private:
    JUCE_DECLARE_NON_COPYABLE(ValueTreePropertyConnector)
    ValueTree tree;
};

Is this any use? I’ve not used it for ages, I think it works. It should let you do something like:

for (auto & x: ValueTreePropertyConnector(someValueTree))
{
   auto & propName = x.first; 
   auto & propVal = x.second;
}

#7

Thank you Jimc, very helpful!

Steve.