diff --git a/src/chat_control.py b/src/chat_control.py index f5b16f3b0..8c4573b24 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -41,6 +41,7 @@ APP = i18n.APP GTKGUI_GLADE = 'gtkgui.glade' +################################################################################ class ChatControlBase(MessageControl): # FIXME '''TODO @@ -113,6 +114,8 @@ class ChatControlBase(MessageControl): dialogs.ErrorDialog(unicode(msg), _('If that is not your language for which you want to highlight misspelled words, then please set your $LANG as appropriate. Eg. for French do export LANG=fr_FR or export LANG=fr_FR.UTF-8 in ~/.bash_profile or to make it global in /etc/profile.\n\nHighlighting misspelled words feature will not be used')).get_response() gajim.config.set('use_speller', False) + self.print_time_timeout_id = None + def _paint_banner(self): '''Repaint banner with theme color''' theme = gajim.config.get('roster_theme') @@ -371,6 +374,25 @@ class ChatControlBase(MessageControl): start, end = buffer.get_bounds() buffer.delete(start, end) + def print_time_timeout(self, arg): + if gajim.config.get('print_time') == 'sometimes': + conv_textview = self.conv_textview + buffer = conv_textview.get_buffer() + end_iter = buffer.get_end_iter() + tim = time.localtime() + tim_format = time.strftime('%H:%M', tim) + buffer.insert_with_tags_by_name(end_iter, '\n' + tim_format, + 'time_sometimes') + # scroll to the end of the textview + if conv_textview.at_the_end(): + # we are at the end + conv_textview.scroll_to_end() + return True # loop again + if self.print_time_timeout_id: + del self.print_time_timeout_id + return False + +################################################################################ class ChatControl(ChatControlBase): '''A control for standard 1-1 chat''' TYPE_ID = 1 @@ -591,7 +613,7 @@ class ChatControl(ChatControlBase): self.kbd_activity_in_last_30_secs = False def print_conversation(self, text, frm = '', tim = None, - encrypted = False, subject = None): + encrypted = False, subject = None): '''Print a line in the conversation: if contact is set to status: it's a status message if contact is set to another value: it's an outgoing message diff --git a/src/config.py b/src/config.py index ff68be0d9..5ff022d76 100644 --- a/src/config.py +++ b/src/config.py @@ -502,7 +502,7 @@ class PreferencesWindow: def toggle_emoticons(self): '''Update emoticons state in Opened Chat Windows''' - for win in gajim.interface.msg_win_mgr.windows.values(): + for win in gajim.interface.msg_win_mgr.windows(): win.toggle_emoticons() def on_add_remove_emoticons_button_clicked(self, widget): @@ -639,13 +639,8 @@ class PreferencesWindow: def update_print_time(self): '''Update time in Opened Chat Windows''' - for a in gajim.connections: - window = gajim.interface.instances[a]['chats'] - if window.has_key('tabbed'): - window['tabbed'].update_print_time() - else: - for jid in window.keys(): - window[jid].update_print_time() + for msg_win in gajim.interface.msg_win_mgr.windows(): + msg_win.update_print_time() def on_time_never_radiobutton_toggled(self, widget): if widget.get_active(): @@ -683,7 +678,7 @@ class PreferencesWindow: def update_text_tags(self): '''Update color tags in Opened Chat Windows''' - for win in gajim.interface.msg_win_mgr.windows.values(): + for win in gajim.interface.msg_win_mgr.windows(): win.update_tags() def on_preference_widget_color_set(self, widget, text): @@ -701,7 +696,7 @@ class PreferencesWindow: def update_text_font(self): '''Update text font in Opened Chat Windows''' - for win in gajim.interface.msg_win_mgr.windows.values(): + for win in gajim.interface.msg_win_mgr.windows(): win.update_font() def on_incoming_msg_colorbutton_color_set(self, widget): diff --git a/src/dialogs.py b/src/dialogs.py index 46063b0e6..d279ea9d0 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -953,22 +953,17 @@ class PopupNotificationWindow: gajim.interface.roster.add_contact_to_roster(contact.jid, self.account) - if self.msg_type == 'pm': # It's a private message - gajim.interface.roster.new_chat(contact, self.account) - chats_window = gajim.interface.instances[self.account]['chats'][self.jid] - chats_window.set_active_tab(self.jid) - chats_window.window.present() - elif self.msg_type in ('normal', 'file-request', 'file-request-error', + if self.msg_type in ('normal', 'file-request', 'file-request-error', 'file-send-error', 'file-error', 'file-stopped', 'file-completed'): # Get the first single message event ev = gajim.get_first_event(self.account, self.jid, self.msg_type) gajim.interface.roster.open_event(self.account, self.jid, ev) - - else: # 'chat' + else: # chat or pm + assert(self.msg_type == 'chat' or self.msg_type == 'pm') gajim.interface.roster.new_chat(contact, self.account) - chats_window = gajim.interface.instances[self.account]['chats'][self.jid] - chats_window.set_active_tab(self.jid) - chats_window.window.present() + msg_window = gajim.interface.msg_win_mgr.get_window(self.jid) + msg_window.set_active_tab(self.jid) + msg_window.window.present() self.adjust_height_and_move_popup_notification_windows() diff --git a/src/gajim.py b/src/gajim.py index 21be9bede..6a63c9c69 100755 --- a/src/gajim.py +++ b/src/gajim.py @@ -375,6 +375,7 @@ class Interface: if gajim.config.get_per('soundevents', 'contact_connected', 'enabled') and gajim.allow_notifications[account]: helpers.play_sound('contact_connected') + # FIXME if not self.instances[account]['chats'].has_key(jid) and \ not gajim.awaiting_events[account].has_key(jid) and \ gajim.config.get('notify_on_signin') and \ @@ -395,6 +396,7 @@ class Interface: if gajim.config.get_per('soundevents', 'contact_disconnected', 'enabled'): helpers.play_sound('contact_disconnected') + # FIXME if not self.instances[account]['chats'].has_key(jid) and \ not gajim.awaiting_events[account].has_key(jid) and \ gajim.config.get('notify_on_signout'): @@ -437,6 +439,7 @@ class Interface: if self.instances[account]['gc'].has_key(jid): # it's a Private Message nick = gajim.get_nick_from_fjid(array[0]) fjid = array[0] + # FIXME if not self.instances[account]['chats'].has_key(fjid) and \ not gajim.awaiting_events[account].has_key(fjid): if show_notification: @@ -452,6 +455,7 @@ class Interface: # Handle chat states contact = gajim.get_first_contact_instance_from_jid(account, jid) + # FIXME if self.instances[account]['chats'].has_key(jid): chat_win = self.instances[account]['chats'][jid] if chatstate is not None: # he or she sent us reply, so he supports jep85 @@ -472,6 +476,7 @@ class Interface: return first = False + # FIXME if not self.instances[account]['chats'].has_key(jid) and \ not gajim.awaiting_events[account].has_key(jid): first = True @@ -509,6 +514,7 @@ class Interface: if jid in gcs: if len(jids) > 1: # it's a pm nick = jids[1] + # FIXME if not self.instances[account]['chats'].has_key(fjid): gc = gcs[jid] tv = gc.list_treeview[jid] @@ -521,6 +527,7 @@ class Interface: c = Contact(jid = fjid, name = nick, groups = ['none'], show = show, ask = 'none') self.roster.new_chat(c, account) + # FIXME self.instances[account]['chats'][fjid].print_conversation( 'Error %s: %s' % (array[1], array[2]), fjid, 'status') return @@ -676,6 +683,7 @@ class Interface: # show avatar in chat win = None + # FIXME if self.instances[account]['chats'].has_key(jid): win = self.instances[account]['chats'][jid] elif resource and self.instances[account]['chats'].has_key( @@ -710,6 +718,7 @@ class Interface: show = array[1] status = array[2] # print status in chat window and update status/GPG image + # FIXME if self.instances[account]['chats'].has_key(fjid): contact = self.instances[account]['chats'][fjid].contacts[fjid] contact.show = show @@ -1273,12 +1282,14 @@ class Interface: if wins['gc'].has_key(jid): w = wins['gc'][jid] elif typ == 'chat': + # FIXME if wins['chats'].has_key(jid): w = wins['chats'][jid] else: self.roster.new_chat(gajim.contacts[account][jid][0], account) w = wins['chats'][jid] elif typ == 'pm': + # FIXME if wins['chats'].has_key(jid): w = wins['chats'][jid] else: diff --git a/src/message_window.py b/src/message_window.py index a9ebde1c6..1d8096930 100644 --- a/src/message_window.py +++ b/src/message_window.py @@ -290,6 +290,24 @@ class MessageWindow: return ctl return None + def controls(self): + for ctl in self._controls.values(): + yield ctl + + def update_print_time(self): + if gajim.config.get('print_time') != 'sometimes': + for ctl in self.controls(): + if ctl.print_time_timeout_id: + gobject.source_remove(ctl.print_time_timeout_id) + del ctl.print_time_timeout_id + else: + for ctl in self.controls(): + if not ctl.print_time_timeout_id: + ctl.print_time_timeout() + ctl.print_time_timeout_id = gobject.timeout_add(300000, + ctl.print_time_timeout, None) + + class MessageWindowMgr: '''A manager and factory for MessageWindow objects''' @@ -307,7 +325,7 @@ class MessageWindowMgr: CONFIG_ALWAYS: The key is MessageWindowMgr.MAIN_WIN CONFIG_PERACCT: The key is the account name CONFIG_PERTYPE: The key is a message type constant''' - self.windows = {} + self._windows = {} # Map the mode to a int constant for frequent compares mode = gajim.config.get('one_message_window') self.mode = common.config.opt_one_window_types.index(mode) @@ -321,7 +339,7 @@ class MessageWindowMgr: return win def _gtkWinToMsgWin(self, gtk_win): - for w in self.windows.values(): + for w in self._windows.values(): if w.window == gtk_win: return w return None @@ -335,11 +353,10 @@ class MessageWindowMgr: # TODO: Clean up windows def get_window(self, jid): - for win in self.windows.values(): + for win in self._windows.values(): if win.get_control_from_jid(jid): return win return None - def has_window(self, jid): return self.get_window(jid) @@ -356,16 +373,30 @@ class MessageWindowMgr: win = None try: - win = self.windows[key] + win = self._windows[key] except KeyError: # FIXME print "Creating tabbed chat window for '%s'" % str(key) win = self._new_window() - self.windows[key] = win + self._windows[key] = win assert(win) return win + def get_control(self, jid): + win = self.get_window(jid) + if win: + return win.get_control_from_jid(jid) + return None + + def windows(self): + for w in self._windows.values(): + yield w + def controls(self): + for w in self._windows: + for c in w.controls(): + yield c + class MessageControl(gtk.VBox): '''An abstract base widget that can embed in the gtk.Notebook of a MessageWindow''' @@ -381,6 +412,7 @@ class MessageControl(gtk.VBox): self.compact_view_always = False self.compact_view_current = False self.nb_unread = 0 + self.print_time_timeout_id = None self.xml = gtk.glade.XML(GTKGUI_GLADE, widget_name, APP) self.widget = self.xml.get_widget(widget_name) @@ -399,6 +431,12 @@ class MessageControl(gtk.VBox): pass # NOTE: Derived classes SHOULD implement this def update_tags(self): pass # NOTE: Derived classes SHOULD implement this + def print_time_timeout(self, arg): + # NOTE: Derived classes SHOULD implement this + if self.print_time_timeout_id: + gobject.source_remove(self.print_time_timeout_id) + del self.print_time_timeout_id + return False def markup_tab_label(self, label_str, chatstate): # NOTE: Derived classes SHOULD implement this # Reurn a markup'd label and optional gtk.Color diff --git a/src/remote_control.py b/src/remote_control.py index e6bb2a777..ac611d89e 100644 --- a/src/remote_control.py +++ b/src/remote_control.py @@ -236,7 +236,7 @@ class SignalObject(DbusPrototype): first_connected_acct = None for acct in accounts: if gajim.connections[acct].connected > 1: # account is online - if gajim.interface.instances[acct]['chats'].has_key(jid): + if gajim.interface.msg_win_mgr.has_window(jid): connected_account = acct break # jid is in roster @@ -257,7 +257,7 @@ class SignalObject(DbusPrototype): if connected_account: gajim.interface.roster.new_chat_from_jid(connected_account, jid) # preserve the 'steal focus preservation' - win = gajim.interface.instances[connected_account]['chats'][jid].window + win = gajim.interface.msg_win_mgr.get_window(jid].window if win.get_property('visible'): win.window.focus() return True diff --git a/src/roster_window.py b/src/roster_window.py index 68d27a7b8..91785a953 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -709,19 +709,21 @@ class RosterWindow: self.add_contact_to_roster(contact.jid, account) self.draw_contact(contact.jid, account) # print status in chat window and update status/GPG image - if gajim.interface.instances[account]['chats'].has_key(contact.jid): + if gajim.interface.msg_win_mgr.has_window(contact.jid): jid = contact.jid - gajim.interface.instances[account]['chats'][jid].set_state_image(jid) + win = gajim.interface.msg_win_mgr.get_window(contact.jid) + ctl = win.get_control_from_jid(jid) + ctl.update_state() + name = contact.name if contact.resource != '': name += '/' + contact.resource uf_show = helpers.get_uf_show(show) - gajim.interface.instances[account]['chats'][jid].print_conversation( - _('%s is now %s (%s)') % (name, uf_show, status), jid, 'status') - - if contact == gajim.get_contact_instance_with_highest_priority(\ - account, contact.jid): - gajim.interface.instances[account]['chats'][jid].draw_name_banner(contact) + ctl.print_conversation(_('%s is now %s (%s)') % (name, uf_show, status), + 'status') + if contact == gajim.get_contact_instance_with_highest_priority(account, + contact.jid): + ctl.draw_banner() def on_info(self, widget, user, account): '''Call vcard_information_window class to display user's information''' @@ -897,8 +899,9 @@ class RosterWindow: keys[user.jid] = keyID[0] for u in gajim.contacts[account][user.jid]: u.keyID = keyID[0] - if gajim.interface.instances[account]['chats'].has_key(user.jid): - gajim.interface.instances[account]['chats'][user.jid].draw_widgets(user) + if gajim.interface.msg_win_mgr.has_window(user.jid): + ctl = gajim.interface.msg_win_mgr.get_control(user.jid) + ctl.draw_widgets() keys_str = '' for jid in keys: keys_str += jid + ' ' + keys[jid] + ' ' @@ -1356,17 +1359,19 @@ _('If "%s" accepts this request you will know his or her status.') %jid) model = self.tree.get_model() iter = model.get_iter(path) type = model[iter][C_TYPE] - # FIXME if type in ('agent', 'contact'): account = model[iter][C_ACCOUNT].decode('utf-8') jid = model[iter][C_JID].decode('utf-8') - if gajim.interface.instances[account]['chats'].has_key(jid): - gajim.interface.instances[account]['chats'][jid].set_active_tab(jid) + win = None + if gajim.interface.msg_win_mgr.has_window(jid): + win = gajim.interface.msg_win_mgr.get_window(jid) elif gajim.contacts[account].has_key(jid): - c = gajim.get_contact_instance_with_highest_priority(account, jid) + c = gajim.get_contact_instance_with_highest_priority(account, + jid) self.new_chat(c, account) - gajim.interface.instances[account]['chats'][jid].set_active_tab(jid) - gajim.interface.instances[account]['chats'][jid].window.present() + win = gajim.interface.msg_win_mgr.get_window(jid) + win.set_active_tab(jid) + win.window.present() elif type == 'account': account = model[iter][C_ACCOUNT] if account != 'all': @@ -1412,7 +1417,6 @@ _('If "%s" accepts this request you will know his or her status.') %jid) _('Contact "%s" will be removed from your roster') % (user.name), _('By removing this contact you also by default remove authorization resulting in him or her always seeing you as offline.'), _('I want this contact to know my status after removal')) - # FIXME: # maybe use 2 optionboxes from which the user can select? (better) if window.get_response() == gtk.RESPONSE_OK: remove_auth = True @@ -1422,7 +1426,7 @@ _('If "%s" accepts this request you will know his or her status.') %jid) for u in gajim.contacts[account][user.jid]: self.remove_contact(u, account) del gajim.contacts[account][u.jid] - if user.jid in gajim.interface.instances[account]['chats']: + if gajim.interface.msg_win_mgr.has_window(user.jid): user1 = Contact(jid = user.jid, name = user.name, groups = [_('not in the roster')], show = 'not in the roster', status = '', ask = 'none', keyID = user.keyID) @@ -1657,11 +1661,8 @@ _('If "%s" accepts this request you will know his or her status.') %jid) ChatControl.TYPE_ID) chat_control = ChatControl(mw, contact, account) mw.new_tab(chat_control) - # REMOVE: eliminate all usage of gajim.interface.instances[account]['chats'] - ################################## def new_chat_from_jid(self, account, jid): - # FIXME if gajim.contacts[account].has_key(jid): contact = gajim.get_contact_instance_with_highest_priority(account, jid) else: @@ -1676,10 +1677,11 @@ _('If "%s" accepts this request you will know his or her status.') %jid) gajim.contacts[account][jid] = [contact] self.add_contact_to_roster(contact.jid, account) - if not gajim.interface.instances[account]['chats'].has_key(jid): + if not gajim.interface.msg_win_mgr.has_window(contact.jid): self.new_chat(contact, account) - gajim.interface.instances[account]['chats'][jid].set_active_tab(jid) - gajim.interface.instances[account]['chats'][jid].window.present() + mw = gajim.interface.msg_win_mgr.get_window(contact.jid) + mw.set_active_tab(jid) + mw.window.present() def new_room(self, jid, nick, account): # FIXME: Not contact. Use jid and nick @@ -1690,12 +1692,9 @@ _('If "%s" accepts this request you will know his or her status.') %jid) GroupchatControl.TYPE_ID) gc_control = ChatControl(mw, contact, account) mw.new_tab(gc_control) - # REMOVE: eliminate all usage of gajim.interface.instances[account]['gc'] - ################################## def on_message(self, jid, msg, tim, account, encrypted = False, - # FIXME - msg_type = '', subject = None, resource = ''): + msg_type = '', subject = None, resource = ''): '''when we receive a message''' if not gajim.contacts[account].has_key(jid): keyID = '' @@ -1736,13 +1735,14 @@ _('If "%s" accepts this request you will know his or her status.') %jid) return # We print if window is opened and it's not a single message - if gajim.interface.instances[account]['chats'].has_key(jid) and \ - msg_type != 'normal': - typ = '' - if msg_type == 'error': - typ = 'status' - gajim.interface.instances[account]['chats'][jid].print_conversation( - msg, jid, typ, tim = tim, encrypted = encrypted, subject = subject) + if gajim.interface.msg_win_mgr.has_window(jid) and msg_type != 'normal': +# FIXME: Remove +# typ = '' +# if msg_type == 'error': +# typ = 'status' + ctl = gajim.interface.msg_win_mgr.get_control(jid) + ctl.print_conversation(msg, jid, tim = tim, encrypted = encrypted, + subject = subject) return # We save it in a queue @@ -1754,7 +1754,7 @@ _('If "%s" accepts this request you will know his or her status.') %jid) qs[jid].append((kind, (msg, subject, msg_type, tim, encrypted, resource))) self.nb_unread += 1 if popup: - if not gajim.interface.instances[account]['chats'].has_key(jid): + if not gajim.interface.msg_win_mgr.has_window(jid): c = gajim.get_contact_instance_with_highest_priority(account, jid) self.new_chat(c, account) if path: @@ -1932,22 +1932,18 @@ _('If "%s" accepts this request you will know his or her status.') %jid) recent = False if self.nb_unread > 0: unread = True - for account in accounts: - if gajim.interface.instances[account]['chats'].has_key('tabbed'): - wins = [gajim.interface.instances[account]['chats']['tabbed']] - else: - wins = gajim.interface.instances[account]['chats'].values() - for win in wins: - unrd = 0 - for jid in win.nb_unread: - unrd += win.nb_unread[jid] - if unrd: - unread = True + for win in gajim.interface.msg_win_mgr.windows.values(): + unrd = 0 + for ctl in win.controls(): + unrd += ctl.nb_unread + if unrd: + unread = True + break + for ctl in win.control(): + jid = ctl.contact.jid + if time.time() - gajim.last_message_time[account][ji] < 2: + recent = True break - for jid in win.contacts: - if time.time() - gajim.last_message_time[account][jid] < 2: - recent = True - break if unread: dialog = dialogs.ConfirmationDialog(_('You have unread messages'), _('Messages will only be available for reading them later if you have history enabled.')) @@ -2201,12 +2197,13 @@ _('If "%s" accepts this request you will know his or her status.') %jid) # Update the systray if gajim.interface.systray_enabled: gajim.interface.systray.set_img() + + for ctl in gajim.interface.msg_win_mgr.controls(): + ctl.update_state() + + # FIXME: All of this will go away with the above for account in gajim.connections: - # Update opened chat windows - for jid in gajim.interface.instances[account]['chats']: - if jid != 'tabbed': - gajim.interface.instances[account]['chats'][jid].set_state_image( - jid) + # FIXME # Update opened groupchat windows gcs = gajim.interface.instances[account]['gc'] if gcs.has_key('tabbed'): @@ -2218,7 +2215,7 @@ _('If "%s" accepts this request you will know his or her status.') %jid) def repaint_themed_widgets(self): '''Notify windows that contain themed widgets to repaint them''' - for win in gajim.interface.msg_win_mgr.windows.values(): + for win in gajim.interface.msg_win_mgr.windows(): win.repaint_themed_widgets() for account in gajim.connections: for addr in gajim.interface.instances[account]['disco']: diff --git a/src/systray.py b/src/systray.py index 02895ae2f..f5c378398 100644 --- a/src/systray.py +++ b/src/systray.py @@ -101,13 +101,13 @@ class Systray: self.set_img() def start_chat(self, widget, account, jid): - if gajim.interface.instances[account]['chats'].has_key(jid): - gajim.interface.instances[account]['chats'][jid].window.present() - gajim.interface.instances[account]['chats'][jid].set_active_tab(jid) + if gajim.interface.msg_win_mgr.has_window(jid): + gajim.interface.msg_win_mgr.get_window(jid).set_active_tab(jid) + gajim.interface.msg_win_mgr.get_window(jid).present() elif gajim.contacts[account].has_key(jid): - gajim.interface.roster.new_chat( - gajim.contacts[account][jid][0], account) - gajim.interface.instances[account]['chats'][jid].set_active_tab(jid) + gajim.interface.roster.new_chat(gajim.contacts[account][jid][0], + account) + gajim.interface.msg_win_mgr.get_window(jid).set_active_tab(jid) def on_new_message_menuitem_activate(self, widget, account): """When new message menuitem is activated: diff --git a/src/tooltips.py b/src/tooltips.py index eef737872..eec22c7ed 100644 --- a/src/tooltips.py +++ b/src/tooltips.py @@ -244,13 +244,12 @@ class NotificationAreaTooltip(BaseTooltip, StatusTable): for acct in gajim.connections: # we count unread chat/pm messages - chat_wins = gajim.interface.instances[acct]['chats'] - for jid in chat_wins: - if jid != 'tabbed': - if gajim.contacts[acct].has_key(jid): - unread_chat += chat_wins[jid].nb_unread[jid] - else: - unread_pm += chat_wins[jid].nb_unread[jid] + for ctl in gajim.interface.msg_win_mgr.controls(): + if gajim.contacts[acct].has_key(jid): + unread_chat += ctl.nb_unread + else: + unread_pm += ctl.nb_unread + # FIXME # we count unread gc/pm messages gc_wins = gajim.interface.instances[acct]['gc'] for jid in gc_wins: