Revision [32862]
This is an old revision of gtkdialogDocTips3 made by zigbert on 2020-07-24 19:46:53.
3. Let external code act on your gtkdialog gui
If you want a second gtkdialog-gui to act on your main gui. You simply "launch" the second gui from the main gui. The negative aspect about this solution is that before showing the main gui, it has to load all the launchable scripts. This means slower startup.
export launch_me=' <button> <input file stock="gtk-refresh"></input> <action>Refresh:DATE</action> </button>' export box=' <vbox> <entry><input>date</input><variable>DATE</variable></entry> <button><label>launch</label><action type="launch">launch_me</action></button> </vbox>' gtkdialog -p box
Imagine that you start a background process to calculate the content of <list>. It will take too long to wait for the result before showing the gui. Imagine that you want to update the content in a gui from a separate app. Okay, here's the trick.....
Gtkdialog updates a progressbar with info from standard output. Most common are the cat and echo commands. First echo "text in bar" (optional), then echo 50 or whatever % integer to define how long the process is come. When a progressbar achieves 100% done (echo 100), it activates its <actions>. So, as long as % is below 100, the actions are not run, but as soon as you echo 100 it will execute your defined actions. What is very good, is that you now can echo 0, and start all over again. Last stage is to define if you want the progressbar shown in your gui. add visible="false" to make it invisible.
Here is a simple example of a clock
export box=' <vbox> <progressbar visible="false"> <input>while [ A != B ; do sleep 0.5; P=`cat /tmp/p`; echo $P; echo 100 > /tmp/p; done</input> <action>refresh:ENTRY</action> <action>echo 99 > /tmp/p</action> </progressbar> <entry> <variable>ENTRY</variable> <input>date +%H:%M:%S</input> </entry> </vbox>' gtkdialog -p box
If you want a frequent refreshing of a widget, the <timer> widget was introduced in gtkdialog 0.7.21.
<timer milliseconds="true" interval="500" visible="false">
Gtkdialog misses a tailbox widget, but using this solution it is easy to build our own tailbox.Both <timer> and <progressbar> widgets uses cpu-power, and in a complex gui this could be a real pitfall. Here follows an explanation of how it is solved in pMusic. It is a way to update a complex gui on non-user actions. User-actions is mouse-clicks and key-entries, and is the common way to interact between user and gui. An example of updating the gui on a non-user-action in pMusic is the loading of id3-tags for files shown in the file-browser....
When clicking on a directory, the browser field refreshes and shows the content of the new directory. Now, pMusic continues with a background process to read the id3 information of the files. When finished, the file-browser should be updated by the new info. - Without the user to click anywhere.
The solution is to either use a <progressbar> which runs its <action> when reaches 100% or a <timer> which acts at a given interval. Older pMusic releases used the <progressbar> solution while recent code uses a <timer>. Both solutions has the downside that they use an amount of cpu power. In a complex gui with several non-user actions this could end up with several cpu-hungry <timers> updating their unique widget(s) of the gui.
pMusic has used 2 <timers> running constantly to update their defined gui-part. You might think that 1 <timer> would be enough, - it could refresh all wanted widgets - it wouldn't harm if the refreshing didn't change anything. BUT, refreshing has an effect on the focus handling. It simply resets the focus, which means that:
- scrolling in <table> is moved to top.
- what you are about to write in an <entry> is cleared.
- Your selected item in the <tree> is not selected anymore
- ...
The idea of pMusic 2.4.0 was to update all kinds of trackinfo (meta-tags, lyrics, albumart, discography, ...) when a new track starts playing. This would not be possible with the underlaying event-handling in pMusic because it would either suck your cpu-power (with several <timers>), or a global refreshing would make it impossible to be a user (because of focus issues). Also, there is a fact that too many refreshing <action> on a <timer> will increase cpu-usage as well.
So the solution has been to add ONE <timer>, which refreshes a small set of <checkboxes> that (if true) refreshes a single or group of widgets.
<checkboxes> can be set true or false by their <input file>, so we can simply echo true to its <input file>. The <timer> runs its <actions> each second, and the <checkbox> will be refreshed by its <input file>. The code could look like this:
<checkbox visible="false"> <label>a</label> <variable>UPDATE_GUI</variable> <input>cat /path/UPDATE_GUI</input> <action>if true refresh:PLAYLIST</action> <action>if true refresh:ARTWORK</action> <action>if true refresh:BUTTON_PLAY</action> <action>if true echo false > /path/UPDATE_GUI</action> </checkbox>
All actions will run only if value is true. To avoid more than one refreshing we reset <input file> and the <checkbox> value to false. Now it will be silent until the next time we echo true > inputfile.
Example script here