Hmm, on the other hand, emblems are only gvfs metadata. So in theory, setting emblems already can be done by plugins, by settings the according emblem for each file. Here some exaples.
I think that something akin to Nautilus's InfoProvider would be really helpful along with this emblem support.
From that documentation:
If subclassed, Nautilus will call update_file_info(_full) to notify extensions of which files are being viewed by the user. This gives extensions an opportunity to invoke actions on the files, or to add emblems or attributes.
This is used by the Nextcloud Nautilus plugin. Whenever someone in Nautilus navigates to any Nextcloud folder, or subfolder, Nautilus will call the plugin's update_file_info function for all the files/folders contained in that folder. The plugin the queries Nextcloud to see what emblems to use for the contents of that folder.
I have been using GFileInfo attributes to set metadata::emblems for the Nextcloud plugin I am working on. Everything happens smoothly, except there is no way (that I can see) to tell Thunar that the emblems have changed. The user has to press ctrl-r to see the emblems change.
It looks like the way to get Thunar to detect the updated emblems is to call thunarx_file_info_changed. However there are two problems with this:
The documentation says "This method should not be invoked by Thunar plugins"
A plugin cannot (AFAIK) create a ThunarxFileInfo instance by itself. It can only be passed one. In order to change emblems in response to external stimuli, the plugin needs to be able to take a path char* or GFile and get a ThunarxFileInfo instance from it. I think the internal thunar_file_get is what we would need, but that is not exposed to plugins.
The documentation says "This method should not be invoked by Thunar plugins"
This documentation is illogical. If it should not be invoked by plugins, why is it exposed to thunarx in the first place? The thunar-shares-plugin as well seems to use it, so I will just update the documentation.
A plugin cannot (AFAIK) create a ThunarxFileInfo instance by itself ...
Not sure if it would be sufficient to expose thunar_file_get to thunarx. That would only give you a single file and as such you would need to iterate on all files in a that folder and so effectively mirror the structures which are already present inside thunar. (Not to mention that it could be inefficient to create and destroy all thunar_files in a folder, since you don't know if thunar already has loaded these files itself)
I think it would be better to inform thunarx whenever the current directory is changed and expose all files in that directory to thunarx. E.g. thunarx_directory_monitor_directory_loaded (GHashTable files). So the plugin could actively check the sync state of files inside that directory after it got loaded. The GHashTable could consist of <g_file,thunarx_file_info> so that you can effectively look up files in large directories.
You think that would work for your usecase?
Regarding setting the emblems itself, I suppose it would make sense to expose thunar_file_set_metadata_setting and thunar_file_get_metadata_setting. Though I think we should encapsulate that a bit, so that in the end there could be thunarx_file_info_add_emblem and thunarx_file_info_remove_emblem ? So thunar itself could take care to set emblems in an asynchronous way (maybe even is a separate thread, to prevent freeze when doing so for a big folder full of files .. that's how it is done for the chooser dialog) and trigger the file reload itself when it is done.
I think it would be better to inform thunarx whenever the current directory is changed and expose all files in that directory to thunarx...
This would be great, but I'm not sure it is sufficient. In addition to the user changing the directory they are in there are two other places that I see emblems being displayed:
In the search view.
In the Bookmarks/Shortcuts sidebar
Ideally the extension should get thunarx_file_info instances for files in those places too.
The other tricky bit (maybe?) would be updating the emblems asynchronously when the Nextcloud client notifies the plugin of changes. Thunar needs to be notified if an emblem on a file changes that is currently visible in:
The main file view.
The search view.
In the Bookmarks sidebar
The plugin could temporarily keep the thunarx_file_info instances, but it would need to know when those files have gone out of view (particularly tricky if the user has multiple windows open).
Instead, would it be reasonable to expose something like thunar_file_cache_lookup to plugins? That way they could properly change the emblems on any cached files?
The plugin could temporarily keep the thunarx_file_info instances, but it would need to know when those files have gone out of view (particularly tricky if the user has multiple windows open).
Yea, that sounds like a bad idea ... I suppose the nextcloud plugin only should keep a ref on a ThunarxFileInfo for the time it does modifications on it / for the time it requests an update for the file via the socket.
Instead, would it be reasonable to expose something like thunar_file_cache_lookup to plugins? That way they could properly change the emblems on any cached files?
Hmm, that might make sense … depends on which possibilities the nextcloud socket API describes. I think I first need to understand what are the possibilities via that Socket connection:
handle_io_watch will be called by the nextcloud app at random times, for random files? Or will the nextcloud app call it only once when the plugin starts with UPDATE_VIEW ? Does the nextcloud app trigger handle_io_watch at all if we don't actively request information?
ncsock_send can be called to ask for info on a specific file or for all files in a folder ... we will get the answer via handle_io_watch ?
Considering we will expose thunar_file_cache_lookup on thunarx, I see two use-cases:
A thunarx_file_info is returnd --> Use thunarx_file_info_add_emblem / thunarx_file_info_remove_emblem and send the "changed" signal if required.
NULL is returned --> Still need to set the emblem on the g_file, since we might not notice when the file is presented via thunar (bookmarks, search view, etc)
So in case handle_io_watch will be called with random paths by the nextcloud app, it looks like we either need to expose thunar_g_file_get/set_metadata_setting, which takes a gfile as argument, or you anyhow need to ship your own code to get/set emblems.
handle_io_watch will be called by the nextcloud app at random times, for random files? Or will the nextcloud app call it only once when the plugin starts with UPDATE_VIEW ? Does the nextcloud app trigger handle_io_watch at all if we don't actively request information?
Yes, handle_io_watch will be triggered by the nextcloud app at random times. The nextcloud app will send out a UPDATE_VIEW command to handle_io_watch. This tells the plugin that there have been changes in that directory.
ncsock_send can be called to ask for info on a specific file or for all files in a folder ... we will get the answer via handle_io_watch ?
The way we scan for changes is by issuing RETRIEVE_FILE_STATUS or RETRIEVE_FOLDER_STATUS commands through ncsock_send. When we ask for status, nextcloud will send back a STATUS command with the emblem to use.
Perhaps an example would be helpful. Say you have a nextcloud tree like this:
And lets say that you edit the /home/user/Nextcloud/notes/dinner.md via the web interface. The server will notify your nextcloud app that the file was modified. Then the nextcloud app will send this message to the Thunar plugin:
UPDATE_VIEW:/home/user/Nextcloud/notes
The Thunar plugin would receive this via handle_io_watch. At this point the plugin will check that directory, and get emblem info by sending:
RETRIEVE_FOLDER_STATUS:/home/user/Nextcloud/notes
And the nextcloud client would reply with the emblems:
...or you anyhow need to ship your own code to get/set emblems.
This isn't all that onerous, but it would be nice if Thunarx provided this functionality. This is how I implemented it (very similar to how Thunar does it).
(Edited to correct the commands that we send and receive in the example)
Edited again well I just did a little more testing, and found out that I don't even have to send out the RETRIEVE_FOLDER_STATUS command. It seems like Nextcloud sends us the STATUS without needing to request it. That makes intuitive sense.
As far as I can tell, this interface is not documented (aside from being open source and having some open-source plugins for other file-managers). So it looks like I can simplify things even further.