[gtkdialog] Button/Command problem [SOLVED]

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Post Reply
Message
Author
User avatar
Argolance
Posts: 3767
Joined: Sun 06 Jan 2008, 22:57
Location: PORT-BRILLET (Mayenne - France)
Contact:

[gtkdialog] Button/Command problem [SOLVED]

#1 Post by Argolance »

Bonsoir,
Is there a way to disable (make insensitive) a button on click, then enable it after the operation completes?
Thanks.

Cordialement.
Last edited by Argolance on Tue 02 Oct 2018, 17:58, edited 1 time in total.

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#2 Post by MochiMoppel »

Depends on operation.

User avatar
Argolance
Posts: 3767
Joined: Sun 06 Jan 2008, 22:57
Location: PORT-BRILLET (Mayenne - France)
Contact:

#3 Post by Argolance »

Bonjour,
MochiMoppel wrote:Depends on operation.
Thank you for replying.

Code: Select all

#!/bin/bash

func() {
	Xdialog --msgbox "$(gettext 'Program!')" 5 30
} ; export -f func

export main="
<window>
		<hbox>
			<button>
				<label>test 1</label>
				<input file stock="gtk-ok"></input>
				<action>func</action>
			</button>
			<button>
				<label>test 2 with &</label>
				<input file stock="gtk-ok"></input>
				<action>func &</action>
			</button>
		</hbox>
</window>
"
gtkdialog --program=main
In both cases the button is sensitive to mouse clicks and there is nothing to prevent the command from being restarted, either delayed (test 1) or immediately (test 2 with &). I would like the user's clicks to have no effect during the execution of the function (which runs an external program).

[EDIT]: Finally found something that seems to do what I was looking for (the night carries advice :)!).
Is it right?

Code: Select all

#!/bin/bash

echo 0 > /tmp/button

func() {
	if [ "`cat /tmp/button`" != "0" ]; then
		echo $((`cat /tmp/button`+1)) > /tmp/button && echo already running && exit
	else
		echo $((`cat /tmp/button`+1)) > /tmp/button
		Xdialog --msgbox "$(gettext 'Program!')" 5 30
		echo 0 > /tmp/button
	fi
} ; export -f func

export main="
<window>
      <hbox>
         <button>
            <label>test</label>
            <input file stock="gtk-ok"></input>
            <action>func &</action>
         </button>
      </hbox>
</window>
"

gtkdialog --program=main
Cordialement.

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#4 Post by MochiMoppel »

Argolance wrote:[EDIT]: Finally found something that seems to do what I was looking for (the night carries advice :)!).
Is it right?
If it does what you are looking for it must be right, right? :wink:
However it is not exactly what you asked for. The button is not insensitive and runs the function whenever you press it.

Still I guess that your approach is the only option. I tried to make the button insensitive with actions like
<action>disable:BUTTON</action>
<action>func</action>
<action>enable:BUTTON</action>
Kind of works, the button is greyed out.
While func is in action and the external Xdialog is displayed, gtkdialog does not seem to respond to any user actions. The funny things is that when you click the greyed out button (while Xdialog is displayed), nothing happens, but as soon as you dismiss Xdialog, gtkdialog runs func again and Xdialog will be displayed a second time. Gtkdialog "remembers" the mouse click on the disabled button and carries it out as soon as Xdialog closes and ends the "freeze" state. I don't know any way to avoid this annoying behavior.

User avatar
Argolance
Posts: 3767
Joined: Sun 06 Jan 2008, 22:57
Location: PORT-BRILLET (Mayenne - France)
Contact:

#5 Post by Argolance »

Bonsoir,
MochiMoppel wrote:However it is not exactly what you asked for. The button is not insensitive and runs the function whenever you press it.
You are right and I don't see how to describe the stuff except by just saying "prevent a button from running again a command already in progress". This was the goal and the reason of this topic. The solution I have found does the job without making the button "insensitive" or "inactive", but simply by displaying a warning message in console or with Xdialog instead of executing the initial command.
Still I guess that your approach is the only option. I tried to make the button insensitive with actions like
<action>disable:BUTTON</action>
<action>func</action>
<action>enable:BUTTON</action>
Kind of works, the button is greyed out.
While func is in action and the external Xdialog is displayed, gtkdialog does not seem to respond to any user actions. The funny things is that when you click the greyed out button (while Xdialog is displayed), nothing happens, but as soon as you dismiss Xdialog, gtkdialog runs func again and Xdialog will be displayed a second time. Gtkdialog "remembers" the mouse click on the disabled button and carries it out as soon as Xdialog closes and ends the "freeze" state. I don't know any way to avoid this annoying behavior.
Greyed or not, this is exactly this "funny" but very annoying thing which happens with the button "test 1" (scritp above, first button, without "&" after the command/function) and what I absolutely wanted to avoid. Nevertheless, "enable" and "disable" actions are good to know and may also be useful in others circumstances.
Thank you!

Cordialement.
Attachments
181002_201704_2646x1024_easyshot.jpg
(33.84 KiB) Downloaded 308 times

User avatar
fabrice_035
Posts: 765
Joined: Mon 28 Apr 2014, 17:54
Location: Bretagne / France

#6 Post by fabrice_035 »

Hello, another idea, with the help of MochiMoppel

Code: Select all

#!/bin/bash

touch /tmp/enable_button

myscript () {

echo "script execute until end  and enable button after, user must wait"

#
sleep 5
#
echo 0 > /tmp/enable_button
echo "you can restart!"

} ; export -f myscript 


echo '
 <button>
    <variable>BUT</variable>
	<label> START </label>
    <action>myscript&</action>
    <action>disable:BUT</action>
 </button>
     
 
  <timer visible="true" milliseconds="true" file-monitor="true">
   <input file>/tmp/enable_button</input>
   <action signal="file-changed">enable:BUT</action>
  </timer>
 
 '| gtkdialog -s
Regard.

User avatar
Argolance
Posts: 3767
Joined: Sun 06 Jan 2008, 22:57
Location: PORT-BRILLET (Mayenne - France)
Contact:

#7 Post by Argolance »

Bonjour,
Yes, it is another way to get a satisfying result and that answers precisely the question as it was originally asked. However, why a delay of x seconds since the function progress is blocked as long as the program is running?
This seems working the same way:

Code: Select all

#!/bin/bash

touch /tmp/enable_button

myscript () {

Xdialog --msgbox "$(gettext 'Program!')" 5 30

echo 0 > /tmp/enable_button
echo "you can restart!"

} ; export -f myscript

echo '
 <button>
    <variable>BUT</variable>
   <label> START </label>
    <action>myscript&</action>
    <action>disable:BUT</action>
 </button>
  
  <timer visible="true" milliseconds="true" file-monitor="true">
   <input file>/tmp/enable_button</input>
   <action signal="file-changed">enable:BUT</action>
  </timer>
 
 ' | gtkdialog -s 
Thanks to both of you!

Cordialement.

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#8 Post by MochiMoppel »

@fabrice_035: Great idea! This works nicely :D
@Argolance: Which delay? The max. 1 sec. delay before the timer enables the button? It appears that the file is monitored every 1 sec and that setting a shorter scan time is not possible. Shouldn't be a big problem in this use case.

Some observations:
  • • milliseconds="true" has no effect and can be deleted
    • Visibility should be set to "false". It really is just a helper widget and should not be shown (the reason why it's invisible in the example code is the missing box container)
    • No need to use a timer widget. Works the same with any widget capable of file input (text, edit, entry and yes, even pixmap or button)
    • Using echo -n > /tmp/enable_button would keep the tmp file at zero size and would work as well
    file-monitor="true" triggers a signal even when the file content does not change. In the example only the modification time changes.
Now let's put this into practice. Instead of a timer I use another button. This button does something useful and should be visible. Note that the input file would normally be an icon, but here it is our zero length file. By using a label attribute instead of a <label> tag the phony input file does not trigger a gtk-missing-image icon:

Code: Select all

#!/bin/bash
touch /tmp/enable_button 

myscript () { 
	Xdialog --msgbox "$(gettext 'Program!')" 5 30 
	echo -n > /tmp/enable_button 
} ; export -f myscript 

echo '
<vbox> 
<button> 
	<variable>BUT</variable> 
	<label> START </label> 
	<action>myscript &</action> 
	<action>disable:BUT</action> 
</button> 

<button file-monitor="true" label="CANCEL"> 
	<input file>/tmp/enable_button</input> 
	<action signal="file-changed">enable:BUT</action>
	<action>exit:</action>
</button> 
</vbox>

' |gtkdialog -s
Attachments
START_button_disabled_while_Xdialog_running.png
(6.23 KiB) Downloaded 248 times

User avatar
Argolance
Posts: 3767
Joined: Sun 06 Jan 2008, 22:57
Location: PORT-BRILLET (Mayenne - France)
Contact:

#9 Post by Argolance »

Bonsoir,
Which delay?
"delay" was probably not the good word: I was just speaking of this code line in fabrice_035's script example:

Code: Select all

#
sleep 5
# 
Thanks for explanations: it is quite clear and so skilled!

Cordialement.

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#10 Post by MochiMoppel »

Sorry for reanimating a solved problem.
With basically 2 approaches to prevent a button from running again a command already in progress I tend to favor the simple first approach. The 2nd approach may look nicer but enable/disable a button is a bit complex.

No tmp files are required. This would run Xdialog if it isn't running yet, otherwise the function does nothing:

Code: Select all

func() { 
    pgrep Xdialog || Xdialog --msgbox "$(gettext 'Program!')" 5 30 
 } ; export -f func
The function would also do nothing if the same program (here Xdialog) is running but was started by a different script.
If this is a problem then the function could start Xdialog with a unique name and avoid consecutive starts of this uniquely named process:

Code: Select all

func() { 
    pgrep anyname || exec -a anyname Xdialog --msgbox "$(gettext 'Program!')" 5 30 
 } ; export -f func

ITSMERSH

#11 Post by ITSMERSH »

I'm using a 'lock' file!

When entering a function/script I'm checking for a file existing. If existing, the script/function will not run. If not existing I'm echoing a message to that lock file, so it exists. After finishing the function/script just removing the lock file. So, there's no need to disable a button etc.

Code: Select all

#!/bin/sh -a
#------------------------------------------------------------------------------
# QTR Suite - Main Script, GtkDialog GUI
# A small Suite to run QJackCtl, Hydrogen, Qtractor, QSynth, ZynAddSubFx
# 2018-06-10 RSH for Art Studio, Studio2Go and BionicDog Audio Studio, see GPL
#------------------------------------------------------------------------------

# Avoid running multiple instances
if [ -f /tmp/qtr-suite-gui-is-running ]; then
	Xdialog --title "$MYTITLE" --icon "/usr/share/pixmaps/qtrsuite.png" --no-buttons --ignore-eof --infobox "$RUNSALREADYMSGTXT" 0 0 0 &
	ARSINITX3PID=$!
	sleep 3
	kill $ARSINITX3PID
	exit 0
fi
# Create the 'lock' file to avoid running multiple instances
echo "qtr-suite-gui-is-running" >/tmp/qtr-suite-gui-is-running

...
...script's content here...
...

# Remove the 'lock' file to avoid running multiple instances
rm -f /tmp/qtr-suite-gui-is-running

exit 0

Post Reply