correctly set message as read when we print them in chat control
[gajim.git] / src / message_control.py
blob322de94b3e32fc4ab4e4d95367f55ebab6b2e9d4
1 # -*- coding:utf-8 -*-
2 ## src/message_control.py
3 ##
4 ## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
5 ## Nikos Kouremenos <kourem AT gmail.com>
6 ## Copyright (C) 2006-2007 Jean-Marie Traissard <jim AT lapin.org>
7 ## Travis Shirk <travis AT pobox.com>
8 ## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
9 ## Copyright (C) 2007 Julien Pivotto <roidelapluie AT gmail.com>
10 ## Stephan Erb <steve-e AT h3c.de>
11 ## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com>
12 ## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
14 ## This file is part of Gajim.
16 ## Gajim is free software; you can redistribute it and/or modify
17 ## it under the terms of the GNU General Public License as published
18 ## by the Free Software Foundation; version 3 only.
20 ## Gajim is distributed in the hope that it will be useful,
21 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 ## GNU General Public License for more details.
25 ## You should have received a copy of the GNU General Public License
26 ## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
29 import gtkgui_helpers
31 from common import gajim
32 from common import helpers
33 from common.stanza_session import EncryptedStanzaSession, ArchivingStanzaSession
35 # Derived types MUST register their type IDs here if custom behavor is required
36 TYPE_CHAT = 'chat'
37 TYPE_GC = 'gc'
38 TYPE_PM = 'pm'
40 ####################
42 class MessageControl(object):
43 """
44 An abstract base widget that can embed in the gtk.Notebook of a
45 MessageWindow
46 """
48 def __init__(self, type_id, parent_win, widget_name, contact, account, resource = None):
49 # dict { cb id : widget}
50 # keep all registered callbacks of widgets, created by self.xml
51 self.handlers = {}
52 self.type_id = type_id
53 self.parent_win = parent_win
54 self.widget_name = widget_name
55 self.contact = contact
56 self.account = account
57 self.hide_chat_buttons = False
58 self.resource = resource
60 self.session = None
62 gajim.last_message_time[self.account][self.get_full_jid()] = 0
64 self.xml = gtkgui_helpers.get_gtk_builder('%s.ui' % widget_name)
65 self.widget = self.xml.get_object('%s_hbox' % widget_name)
67 def get_full_jid(self):
68 fjid = self.contact.jid
69 if self.resource:
70 fjid += '/' + self.resource
71 return fjid
73 def set_control_active(self, state):
74 """
75 Called when the control becomes active (state is True) or inactive (state
76 is False)
77 """
78 pass # Derived classes MUST implement this method
80 def minimizable(self):
81 """
82 Called to check if control can be minimized
84 Derived classes MAY implement this.
85 """
86 return False
88 def safe_shutdown(self):
89 """
90 Called to check if control can be closed without loosing data.
91 returns True if control can be closed safely else False
93 Derived classes MAY implement this.
94 """
95 return True
97 def allow_shutdown(self, method, on_response_yes, on_response_no,
98 on_response_minimize):
99 """
100 Called to check is a control is allowed to shutdown.
101 If a control is not in a suitable shutdown state this method
102 should call on_response_no, else on_response_yes or
103 on_response_minimize
105 Derived classes MAY implement this.
107 on_response_yes(self)
109 def shutdown(self):
111 Derived classes MUST implement this
113 pass
115 def repaint_themed_widgets(self):
117 Derived classes SHOULD implement this
119 pass
121 def update_ui(self):
123 Derived classes SHOULD implement this
125 pass
127 def toggle_emoticons(self):
129 Derived classes MAY implement this
131 pass
133 def update_font(self):
135 Derived classes SHOULD implement this
137 pass
139 def update_tags(self):
141 Derived classes SHOULD implement this
143 pass
145 def get_tab_label(self, chatstate):
147 Return a suitable tab label string. Returns a tuple such as: (label_str,
148 color) either of which can be None if chatstate is given that means we
149 have HE SENT US a chatstate and we want it displayed
151 Derivded classes MUST implement this.
153 # Return a markup'd label and optional gtk.Color in a tupple like:
154 # return (label_str, None)
155 pass
157 def get_tab_image(self, count_unread=True):
158 # Return a suitable tab image for display.
159 # None clears any current label.
160 return None
162 def prepare_context_menu(self):
164 Derived classes SHOULD implement this
166 return None
168 def chat_buttons_set_visible(self, state):
170 Derived classes MAY implement this
172 self.hide_chat_buttons = state
174 def got_connected(self):
175 pass
177 def got_disconnected(self):
178 pass
180 def get_specific_unread(self):
181 return len(gajim.events.get_events(self.account,
182 self.contact.jid))
184 def set_session(self, session):
185 oldsession = None
186 if hasattr(self, 'session'):
187 oldsession = self.session
189 if oldsession and session == oldsession:
190 return
192 self.session = session
194 if session:
195 session.control = self
197 if oldsession:
198 oldsession.control = None
200 jid = self.contact.jid
201 if self.resource:
202 jid += '/' + self.resource
204 crypto_changed = bool(session and isinstance(session,
205 EncryptedStanzaSession) and session.enable_encryption) != \
206 bool(oldsession and isinstance(oldsession,
207 EncryptedStanzaSession) and oldsession.enable_encryption)
209 archiving_changed = bool(session and isinstance(session,
210 ArchivingStanzaSession) and session.archiving) != \
211 bool(oldsession and isinstance(oldsession,
212 ArchivingStanzaSession) and oldsession.archiving)
214 if crypto_changed or archiving_changed:
215 self.print_session_details()
217 def send_message(self, message, keyID='', type_='chat', chatstate=None,
218 msg_id=None, composing_xep=None, resource=None, user_nick=None,
219 xhtml=None, label=None, callback=None, callback_args=[]):
220 # Send the given message to the active tab.
221 # Doesn't return None if error
222 jid = self.contact.jid
224 message = helpers.remove_invalid_xml_chars(message)
226 original_message = message
227 conn = gajim.connections[self.account]
229 if not self.session:
230 if not resource:
231 if self.resource:
232 resource = self.resource
233 else:
234 resource = self.contact.resource
235 sess = conn.find_controlless_session(jid, resource=resource)
237 if self.resource:
238 jid += '/' + self.resource
240 if not sess:
241 if self.type_id == TYPE_PM:
242 sess = conn.make_new_session(jid, type_='pm')
243 else:
244 sess = conn.make_new_session(jid)
246 self.set_session(sess)
248 # Send and update history
249 conn.send_message(jid, message, keyID, type_=type_, chatstate=chatstate,
250 msg_id=msg_id, composing_xep=composing_xep, resource=self.resource,
251 user_nick=user_nick, session=self.session,
252 original_message=original_message, xhtml=xhtml, label=label, callback=callback,
253 callback_args=callback_args)