Add mechanism to reference keys in the GUI
This is an implementation to fetch a FilePath object's "path" attribute from another widget.
Usually the latter will be a FilePath of type "path" but this doesn't matter, you could also prepend a number. This adresses issue #878 (closed), but does not add all functionality mentioned in @bavay's comment (recursion).
There is a central point for this now which can be called from any place at which inishell.h can be included. So far, it is only used in a FilePath type "filename" where the "path" attribute was set.
Hence, the following is possible and showcased in MeteoIO:
<parameter key="STATION#" type="filename" mode="input" replicate="true" optional="false" path="%INPUT::METEOPATH">
In principle it is now easy to call the keysub
function in any place we want to look up keys.
The tricky part is deciding exactly where and when this should take place.
Considering this example given by @bavay:
<parameter key="SNOWFILE#" type="filename" mode="input" replicate="true" optional="true" section="Input" path="%INPUT::SNOWPATH">
<parameter key="SNOWPATH" type="path" default="%INPUT::METEOPATH">
we run into some sort of "race condition" the way I see it. I have not thought it through 100% but food for thought:
- This feature is part of the XML design. There, user content should not matter when initially creating the GUI.
- When reading default="%INPUT::METEOPATH" at creation time of "SNOWPATH", that key will be empty.
- So, we would have to remember to look up that value at a later time (which is exactly what FilePath does for the "path" attribute).
- But: what to use it for? The FilePath panel internally handles when to do the substitution, for example when the user wants to preview the file, but not when it is written out. Where to inject the default value though?
- Surely we do not want to do it on ini writeout, because then every time the file was saved and read back in we would have one iteration of the path prepended, and the ini altered each time.
- When you put default="%INPUT::METEOPATH" then this will be displayed in the text field. I. e., when just saving the ini this is the
configuration the application will get to see. Unless we explicitly exclude it, and try to keep track of all of this internally. We would
need to activate the
keysub
function for generic ini keys (for example in thegetIniValue()
call), but this should not be taken lightly I think, mainly because we then have to avoid writing this out to the ini file! We would track two different states for each value, one when it's loaded in INIshell (all replacements done), and one for the ini file (no replacements). Sounds awullly complicated... - Maybe it is more logical to do this after the ini file is complete, i. e. in MeteoIO? This way it would be clear who handles what. Our widget value is exactly what the application will get to see, and the "path" substitution is handled transparently in the GUI:
<parameter key="SNOWFILE#" type="filename" mode="input" replicate="true" optional="true" section="Input" path="%INPUT::SNOWPATH">
<parameter key="SNOWPATH" type="path" default="${INPUT::METEOPATH}">
Or am I seeing this all wrong and there's an elegant solution?
More comments:
- This is a one-way connection; a "path" type FilePath does not know that it is being referenced by some other widget. Hence, the referring widget will not update when the referenced one changes and for e. g. the "unknown file" warning stays active when the prepending path is altered. Could be fixed of course, but not without some added complexity.
- Since this should close issue #878 (closed) and the rest does not fit right now I suggest to merge soon and open new tickets
for further (well thought-through) features. My feeling is that there is no generic way to decide when exactly to substitute and
each new such substitution must be crafted a bit separately (using the central
keysub
function). Feel free to play around in the branch though if you have concrete ideas. - I did not touch the Workflow and see if things could be unified more because issue #881 is a thing (but quite big).
- The
keysub
function is recursive, but this is unused and untested. Multiple substitutions per string are possible and arbitrary strings can be in between as long as they are separated from the keyval as per the regex (e. g.FILE_%INPUT::INFILE[%INPUT::NRKEY].dat
).