Add MAM Preference Dialog

This commit is contained in:
lovetox 2016-10-31 02:11:46 +01:00
parent b51b27d460
commit f961e0be9a
7 changed files with 600 additions and 7 deletions

View File

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<object class="GtkListStore" id="dialog_pref_liststore">
<columns>
<!-- column-name gchararray1 -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">Always</col>
</row>
<row>
<col id="0" translatable="yes">Never</col>
</row>
</data>
</object>
<object class="GtkDialog" id="item_dialog">
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="resizable">False</property>
<property name="destroy_with_parent">True</property>
<property name="type_hint">dialog</property>
<signal name="destroy" handler="on_item_archiving_preferences_window_destroy" swapped="no"/>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">20</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="cancel_button">
<property name="label">gtk-close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="on_cancel_button_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="ok_button">
<property name="label">gtk-ok</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="on_ok_button_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="dialog_grid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">5</property>
<property name="column_spacing">5</property>
<child>
<object class="GtkLabel" id="jid_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Jabber ID:</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="pref_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Preference:</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="jid_entry">
<property name="width_request">194</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="pref_cb">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="model">dialog_pref_liststore</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext2"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

View File

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<object class="GtkImage" id="add_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-add</property>
</object>
<object class="GtkListStore" id="archive_items_liststore">
<columns>
<!-- column-name jid -->
<column type="gchararray"/>
<!-- column-name archive_pref -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkListStore" id="default_pref_liststore">
<columns>
<!-- column-name gchararray1 -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">Always</col>
</row>
<row>
<col id="0" translatable="yes">Roster</col>
</row>
<row>
<col id="0" translatable="yes">Never</col>
</row>
</data>
</object>
<object class="GtkImage" id="remove_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-remove</property>
</object>
<object class="GtkWindow" id="archiving_313_pref">
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="window_position">center</property>
<property name="default_width">450</property>
<signal name="destroy" handler="on_archiving_preferences_window_destroy" swapped="no"/>
<child>
<object class="GtkGrid" id="pref_grid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">5</property>
<property name="column_spacing">10</property>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="height_request">150</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="archive_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">archive_items_liststore</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection2"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn1">
<property name="title" translatable="yes">Jabber ID</property>
<property name="clickable">True</property>
<property name="sort_indicator">True</property>
<property name="sort_column_id">0</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext3"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn2">
<property name="title" translatable="yes">Preference</property>
<property name="clickable">True</property>
<property name="sort_indicator">True</property>
<property name="sort_column_id">1</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext4"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkButtonBox" id="buttonbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="spacing">5</property>
<property name="layout_style">start</property>
<child>
<object class="GtkButton" id="add_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">add_image</property>
<signal name="clicked" handler="on_add_item_button_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="non_homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkButton" id="remove_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">remove_image</property>
<signal name="clicked" handler="on_remove_item_button_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="non_homogeneous">True</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="column_spacing">5</property>
<child>
<object class="GtkLabel" id="default_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Default:</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="default_cb">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">False</property>
<property name="model">default_pref_liststore</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext1"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="save_button">
<property name="label">gtk-save</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">end</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="on_save_button_clicked" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</interface>

View File

@ -1465,6 +1465,8 @@ ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream):
gajim.nec.register_incoming_event(ArchivingErrorReceivedEvent)
gajim.nec.register_incoming_event(
ArchivingPreferencesChangedReceivedEvent)
gajim.nec.register_incoming_event(
Archiving313PreferencesChangedReceivedEvent)
gajim.nec.register_incoming_event(NotificationEvent)
gajim.ged.register_event_handler('http-auth-received', ged.CORE,
@ -2340,6 +2342,7 @@ ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream):
con.RegisterHandler('iq', self._SearchCB, 'result', nbxmpp.NS_SEARCH)
con.RegisterHandler('iq', self._PrivacySetCB, 'set', nbxmpp.NS_PRIVACY)
con.RegisterHandler('iq', self._ArchiveCB, ns=nbxmpp.NS_ARCHIVE)
con.RegisterHandler('iq', self._ArchiveCB, ns=nbxmpp.NS_MAM)
con.RegisterHandler('iq', self._PubSubCB, 'result')
con.RegisterHandler('iq', self._PubSubErrorCB, 'error')
con.RegisterHandler('iq', self._JingleCB, 'result')

View File

@ -1751,9 +1751,8 @@ class ArchivingPreferencesChangedReceivedEvent(nec.NetworkIncomingEvent):
self.conf = {}
self.new_items = {}
self.removed_items = []
if self.stanza.getTag('pref'):
pref = self.stanza.getTag('pref')
pref = self.stanza.getTag('pref', namespace=nbxmpp.NS_ARCHIVE)
if pref:
if pref.getTag('auto'):
self.conf['auto'] = pref.getTagAttr('auto', 'save')
@ -1786,6 +1785,37 @@ class ArchivingPreferencesChangedReceivedEvent(nec.NetworkIncomingEvent):
elif self.stanza.getTag('itemremove'):
for item in pref.getTags('item'):
self.removed_items.append(item.getAttr('jid'))
else:
return
return True
class Archiving313PreferencesChangedReceivedEvent(nec.NetworkIncomingEvent):
name = 'archiving-313-preferences-changed-received'
base_network_events = ['archiving-received']
def generate(self):
self.conn = self.base_event.conn
self.stanza = self.base_event.stanza
self.type_ = self.base_event.type_
self.items = []
self.default = None
self.id = self.stanza.getID()
self.answer = None
if self.type_ != 'result':
return
prefs = self.stanza.getTag('prefs', namespace=nbxmpp.NS_MAM)
if prefs:
self.default = prefs.getAttr('default')
for item in prefs.getTag('always').getTags('jid'):
self.items.append((item.getData(), 'Always'))
for item in prefs.getTag('never').getTags('jid'):
self.items.append((item.getData(), 'Never'))
else:
return
return True
class AccountCreatedEvent(nec.NetworkIncomingEvent):

View File

@ -41,6 +41,7 @@ class ConnectionArchive313(ConnectionArchive):
ConnectionArchive.__init__(self)
self.archiving_313_supported = False
self.mam_awaiting_disco_result = {}
self.iq_answer = []
gajim.ged.register_event_handler('raw-message-received', ged.CORE,
self._nec_raw_message_313_received)
gajim.ged.register_event_handler('agent-info-error-received', ged.CORE,
@ -49,6 +50,9 @@ class ConnectionArchive313(ConnectionArchive):
self._nec_agent_info)
gajim.ged.register_event_handler('mam-decrypted-message-received',
ged.CORE, self._nec_mam_decrypted_message_received)
gajim.ged.register_event_handler(
'archiving-313-preferences-changed-received', ged.CORE,
self._nec_archiving_313_preferences_changed_received)
def cleanup(self):
gajim.ged.remove_event_handler('raw-message-received', ged.CORE,
@ -59,6 +63,13 @@ class ConnectionArchive313(ConnectionArchive):
self._nec_agent_info)
gajim.ged.remove_event_handler('mam-decrypted-message-received',
ged.CORE, self._nec_mam_decrypted_message_received)
gajim.ged.remove_event_handler(
'archiving-313-preferences-changed-received', ged.CORE,
self._nec_archiving_313_preferences_changed_received)
def _nec_archiving_313_preferences_changed_received(self, obj):
if obj.id in self.iq_answer:
obj.answer = True
def _nec_agent_info_error(self, obj):
if obj.jid in self.mam_awaiting_disco_result:
@ -138,6 +149,32 @@ class ConnectionArchive313(ConnectionArchive):
self.awaiting_answers[queryid_] = (MAM_RESULTS_ARRIVED, )
self.connection.send(iq_)
def request_archive_preferences(self):
if not gajim.account_is_connected(self.name):
return
iq = nbxmpp.Iq(typ='get')
id_ = self.connection.getAnID()
iq.setID(id_)
iq.addChild(name='prefs', namespace=nbxmpp.NS_MAM)
self.connection.send(iq)
def set_archive_preferences(self, items, default):
if not gajim.account_is_connected(self.name):
return
iq = nbxmpp.Iq(typ='set')
id_ = self.connection.getAnID()
self.iq_answer.append(id_)
iq.setID(id_)
prefs = iq.addChild(name='prefs', namespace=nbxmpp.NS_MAM, attrs={'default': default})
always = prefs.addChild(name='always')
never = prefs.addChild(name='never')
for item in items:
jid, preference = item
if preference == 'always':
always.addChild(name='jid').setData(jid)
else:
never.addChild(name='jid').setData(jid)
self.connection.send(iq)
class ConnectionArchive136(ConnectionArchive):
def __init__(self):

View File

@ -69,6 +69,7 @@ from common import dataforms
from common.exceptions import GajimGeneralException
from common.connection_handlers_events import MessageOutgoingEvent
class EditGroupsDialog:
"""
Class for the edit group dialog window
@ -4107,6 +4108,166 @@ class ArchivingPreferencesWindow:
del gajim.interface.instances[self.account]['archiving_preferences']
class Archiving313PreferencesWindow:
default_dict = {'always': 0, 'roster': 1, 'never': 2}
def __init__(self, account):
self.account = account
self.idle_id = None
# Connect to glade
self.xml = gtkgui_helpers.get_gtk_builder(
'archiving_313_preferences_window.ui')
self.window = self.xml.get_object('archiving_313_pref')
# Add Widgets
for widget in ('archive_items_liststore', 'default_cb'):
setattr(self, widget, self.xml.get_object(widget))
self.window.set_title(_('Archiving Preferences for %s') % self.account)
gajim.ged.register_event_handler(
'archiving-313-preferences-changed-received', ged.GUI1,
self._nec_archiving_313_changed_received)
gajim.ged.register_event_handler(
'archiving-error-received', ged.GUI1, self._nec_archiving_error)
self.default_cb.set_active(0)
self.set_widget_state(False)
self.window.show_all()
self.xml.connect_signals(self)
self.idle_id = GLib.timeout_add_seconds(3, self._nec_archiving_error)
gajim.connections[self.account].request_archive_preferences()
def set_widget_state(self, state):
for widget in ('default_cb', 'save_button', 'add_button',
'remove_button'):
self.xml.get_object(widget).set_sensitive(state)
def _nec_archiving_313_changed_received(self, obj):
if obj.conn.name != self.account:
return
try:
GLib.source_remove(self.idle_id)
except Exception as e:
log.debug(e)
self.set_widget_state(True)
if obj.answer:
def on_ok(dialog):
self.window.destroy()
dialog = HigDialog(
self.window, Gtk.MessageType.INFO, Gtk.ButtonsType.OK,
_('Success!'), _('Your Archiving Preferences have been saved!'),
on_response_ok=on_ok, on_response_cancel=on_ok)
dialog.popup()
self.default_cb.set_active(self.default_dict[obj.default])
self.archive_items_liststore.clear()
for items in obj.items:
self.archive_items_liststore.append(items)
def _nec_archiving_error(self, obj=None):
if obj and obj.conn.name != self.account:
return
try:
GLib.source_remove(self.idle_id)
except Exception as e:
log.debug(e)
if not obj:
msg = _('We got no response from the Server')
else:
msg = _('We received an error: {}').format(self.error_msg)
dialog = HigDialog(
self.window, Gtk.MessageType.INFO, Gtk.ButtonsType.OK,
_('Error!'), msg)
dialog.popup()
self.set_widget_state(True)
return
def on_add_item_button_clicked(self, widget):
key_name = 'item_archiving_preferences'
if key_name in gajim.interface.instances[self.account]:
gajim.interface.instances[self.account][key_name].window.present()
else:
gajim.interface.instances[self.account][key_name] = \
ItemArchiving313PreferencesWindow(
self.account, self, self.window)
def on_remove_item_button_clicked(self, widget):
archive_view = self.xml.get_object('archive_view')
mod, path = archive_view.get_selection().get_selected_rows()
if path:
iter_ = mod.get_iter(path)
self.archive_items_liststore.remove(iter_)
def on_save_button_clicked(self, widget):
self.set_widget_state(False)
items = []
iter_ = self.default_cb.get_active_iter()
default = self.default_cb.get_model().get_value(iter_, 0)
for item in self.archive_items_liststore:
items.append((item[0].lower(), item[1].lower()))
self.idle_id = GLib.timeout_add_seconds(3, self._nec_archiving_error)
gajim.connections[self.account]. \
set_archive_preferences(items, default.lower())
def on_close_button_clicked(self, widget):
self.window.destroy()
def on_archiving_preferences_window_destroy(self, widget):
gajim.ged.remove_event_handler(
'archiving-313-preferences-changed-received', ged.GUI1,
self._nec_archiving_313_changed_received)
gajim.ged.remove_event_handler(
'archiving-error-received', ged.GUI1, self._nec_archiving_error)
if 'archiving_preferences' in gajim.interface.instances[self.account]:
del gajim.interface.instances[self.account]['archiving_preferences']
class ItemArchiving313PreferencesWindow:
def __init__(self, account, archive, transient):
self.account = account
self.archive = archive
self.xml = gtkgui_helpers.get_gtk_builder(
'archiving_313_preferences_item.ui')
self.window = self.xml.get_object('item_dialog')
self.window.set_transient_for(transient)
# Add Widgets
for widget in ('jid_entry', 'pref_cb'):
setattr(self, widget, self.xml.get_object(widget))
self.window.set_title(_('Add Jabber ID'))
self.pref_cb.set_active(0)
self.window.show_all()
self.xml.connect_signals(self)
def on_ok_button_clicked(self, widget):
if self.pref_cb.get_active() == 0:
pref = 'Always'
else:
pref = 'Never'
text = self.jid_entry.get_text()
if not text:
self.window.destroy()
return
else:
self.archive.archive_items_liststore.append((text, pref))
self.window.destroy()
def on_cancel_button_clicked(self, widget):
self.window.destroy()
def on_item_archiving_preferences_window_destroy(self, widget):
key_name = 'item_archiving_preferences'
if key_name in gajim.interface.instances[self.account]:
del gajim.interface.instances[self.account][key_name]
class PrivacyListWindow:
"""
Window that is used for creating NEW or EDITING already there privacy lists

View File

@ -2830,8 +2830,12 @@ class RosterWindow:
gajim.interface.instances[account]['archiving_preferences'].window.\
present()
else:
gajim.interface.instances[account]['archiving_preferences'] = \
dialogs.ArchivingPreferencesWindow(account)
if gajim.connections[account].archiving_313_supported:
gajim.interface.instances[account]['archiving_preferences'] = \
dialogs.Archiving313PreferencesWindow(account)
else:
gajim.interface.instances[account]['archiving_preferences'] = \
dialogs.ArchivingPreferencesWindow(account)
def on_privacy_lists_menuitem_activate(self, widget, account):
if 'privacy_lists' in gajim.interface.instances[account]:
@ -6099,8 +6103,10 @@ class RosterWindow:
self.on_privacy_lists_menuitem_activate, account)
else:
privacy_lists_menuitem.set_sensitive(False)
if gajim.connections[account].archive_pref_supported:
archiving_preferences_menuitem.connect('activate',
if gajim.connections[account].archive_pref_supported or \
gajim.connections[account].archiving_313_supported:
archiving_preferences_menuitem.connect(
'activate',
self.on_archiving_preferences_menuitem_activate, account)
else:
archiving_preferences_menuitem.set_sensitive(False)