Quote:
Originally Posted by capink
Actually I was thinking of not (just) using templates on book metadata, since mi objects can accept extra information I can do something like this:
Code:
device_uuid = get_device_uuid()
cmeta1 = {'datatype': 'text', 'is_multiple': {}, 'name': '#device_uuid'}
mi.set_user_metadata('#device_uuid', cmeta1)
mi.set('#device_uuid', device_uuid)
Using this method, we can insert multiple fields storing global state values enabling the user can define conditions using the familiar template language:
|
This is a bit dangerous. You must ensure that the field doesn't already exist. There are also a lot more field metadata items that are assumed to exist in various places, for example "display". Depending on the calibre action, the field might appear in a column list but not work correctly. I don't know if it is safe to pass such an mi to all db functions that modify the database. Note: some formatter functions check if mi is a ProxyMetadata object and refuse to work if it is not. For that reason, and also for performance, you probably want to use get_proxy_metadata() instead of get_metadata().
Another safer way to insert data: implement "globals" in the formatter. I would extend the formatter to accept a dictionary of name:value pairs. A template would access this dict using a new function, perhaps globals(), that acts similarly to the existing arguments() function, copying the globals to local variables. Example: in your plugin you call the formatter with something like
Code:
dict = {'a': 2, 'b': 'some string', 'e':'not used'}
The user puts something like this in the template
Code:
globals(a, b='no string', c='default')
"globals()" sets the variables a, b, and c from the dict, using the default expression if the variable is missing from the dict. In this example 'a' and 'b' are set from the dict, 'c' gets the default, and 'e' isn't copied. NB: template variables can be accessed in both TPM and GPM.
In addition to the above, you define a new built-in action to set the value of a global. It would be almost identical to "Single Field Edit". That along with the branching idea might solve @compurandom's problem because he could use branching to set variables he can use in templates. In fact, he might not need branching.
There might be a way to combine the globals dict with branching. For example, branching could test the global variable '_branch_condition_'. Another way would be to use two columns, one for the global name and one for the value.
Quote:
And now the user can flag actions with the device_uuid (or alternatively device_name if there is such a thing?) and they will only run if the device is attached. This also presents the question of what extra information to inject into the mi object that can be useful for conditional actions?
|
There is already a formatter function to retrieve the device name, connected_device_name(). I can add a function to get the device UUID if that is something useful.
Regarding extra information, perhaps things like the chain name, the action name, the action comment, the value controlling branching, and action-specific data such as the file path you mention below. FWIW: I think automatically-added globals should have a distinctive name to avoid collisions, perhaps one that begins and ends with '_'.
Quote:
By the way, the above technique is already used in the plugin. Any action that implements an update_metadata(self, mi) method, is called on every mi object and given the chance to modify it. I have a custom action that inserts a calculated file path, that is not stored in calibre, into the mi object as a #path_to_file field, this field is used by the template feature of the open with action to open the file/folder. Since the file(s) location changes from time to time, I have it mapped into a automatically updated json file (uuid to location mapping).
|
This is useful for modifying metadata. I am still concerned about inserting new metadata fields (lookup keys).
Quote:
Finally, when fetching mi object in case we have multiple books selected, which one do we use? the current index? would the metadata for that one book provide value for conditional execution of actions?
|
This is an interesting question. There is no reason to believe that the condition evaluation template will generate the same answer for each book. I suspect the right thing to do is (optionally) loop over the books calling the chain for each book. If the user knows that the condition(s) will apply to all books then don't check the option, in which case the condition evaluation uses the first book in the selection.