Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/gajim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYann Leboulanger <asterix@lagaule.org>2007-03-11 23:14:53 +0300
committerYann Leboulanger <asterix@lagaule.org>2007-03-11 23:14:53 +0300
commit5920d03aeec3e4be5871b2dbb0a1f100ec17760e (patch)
tree1c2277c6dc033b3c84c2a4d4318159a6026b4c42
parent81c0b528aed3d437b51dc877da747ce758c28e41 (diff)
ability to destroy a room when we are owner, give a reason and alternative room
jid. fixes #3031
-rw-r--r--data/glade/gc_control_popup_menu.glade30
-rw-r--r--src/common/connection.py14
-rw-r--r--src/common/connection_handlers.py29
-rw-r--r--src/dialogs.py56
-rw-r--r--src/groupchat_control.py37
5 files changed, 153 insertions, 13 deletions
diff --git a/data/glade/gc_control_popup_menu.glade b/data/glade/gc_control_popup_menu.glade
index 537c4daad..af8dba982 100644
--- a/data/glade/gc_control_popup_menu.glade
+++ b/data/glade/gc_control_popup_menu.glade
@@ -12,7 +12,7 @@
<property name="use_underline">True</property>
<child internal-child="image">
- <widget class="GtkImage" id="image1359">
+ <widget class="GtkImage" id="image1378">
<property name="visible">True</property>
<property name="stock">gtk-justify-fill</property>
<property name="icon_size">1</property>
@@ -31,7 +31,7 @@
<property name="use_underline">True</property>
<child internal-child="image">
- <widget class="GtkImage" id="image1360">
+ <widget class="GtkImage" id="image1379">
<property name="visible">True</property>
<property name="stock">gtk-preferences</property>
<property name="icon_size">1</property>
@@ -45,12 +45,32 @@
</child>
<child>
+ <widget class="GtkImageMenuItem" id="destroy_room_menuitem">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Destroy room</property>
+ <property name="use_underline">True</property>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image1380">
+ <property name="visible">True</property>
+ <property name="stock">gtk-delete</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
<widget class="GtkImageMenuItem" id="change_subject_menuitem">
<property name="label" translatable="yes">Change _Subject</property>
<property name="use_underline">True</property>
<child internal-child="image">
- <widget class="GtkImage" id="image1361">
+ <widget class="GtkImage" id="image1381">
<property name="visible">True</property>
<property name="stock">gtk-edit</property>
<property name="icon_size">1</property>
@@ -69,7 +89,7 @@
<property name="use_underline">True</property>
<child internal-child="image">
- <widget class="GtkImage" id="image1362">
+ <widget class="GtkImage" id="image1382">
<property name="visible">True</property>
<property name="stock">gtk-redo</property>
<property name="icon_size">1</property>
@@ -88,7 +108,7 @@
<property name="use_underline">True</property>
<child internal-child="image">
- <widget class="GtkImage" id="image1363">
+ <widget class="GtkImage" id="image1383">
<property name="visible">True</property>
<property name="stock">gtk-add</property>
<property name="icon_size">1</property>
diff --git a/src/common/connection.py b/src/common/connection.py
index 45c91ed12..614227077 100644
--- a/src/common/connection.py
+++ b/src/common/connection.py
@@ -1160,10 +1160,24 @@ class Connection(ConnectionHandlers):
self.connection.send(msg_iq)
def request_gc_config(self, room_jid):
+ if not self.connection:
+ return
iq = common.xmpp.Iq(typ = 'get', queryNS = common.xmpp.NS_MUC_OWNER,
to = room_jid)
self.connection.send(iq)
+ def destroy_gc_room(self, room_jid, reason = '', jid = ''):
+ if not self.connection:
+ return
+ iq = common.xmpp.Iq(typ = 'set', queryNS = common.xmpp.NS_MUC_OWNER,
+ to = room_jid)
+ destroy = iq.getTag('query').setTag('destroy')
+ if reason:
+ destroy.setTagData('reason', reason)
+ if jid:
+ destroy.setAttr('jid', jid)
+ self.connection.send(iq)
+
def send_gc_status(self, nick, jid, show, status):
if not self.connection:
return
diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py
index b21de9ec6..2d853c84e 100644
--- a/src/common/connection_handlers.py
+++ b/src/common/connection_handlers.py
@@ -1547,6 +1547,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
timestamp = None
is_gc = False # is it a GC presence ?
sigTag = None
+ ns_muc_user_x = None
avatar_sha = None
# JEP-0172 User Nickname
user_nick = prs.getTagData('nick')
@@ -1558,16 +1559,18 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
namespace = x.getNamespace()
if namespace.startswith(common.xmpp.NS_MUC):
is_gc = True
- if namespace == common.xmpp.NS_SIGNED:
+ if namespace == common.xmpp.NS_MUC_USER and x.getTag('destroy'):
+ ns_muc_user_x = x
+ elif namespace == common.xmpp.NS_SIGNED:
sigTag = x
- if namespace == common.xmpp.NS_VCARD_UPDATE:
+ elif namespace == common.xmpp.NS_VCARD_UPDATE:
avatar_sha = x.getTagData('photo')
- if namespace == common.xmpp.NS_DELAY:
+ elif namespace == common.xmpp.NS_DELAY:
# JEP-0091
tim = prs.getTimestamp()
tim = time.strptime(tim, '%Y%m%dT%H:%M:%S')
timestamp = time.localtime(timegm(tim))
- if namespace == 'http://delx.cjb.net/protocol/roster-subsync':
+ elif namespace == 'http://delx.cjb.net/protocol/roster-subsync':
# see http://trac.gajim.org/ticket/326
agent = gajim.get_server_from_jid(jid_stripped)
if self.connection.getRoster().getItem(agent): # to be sure it's a transport contact
@@ -1667,10 +1670,24 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
else:
# save sha in mem NOW
self.vcard_shas[who] = avatar_sha
+ if ns_muc_user_x:
+ # Room has been destroyed. see
+ # http://www.xmpp.org/extensions/xep-0045.html#destroyroom
+ reason = _('Room has been destroyed')
+ destroy = ns_muc_user_x.getTag('destroy')
+ r = destroy.getTagData('reason')
+ if r:
+ reason += ' (%s)' % r
+ jid = destroy.getAttr('jid')
+ if jid:
+ reason += '\n' + _('You can join this room instead: %s') % jid
+ statusCode = 'destroyed'
+ else:
+ reason = prs.getReason()
+ statusCode = prs.getStatusCode()
self.dispatch('GC_NOTIFY', (jid_stripped, show, status, resource,
prs.getRole(), prs.getAffiliation(), prs.getJid(),
- prs.getReason(), prs.getActor(), prs.getStatusCode(),
- prs.getNewNick()))
+ reason, prs.getActor(), statusCode, prs.getNewNick()))
return
if ptype == 'subscribe':
diff --git a/src/dialogs.py b/src/dialogs.py
index 279f67deb..8155753ea 100644
--- a/src/dialogs.py
+++ b/src/dialogs.py
@@ -1049,6 +1049,62 @@ class InputDialog:
self.dialog.destroy()
return response
+class DubbleInputDialog:
+ '''Class for Dubble Input dialog'''
+ def __init__(self, title, label_str1, label_str2, input_str1 = None,
+ input_str2 = None, is_modal = True, ok_handler = None,
+ cancel_handler = None):
+ # if modal is True you also need to call get_response()
+ # and ok_handler won't be used
+ self.xml = gtkgui_helpers.get_glade('dubbleinput_dialog.glade')
+ self.dialog = self.xml.get_widget('dubbleinput_dialog')
+ label1 = self.xml.get_widget('label1')
+ self.input_entry1 = self.xml.get_widget('input_entry1')
+ label2 = self.xml.get_widget('label2')
+ self.input_entry2 = self.xml.get_widget('input_entry2')
+ self.dialog.set_title(title)
+ label1.set_markup(label_str1)
+ label2.set_markup(label_str2)
+ self.cancel_handler = cancel_handler
+ if input_str1:
+ self.input_entry1.set_text(input_str1)
+ self.input_entry1.select_region(0, -1) # select all
+ if input_str2:
+ self.input_entry2.set_text(input_str2)
+ self.input_entry2.select_region(0, -1) # select all
+
+ self.is_modal = is_modal
+ if not is_modal and ok_handler is not None:
+ self.ok_handler = ok_handler
+ okbutton = self.xml.get_widget('okbutton')
+ okbutton.connect('clicked', self.on_okbutton_clicked)
+ cancelbutton = self.xml.get_widget('cancelbutton')
+ cancelbutton.connect('clicked', self.on_cancelbutton_clicked)
+ self.xml.signal_autoconnect(self)
+ self.dialog.show_all()
+
+ def on_dubbleinput_dialog_destroy(self, widget):
+ if self.cancel_handler:
+ self.cancel_handler()
+
+ def on_okbutton_clicked(self, widget):
+ user_input1 = self.input_entry1.get_text().decode('utf-8')
+ user_input2 = self.input_entry2.get_text().decode('utf-8')
+ self.dialog.destroy()
+ if isinstance(self.ok_handler, tuple):
+ self.ok_handler[0](user_input1, user_input2, *self.ok_handler[1:])
+ else:
+ self.ok_handler(user_input1, user_input2)
+
+ def on_cancelbutton_clicked(self, widget):
+ self.dialog.destroy()
+
+ def get_response(self):
+ if self.is_modal:
+ response = self.dialog.run()
+ self.dialog.destroy()
+ return response
+
class SubscriptionRequestWindow:
def __init__(self, jid, text, account, user_nick = None):
xml = gtkgui_helpers.get_glade('subscription_request_window.glade')
diff --git a/src/groupchat_control.py b/src/groupchat_control.py
index d07fecf42..ecb93ba4a 100644
--- a/src/groupchat_control.py
+++ b/src/groupchat_control.py
@@ -222,6 +222,11 @@ class GroupchatControl(ChatControlBase):
self._on_configure_room_menuitem_activate)
self.handlers[id] = widget
+ widget = xm.get_widget('destroy_room_menuitem')
+ id = widget.connect('activate',
+ self._on_destroy_room_menuitem_activate)
+ self.handlers[id] = widget
+
widget = xm.get_widget('change_subject_menuitem')
id = widget.connect('activate',
self._on_change_subject_menuitem_activate)
@@ -472,18 +477,21 @@ class GroupchatControl(ChatControlBase):
sets sensitivity state for configure_room'''
menu = self.gc_popup_menu
childs = menu.get_children()
- # hide chat buttons
- childs[5].set_active(self.hide_chat_buttons_current)
+ # Check compact view menuitem
+ childs[6].set_active(self.hide_chat_buttons_current)
if gajim.gc_connected[self.account][self.room_jid]:
c = gajim.contacts.get_gc_contact(self.account, self.room_jid,
self.nick)
if c.affiliation not in ('owner', 'admin'):
childs[1].set_sensitive(False)
+ if c.affiliation != 'owner':
+ childs[2].set_sensitive(False)
else:
# We are not connected to this groupchat, disable unusable menuitems
childs[1].set_sensitive(False)
childs[2].set_sensitive(False)
childs[3].set_sensitive(False)
+ childs[4].set_sensitive(False)
return menu
def on_message(self, nick, msg, tim, has_timestamp = False, xhtml = None):
@@ -888,6 +896,8 @@ class GroupchatControl(ChatControlBase):
os.remove(files[old_file])
os.rename(old_file, files[old_file])
self.print_conversation(s, 'info')
+ elif statusCode == 'destroyed': # Room has been destroyed
+ self.print_conversation(reason, 'info')
if len(gajim.events.get_events(self.account,
self.room_jid + '/' + nick)) == 0:
@@ -1442,6 +1452,29 @@ class GroupchatControl(ChatControlBase):
gajim.interface.instances[self.account]['gc_config'][self.room_jid]\
= config.GroupchatConfigWindow(self.account, self.room_jid)
+ def _on_destroy_room_menuitem_activate(self, widget):
+ # Ask for a reason
+ instance = dialogs.DubbleInputDialog(_('Destroying %s') % self.room_jid,
+ _('You are going to definitively destroy this room.\n'
+ 'You may specify a reason below:'),
+ _('You may also enter an alternate venue:'))
+ response = instance.get_response()
+ if response == gtk.RESPONSE_OK:
+ reason = instance.input_entry1.get_text().decode('utf-8')
+ jid = instance.input_entry2.get_text().decode('utf-8')
+ # Test jid
+ try:
+ jid = helpers.parse_jid(jid)
+ except:
+ ErrorDialog(_('Invalid group chat Jabber ID'),
+ _('The group chat Jabber ID has not allowed characters.'))
+ return
+ else:
+ # Abord destroy operation
+ return
+ gajim.connections[self.account].destroy_gc_room(self.room_jid, reason,
+ jid)
+
def _on_bookmark_room_menuitem_activate(self, widget):
bm = {
'name': self.name,