TwiceAsNice  2019-02-18
Public Member Functions | Private Member Functions | List of all members
indiclient.gui_indi_object_handler Class Reference
Inheritance diagram for indiclient.gui_indi_object_handler:
Inheritance graph
Collaboration diagram for indiclient.gui_indi_object_handler:
Collaboration graph

Public Member Functions

def on_blocked (self, args)
 
def on_gui_changed (self, args)
 
def set_bidirectional (self)
 
def unset_bidirectional (self)
 
- Public Member Functions inherited from indiclient._blocking_indi_object_handler
def __init__ (self)
 
def indi_object_change_notify (self, args)
 
def on_indiobject_changed (self, args)
 
def configure (self, args)
 

Private Member Functions

def _blocking_on_gui_changed (self, args)
 

Detailed Description

This class provides two abstract handler functions. One to handle changes of (not 
necessary graphical) user interfaces L{on_gui_changed}. And another one  
L{on_indiobject_changed} to handle changes of INDIobjects received from the INDI server.
It allows to detect if the method L{on_gui_changed} is in asked to be called,  while the method 
L{on_indiobject_changed} is running. This situation has to be take special care of, as loopbacks or data losses
are likely to happen if one does not take care.
In order to allow this mechanism to work
every function must B{not} call on_gui_changed directly, but any function may call 
L{_blocking_on_gui_changed} instead. So if you are writing a custom handler please link the callback of
your GUI to L{_blocking_on_gui_changed} and implement it in L{on_gui_changed}

Member Function Documentation

◆ _blocking_on_gui_changed()

def indiclient.gui_indi_object_handler._blocking_on_gui_changed (   self,
  args 
)
private
Called by the GUI whenever the widget associated with this handler has changed. If the method on_indiobject_changed is currently active,
the method L{on_blocked} is called otherwise (which is the far more usual case) the method L{on_gui_changed} is called.
B{Important:} link your GUI callback signal to this function but implement it in L{on_gui_changed} (see L{on_blocked} if you want to know why)
@param args: The arguments describing the change of the GUI object(s)
@type args: list
@return: B{None}
@rtype:  NoneType       

◆ on_blocked()

def indiclient.gui_indi_object_handler.on_blocked (   self,
  args 
)
The method L{_blocking_on_gui_changed} is called by the GUI, in order to inform us, that a widget has changed.
If the blocked property is C{True}, when L{_blocking_on_gui_changed} is called by the GUI. This method (L{on_blocked}) is called and nothing else done.
The blocked property is C{True} while the  L{on_indiobject_changed} function is running, so and indiobject has been received from the server
and L{on_indiobject_changed} is currently changing the widget associated with it. So there is a question: Was L{_blocking_on_gui_changed} called by the GUI?
because  L{on_indiobject_changed} changed the widget or was it called because the user changed something? 
Well, we don't know! And this is bad.
Because if L{on_indiobject_changed} did it and we send the new state to the server, the server will reply, which will in turn trigger
L{on_indiobject_changed} which will cause the GUI to emit another L{_blocking_on_gui_changed} signal and finally call L{on_blocked}.
This way we have generated a nasty loopback. But if we don't send the new state to the server and the change was caused by the user, the user 
will see the widget in the new state, but the server will not know about it, so the user has got another idea of the status of the system than the server
and this is also quite dangerous. For the moment we print a warning and send the signal to the server, so we use the solution that might cause a loopback,
but we make sure that the GUI and the server have got the same information about the status of the devices. One possible solution to this problem that
causes neither of the problems is implemented in the L{gtkindiclient._comboboxentryhandler} class. We do no send the new state to the server. But we load the latest state
we received from the server and set the gui to this state. So the user might have clicked at a GUI element, and it might not have changed in the proper
way. We tested this for the combobox and the togglebutton and it worked.
@param args: The arguments describing the change of the GUI object(s)
@type args: list
@return: B{None}
@rtype:  NoneType       

◆ on_gui_changed()

def indiclient.gui_indi_object_handler.on_gui_changed (   self,
  args 
)
B{Important:} Implement your GUI callback here but link you GUI callback signal to {_blocking_on_gui_changed}
(see L{on_blocked} if you want to know why)
@param args: The arguments describing the change of the GUI object(s)
@type args: list
@return: B{None}
@rtype:  NoneType

◆ set_bidirectional()

def indiclient.gui_indi_object_handler.set_bidirectional (   self)
installs callbacks of the GUI that will call the function L{_blocking_on_gui_changed} if the user changes the the GUI object associated 
with this L{gui_indi_object_handler} . 
The function L{_blocking_on_gui_changed} will usually call the function L{on_gui_changed}. The function L{on_gui_changed} has to update and send the 
INDI object associated with this L{gui_indi_object_handler}. 
@return: B{None}
@rtype: NoneType

◆ unset_bidirectional()

def indiclient.gui_indi_object_handler.unset_bidirectional (   self)
uninstalls the GUI callback installed with L{set_bidirectional} (see L{set_bidirectional} for details)
@return: B{None}
@rtype: NoneType

The documentation for this class was generated from the following file: