Fetching command list from entity now works.
If the entity has at least one command exposed, it will be displayed as a radio button. Other changes: run python interpreter without optimalizations, otherwise asserts doesn't work. Names of widgets in the glade file were changed a bit.
This commit is contained in:
parent
23fa0bf8e6
commit
145cdbbf40
|
@ -17,6 +17,7 @@
|
||||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
|
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
|
||||||
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
||||||
<property name="focus_on_map">True</property>
|
<property name="focus_on_map">True</property>
|
||||||
|
<signal name="destroy" handler="on_adhoc_commands_window_destroy" last_modification_time="Thu, 22 Jun 2006 22:50:45 GMT"/>
|
||||||
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkVBox" id="vbox1">
|
<widget class="GtkVBox" id="vbox1">
|
||||||
|
@ -26,7 +27,7 @@
|
||||||
<property name="spacing">0</property>
|
<property name="spacing">0</property>
|
||||||
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkNotebook" id="mode_notebook">
|
<widget class="GtkNotebook" id="stages_notebook">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="show_tabs">False</property>
|
<property name="show_tabs">False</property>
|
||||||
<property name="show_border">False</property>
|
<property name="show_border">False</property>
|
||||||
|
@ -35,7 +36,7 @@
|
||||||
<property name="enable_popup">False</property>
|
<property name="enable_popup">False</property>
|
||||||
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkVBox" id="vbox2">
|
<widget class="GtkVBox" id="retrieving_commands_stage_vbox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="homogeneous">False</property>
|
<property name="homogeneous">False</property>
|
||||||
<property name="spacing">0</property>
|
<property name="spacing">0</property>
|
||||||
|
@ -114,7 +115,7 @@
|
||||||
</child>
|
</child>
|
||||||
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkVBox" id="vbox5">
|
<widget class="GtkVBox" id="command_list_stage_vbox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="homogeneous">False</property>
|
<property name="homogeneous">False</property>
|
||||||
<property name="spacing">0</property>
|
<property name="spacing">0</property>
|
||||||
|
@ -187,7 +188,7 @@
|
||||||
</child>
|
</child>
|
||||||
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkVBox" id="vbox3">
|
<widget class="GtkVBox" id="sending_form_stage_vbox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="homogeneous">False</property>
|
<property name="homogeneous">False</property>
|
||||||
<property name="spacing">0</property>
|
<property name="spacing">0</property>
|
||||||
|
@ -314,7 +315,27 @@
|
||||||
</child>
|
</child>
|
||||||
|
|
||||||
<child>
|
<child>
|
||||||
<placeholder/>
|
<widget class="GtkLabel" id="label257">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="label" translatable="yes">An error has occured.</property>
|
||||||
|
<property name="use_underline">False</property>
|
||||||
|
<property name="use_markup">False</property>
|
||||||
|
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||||
|
<property name="wrap">False</property>
|
||||||
|
<property name="selectable">False</property>
|
||||||
|
<property name="xalign">0.5</property>
|
||||||
|
<property name="yalign">0.5</property>
|
||||||
|
<property name="xpad">0</property>
|
||||||
|
<property name="ypad">0</property>
|
||||||
|
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||||
|
<property name="width_chars">-1</property>
|
||||||
|
<property name="single_line_mode">False</property>
|
||||||
|
<property name="angle">0</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="tab_expand">False</property>
|
||||||
|
<property name="tab_fill">True</property>
|
||||||
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
|
||||||
<child>
|
<child>
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
cd `dirname $0`/src
|
cd `dirname $0`/src
|
||||||
exec python -OOt gajim.py $@
|
exec python -t gajim.py $@
|
||||||
|
|
|
@ -19,9 +19,16 @@
|
||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
## GNU General Public License for more details.
|
## GNU General Public License for more details.
|
||||||
|
|
||||||
|
# TODO: think if we need caching command list. it may be wrong if there will
|
||||||
|
# TODO: be entities that often change the list, it may be slow to fetch it
|
||||||
|
# TODO: every time
|
||||||
|
|
||||||
import gobject
|
import gobject
|
||||||
import gtk
|
import gtk
|
||||||
|
|
||||||
|
import common.xmpp as xmpp
|
||||||
|
import common.gajim as gajim
|
||||||
|
|
||||||
import gtkgui_helpers
|
import gtkgui_helpers
|
||||||
|
|
||||||
class CommandWindow:
|
class CommandWindow:
|
||||||
|
@ -35,45 +42,158 @@ class CommandWindow:
|
||||||
def __init__(self, account, jid):
|
def __init__(self, account, jid):
|
||||||
'''Create new window.'''
|
'''Create new window.'''
|
||||||
|
|
||||||
self.pulse_id=None # to satisfy self..setup_pulsing()
|
# an account object
|
||||||
|
self.account = gajim.connections[account]
|
||||||
|
self.jid = jid
|
||||||
|
|
||||||
# connecting to handlers
|
self.pulse_id=None # to satisfy self.setup_pulsing()
|
||||||
|
self.commandlist=None # a list of (commandname, commanddescription)
|
||||||
|
|
||||||
# retrieving widgets from xml
|
# retrieving widgets from xml
|
||||||
self.xml = gtkgui_helpers.get_glade('adhoc_commands_window.glade')
|
self.xml = gtkgui_helpers.get_glade('adhoc_commands_window.glade')
|
||||||
self.window = self.xml.get_widget('adhoc_commands_window')
|
self.window = self.xml.get_widget('adhoc_commands_window')
|
||||||
|
for name in ('cancel_button', 'back_button', 'forward_button',
|
||||||
|
'execute_button','stages_notebook',
|
||||||
|
'retrieving_commands_stage_vbox',
|
||||||
|
'command_list_stage_vbox','command_list_vbox',
|
||||||
|
'sending_form_stage_vbox'):
|
||||||
|
self.__dict__[name] = self.xml.get_widget(name)
|
||||||
|
|
||||||
# setting initial state of widgets
|
# setting initial stage
|
||||||
self.setup_pulsing(self.xml.get_widget('retrieving_commands_progressbar'))
|
self.stage1()
|
||||||
|
|
||||||
# invoking disco to find commands
|
|
||||||
|
|
||||||
# displaying the window
|
# displaying the window
|
||||||
self.xml.signal_autoconnect(self)
|
self.xml.signal_autoconnect(self)
|
||||||
self.window.show_all()
|
self.window.show_all()
|
||||||
|
|
||||||
|
def on_adhoc_commands_window_destroy(self, window):
|
||||||
|
''' The window dissappeared somehow... clean the environment,
|
||||||
|
Stop pulsing.'''
|
||||||
|
self.remove_pulsing()
|
||||||
|
|
||||||
|
# these functions are set up by appropriate stageX methods
|
||||||
|
def stage_finish(self, *anything): pass
|
||||||
def on_cancel_button_clicked(self, *anything): pass
|
def on_cancel_button_clicked(self, *anything): pass
|
||||||
def on_back_button_clicked(self, *anything): pass
|
def on_back_button_clicked(self, *anything): pass
|
||||||
def on_forward_button_clicked(self, *anything): pass
|
def on_forward_button_clicked(self, *anything): pass
|
||||||
def on_execute_button_clicked(self, *anything): pass
|
def on_execute_button_clicked(self, *anything): pass
|
||||||
|
def on_adhoc_commands_window_destroy(self, *anything): pass
|
||||||
|
|
||||||
|
# stage 1: waiting for command list
|
||||||
|
def stage1(self):
|
||||||
|
'''Prepare the first stage. Request command list,
|
||||||
|
set appropriate state of widgets.'''
|
||||||
|
# close old stage...
|
||||||
|
self.stage_finish()
|
||||||
|
|
||||||
|
# show the stage
|
||||||
|
self.stages_notebook.set_current_page(
|
||||||
|
self.stages_notebook.page_num(
|
||||||
|
self.retrieving_commands_stage_vbox))
|
||||||
|
|
||||||
|
# set widgets' state
|
||||||
|
self.cancel_button.set_sensitive(True)
|
||||||
|
self.back_button.set_sensitive(False)
|
||||||
|
self.forward_button.set_sensitive(False)
|
||||||
|
self.execute_button.set_sensitive(False)
|
||||||
|
|
||||||
|
# request command list
|
||||||
|
self.request_command_list()
|
||||||
|
self.setup_pulsing(
|
||||||
|
self.xml.get_widget('retrieving_commands_progressbar'))
|
||||||
|
|
||||||
|
# setup the callbacks
|
||||||
|
self.stage_finish = self.stage1_finish
|
||||||
|
self.on_cancel_button_clicked = self.stage1_on_cancel_button_clicked
|
||||||
|
|
||||||
|
def stage1_finish(self):
|
||||||
|
self.remove_pulsing()
|
||||||
|
|
||||||
|
def stage1_on_cancel_button_clicked(self, widget):
|
||||||
|
# cancelling in this stage is not critical, so we don't
|
||||||
|
# show any popups to user
|
||||||
|
self.stage1_finish()
|
||||||
|
self.window.destroy()
|
||||||
|
|
||||||
|
# stage 2: choosing the command to execute
|
||||||
|
def stage2(self):
|
||||||
|
'''Populate the command list vbox with radiobuttons
|
||||||
|
(TODO: if there is more commands, maybe some kind of list?),
|
||||||
|
set widgets' state.'''
|
||||||
|
# close old stage
|
||||||
|
self.stage_finish()
|
||||||
|
|
||||||
|
assert len(self.commandlist)>0
|
||||||
|
|
||||||
|
self.stages_notebook.set_current_page(
|
||||||
|
self.stages_notebook.page_num(
|
||||||
|
self.command_list_stage_vbox))
|
||||||
|
|
||||||
|
self.cancel_button.set_sensitive(True)
|
||||||
|
self.back_button.set_sensitive(False)
|
||||||
|
self.forward_button.set_sensitive(True)
|
||||||
|
self.execute_button.set_sensitive(False)
|
||||||
|
|
||||||
|
# build the commands list radiobuttons
|
||||||
|
first_radio = None
|
||||||
|
for (commandnode, commandname) in self.commandlist:
|
||||||
|
radio = gtk.RadioButton(first_radio, label=commandname)
|
||||||
|
if first_radio is None: first_radio = radio
|
||||||
|
self.command_list_vbox.pack_end(radio, expand=False)
|
||||||
|
self.command_list_vbox.show_all()
|
||||||
|
|
||||||
|
self.stage_finish = self.stage_finish
|
||||||
|
self.on_cancel_button_clicked = self.stage2_on_cancel_button_clicked
|
||||||
|
self.on_forward_button_clicked = self.stage2_on_forward_button_clicked
|
||||||
|
|
||||||
|
def stage2_on_cancel_button_clicked(self):
|
||||||
|
self.stage_finish()
|
||||||
|
self.window.destroy()
|
||||||
|
|
||||||
|
def stage2_on_forward_button_clicked(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# helpers to handle pulsing in progressbar
|
||||||
def setup_pulsing(self, progressbar):
|
def setup_pulsing(self, progressbar):
|
||||||
'''Useful to set the progressbar to pulse. Makes a custom
|
'''Set the progressbar to pulse. Makes a custom
|
||||||
function to repeatedly call progressbar.pulse() method.'''
|
function to repeatedly call progressbar.pulse() method.'''
|
||||||
assert self.pulse_id is None
|
assert self.pulse_id is None
|
||||||
assert isinstance(progressbar, Gtk.ProgressBar)
|
assert isinstance(progressbar, gtk.ProgressBar)
|
||||||
assert False
|
|
||||||
|
|
||||||
def callback():
|
def callback():
|
||||||
progressbar.pulse()
|
progressbar.pulse()
|
||||||
return True # important to keep callback be called back!
|
return True # important to keep callback be called back!
|
||||||
|
|
||||||
# 12 times per second (40 miliseconds)
|
# 12 times per second (80 miliseconds)
|
||||||
self.pulse_id = gobject.timeout_add(80, callback)
|
self.pulse_id = gobject.timeout_add(80, callback)
|
||||||
progressbar.pulse() # start from now!
|
|
||||||
|
|
||||||
def remove_pulsing(self):
|
def remove_pulsing(self):
|
||||||
'''Useful to stop pulsing, especially when removing widget.'''
|
'''Stop pulsing, useful when especially when removing widget.'''
|
||||||
if self.pulse_id is not None:
|
if self.pulse_id is not None:
|
||||||
gobject.source_remove(self.pulse_id)
|
gobject.source_remove(self.pulse_id)
|
||||||
self.pulse_id=None
|
self.pulse_id=None
|
||||||
|
|
||||||
|
# handling xml stanzas
|
||||||
|
def request_command_list(self):
|
||||||
|
'''Request the command list. Change stage on delivery.'''
|
||||||
|
query = xmpp.Iq(typ='get', to=xmpp.JID(self.jid), xmlns=xmpp.NS_DISCO_ITEMS)
|
||||||
|
query.setQuerynode(xmpp.NS_COMMANDS)
|
||||||
|
|
||||||
|
def callback(response):
|
||||||
|
'''Called on response to query.'''
|
||||||
|
# is error => error stage
|
||||||
|
error = response.getError()
|
||||||
|
if error is not None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# no commands => no commands stage
|
||||||
|
# commands => command selection stage
|
||||||
|
items = response.getTag('query').getTags('item')
|
||||||
|
if len(items)==0:
|
||||||
|
self.commandlist = []
|
||||||
|
self.stage2() # stageX, where X is the number for error page
|
||||||
|
else:
|
||||||
|
self.commandlist = [(t.getAttr('node'), t.getAttr('name')) for t in items]
|
||||||
|
self.stage2()
|
||||||
|
|
||||||
|
self.account.connection.SendAndCallForResponse(query, callback)
|
||||||
|
|
Loading…
Reference in New Issue