diff --git a/data/gui/archiving_313_preferences_item.ui b/data/gui/archiving_313_preferences_item.ui new file mode 100644 index 000000000..bda22250a --- /dev/null +++ b/data/gui/archiving_313_preferences_item.ui @@ -0,0 +1,143 @@ + + + + + + + + + + + + Always + + + Never + + + + + False + 12 + False + True + dialog + + + + False + vertical + 20 + + + False + end + + + gtk-close + True + True + True + True + True + + + + True + True + 0 + + + + + gtk-ok + True + True + True + True + True + + + + True + True + 1 + + + + + False + False + 0 + + + + + True + False + 5 + 5 + + + True + False + Jabber ID: + 0 + + + 0 + 0 + + + + + True + False + Preference: + 0 + + + 0 + 1 + + + + + 194 + True + True + + + 1 + 0 + + + + + True + False + start + dialog_pref_liststore + + + + 0 + + + + + 1 + 1 + + + + + False + True + 1 + + + + + + diff --git a/data/gui/archiving_313_preferences_window.ui b/data/gui/archiving_313_preferences_window.ui new file mode 100644 index 000000000..c59c442de --- /dev/null +++ b/data/gui/archiving_313_preferences_window.ui @@ -0,0 +1,213 @@ + + + + + + True + False + gtk-add + + + + + + + + + + + + + + + + + Always + + + Roster + + + Never + + + + + True + False + gtk-remove + + + False + 12 + center + 450 + + + + True + False + 5 + 10 + + + 150 + True + True + True + True + in + + + True + True + archive_items_liststore + + + + + + Jabber ID + True + True + 0 + + + + 0 + + + + + + + Preference + True + True + 1 + + + + 1 + + + + + + + + + 0 + 1 + 2 + + + + + True + False + start + 5 + start + + + True + True + True + add_image + + + + False + True + 0 + True + + + + + True + True + True + remove_image + + + + True + True + 1 + True + + + + + 0 + 2 + + + + + True + False + start + 5 + + + True + False + Default: + 0 + + + 0 + 0 + + + + + True + False + start + False + default_pref_liststore + + + + 0 + + + + + 1 + 0 + + + + + 0 + 0 + + + + + gtk-save + True + True + True + end + True + True + + + + 1 + 2 + + + + + + + + + diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index 42c661829..f679366dd 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -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') diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py index b53efd7f2..00c9eb61e 100644 --- a/src/common/connection_handlers_events.py +++ b/src/common/connection_handlers_events.py @@ -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): diff --git a/src/common/message_archiving.py b/src/common/message_archiving.py index b0ba359d1..ec95c6830 100644 --- a/src/common/message_archiving.py +++ b/src/common/message_archiving.py @@ -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): diff --git a/src/dialogs.py b/src/dialogs.py index 280fe0e9c..a11e5d9cc 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -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 diff --git a/src/roster_window.py b/src/roster_window.py index 7da2a4546..e53f809a4 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -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)