Add chatstate setting per contact

This commit is contained in:
Philipp Hörist 2019-04-20 17:43:54 +02:00
parent df13aa4b22
commit 5f84dffca6
8 changed files with 41 additions and 170 deletions

View File

@ -289,6 +289,16 @@ class ChatControl(ChatControlBase):
self.video_action.connect('change-state', self._on_video)
self.parent_win.window.add_action(self.video_action)
chatstate = app.config.get_per(
'contacts', self.contact.jid, 'send_chatstate', 'composing_only')
act = Gio.SimpleAction.new_stateful(
'send-chatstate-' + self.control_id,
GLib.VariantType.new("s"),
GLib.Variant("s", chatstate))
act.connect('change-state', self._on_send_chatstate)
self.parent_win.window.add_action(act)
def update_actions(self):
win = self.parent_win.window
online = app.account_is_connected(self.account)
@ -376,6 +386,11 @@ class ChatControl(ChatControlBase):
state = param.get_boolean()
self.on_jingle_button_toggled(state, 'video')
def _on_send_chatstate(self, action, param):
action.set_state(param)
app.config.set_per('contacts', self.contact.jid,
'send_chatstate', param.get_string())
def subscribe_events(self):
"""
Register listeners to the events class

View File

@ -156,6 +156,7 @@ gajim_common_features = [
nbxmpp.NS_DATA,
nbxmpp.NS_ENCRYPTED,
nbxmpp.NS_PING,
nbxmpp.NS_CHATSTATES,
nbxmpp.NS_TIME_REVISED,
nbxmpp.NS_VERSION,
nbxmpp.NS_ROSTERX,

View File

@ -183,7 +183,6 @@ class Config:
'always_english_wikipedia': [opt_bool, False],
'always_english_wiktionary': [opt_bool, True],
'remote_control': [opt_bool, False, _('If checked, Gajim can be controlled remotely using gajim-remote.'), True],
'outgoing_chat_state_notifications': [opt_str, 'all', _('Sent chat state notifications. Can be one of all, composing_only, disabled.')],
'autodetect_browser_mailer': [opt_bool, True, '', True],
'print_ichat_every_foo_minutes': [opt_int, 5, _('When not printing time for every message (print_time==sometimes), print it every x minutes.')],
'confirm_close_muc': [opt_bool, True, _('Ask before closing a group chat tab/window.')],
@ -421,9 +420,9 @@ class Config:
'bosh_http_pipelining': [opt_bool, False],
'bosh_wait_for_restart_response': [opt_bool, False],
}, {}),
'contacts': ({
'speller_language': [opt_str, '', _('Language for which misspelled words will be checked')],
'send_chatstate': [opt_str, 'composing_only', _('Chat state notifications that are sent to contacts. Possible values: all, composing_only, disabled')],
}, {}),
'encryption': ({
'encryption': [opt_str, '', _('The currently active encryption for that contact')],

View File

@ -1127,8 +1127,6 @@ def update_optional_features(account=None):
features.append(nbxmpp.NS_NICK + '+notify')
if app.config.get_per('accounts', account_, 'subscribe_location'):
features.append(nbxmpp.NS_LOCATION + '+notify')
if app.config.get('outgoing_chat_state_notifactions') != 'disabled':
features.append(nbxmpp.NS_CHATSTATES)
if not app.config.get('ignore_incoming_xhtml'):
features.append(nbxmpp.NS_XHTML_IM)
if app.config.get_per('accounts', account_, 'answer_receipts'):

View File

@ -358,7 +358,8 @@ class Chatstate(BaseModule):
if contact.is_groupchat():
return app.config.get_per(
'rooms', contact.jid, 'send_chatstate', 'composing_only')
return app.config.get('outgoing_chat_state_notifications')
return app.config.get_per(
'contacts', contact.jid, 'send_chatstate', 'composing_only')
def remove_delay_timeout(self, contact):
timeout = self._delay_timeout_ids.get(contact.jid)

View File

@ -42,23 +42,6 @@
<column type="gboolean"/>
</columns>
</object>
<object class="GtkListStore" id="display_chat_state_notifications_liststore">
<columns>
<!-- column-name item -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">All chat states</col>
</row>
<row>
<col id="0" translatable="yes">Composing only</col>
</row>
<row>
<col id="0" translatable="yes">Disabled</col>
</row>
</data>
</object>
<object class="GtkListStore" id="on_event_received_liststore">
<columns>
<!-- column-name item -->
@ -127,23 +110,6 @@
</row>
</data>
</object>
<object class="GtkListStore" id="send_chatstate_notifications_liststore">
<columns>
<!-- column-name item -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">All chat states</col>
</row>
<row>
<col id="0" translatable="yes">Composing only</col>
</row>
<row>
<col id="0" translatable="yes">Disabled</col>
</row>
</data>
</object>
<object class="GtkListStore" id="show_roster_on_startup_liststore">
<columns>
<!-- column-name item -->
@ -756,7 +722,6 @@
<property name="label" translatable="yes">Default Sync Threshold</property>
<property name="use_underline">True</property>
<property name="justify">right</property>
<property name="mnemonic_widget">outgoing_chat_states_combobox</property>
<style>
<class name="dim-label"/>
</style>
@ -1754,107 +1719,6 @@ $T will be replaced by auto-not-available timeout.</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkBox" id="privacy_tab">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">18</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">6</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Gajim can send and receive meta-information related to a conversation you may have with a contact. Here you can specify which chatstates you want to send to the other party.</property>
<property name="halign">start</property>
<property name="label" translatable="yes">S_end chat state notifications</property>
<property name="use_underline">True</property>
<property name="justify">right</property>
<property name="mnemonic_widget">outgoing_chat_states_combobox</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="outgoing_chat_states_combobox">
<property name="width_request">200</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="model">send_chatstate_notifications_liststore</property>
<signal name="changed" handler="on_outgoing_chat_states_combobox_changed" swapped="no"/>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Privacy</property>
<style>
<class name="bold"/>
<class name="margin-top6"/>
</style>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="name">privacy</property>
<property name="title" translatable="yes">Privacy</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkBox" id="style_tab">
<property name="visible">True</property>
@ -2169,7 +2033,7 @@ $T will be replaced by auto-not-available timeout.</property>
<packing>
<property name="name">style</property>
<property name="title" translatable="yes">Style</property>
<property name="position">5</property>
<property name="position">4</property>
</packing>
</child>
<child>
@ -2479,7 +2343,7 @@ to discover one from the server. (Example: stun.iptel.org)</property>
<packing>
<property name="name">audio_video</property>
<property name="title" translatable="yes">Audio/Video</property>
<property name="position">6</property>
<property name="position">5</property>
</packing>
</child>
<child>
@ -2875,7 +2739,7 @@ to discover one from the server. (Example: stun.iptel.org)</property>
<packing>
<property name="name">advanced</property>
<property name="title" translatable="yes">Advanced</property>
<property name="position">7</property>
<property name="position">6</property>
</packing>
</child>
<style>

View File

@ -281,16 +281,6 @@ class Preferences(Gtk.ApplicationWindow):
buf = self._ui.msg_textview.get_buffer()
buf.connect('end-user-action', self.on_msg_textview_changed)
### Privacy tab ###
# Outgoing chat state notifications
st = app.config.get('outgoing_chat_state_notifications')
if st == 'all':
self._ui.outgoing_chat_states_combobox.set_active(0)
elif st == 'composing_only':
self._ui.outgoing_chat_states_combobox.set_active(1)
else: # disabled
self._ui.outgoing_chat_states_combobox.set_active(2)
### Style tab ###
# Themes
self.changed_id = self._ui.theme_combobox.connect(
@ -858,20 +848,6 @@ class Preferences(Gtk.ApplicationWindow):
widget.set_inconsistent(False)
self.on_per_account_checkbutton_toggled(widget, 'ignore_unknown_contacts')
def on_outgoing_chat_states_combobox_changed(self, widget):
active = widget.get_active()
old_value = app.config.get('outgoing_chat_state_notifications')
if active == 0: # all
app.config.set('outgoing_chat_state_notifications', 'all')
elif active == 1: # only composing
app.config.set('outgoing_chat_state_notifications', 'composing_only')
else: # disabled
app.config.set('outgoing_chat_state_notifications', 'disabled')
new_value = app.config.get('outgoing_chat_state_notifications')
if 'disabled' in (old_value, new_value):
# We changed from disabled to sth else or vice versa
helpers.update_optional_features()
### Style ###
@staticmethod
def on_theme_combobox_changed(combobox):

View File

@ -609,6 +609,7 @@ def get_singlechat_menu(control_id, account, jid):
('win.send-file-httpupload-', _('Upload File…')),
('win.send-file-jingle-', _('Send File Directly…')),
]),
(_('Send Chatstate'), ['chatstate']),
('win.invite-contacts-', _('Invite Contacts')),
('win.add-to-roster-', _('Add to Roster')),
('win.toggle-audio-', _('Audio Session')),
@ -617,6 +618,20 @@ def get_singlechat_menu(control_id, account, jid):
('app.browse-history', _('History')),
]
def build_chatstate_menu():
menu = Gio.Menu()
entrys = [
(_('Disabled'), 'disabled'),
(_('Composing only'), 'composing_only'),
(_('All chat states'), 'all')
]
for entry in entrys:
label, setting = entry
action = 'win.send-chatstate-%s::%s' % (control_id, setting)
menu.append(label, action)
return menu
def build_menu(preset):
menu = Gio.Menu()
for item in preset:
@ -634,8 +649,10 @@ def get_singlechat_menu(control_id, account, jid):
menu.append(label, action_name + control_id)
else:
label, sub_menu = item
# This is a submenu
submenu = build_menu(sub_menu)
if 'chatstate' in sub_menu:
submenu = build_chatstate_menu()
else:
submenu = build_menu(sub_menu)
menu.append_submenu(label, submenu)
return menu