From 4b59506c97aefcd75564221905a539c15295852f Mon Sep 17 00:00:00 2001 From: Travis Shirk Date: Mon, 2 Jan 2006 02:12:34 +0000 Subject: [PATCH] Moved MessageControl into it's own file to avoid circular depency --- src/chat_control.py | 6 +- src/groupchat_control.py | 5 +- src/groupchat_window.py | 4 ++ src/message_control.py | 135 +++++++++++++++++++++++++++++++++++++++ src/message_window.py | 121 ++++++----------------------------- 5 files changed, 166 insertions(+), 105 deletions(-) create mode 100644 src/message_control.py diff --git a/src/chat_control.py b/src/chat_control.py index 077364fd3..2a5060582 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -20,12 +20,12 @@ import gtk.glade import pango import gobject import gtkgui_helpers -import message_window +import message_control import dialogs from common import gajim from common import helpers -from message_window import MessageControl +from message_control import MessageControl from conversation_textview import ConversationTextview from message_textview import MessageTextView @@ -406,7 +406,7 @@ class ChatControlBase(MessageControl): ################################################################################ class ChatControl(ChatControlBase): '''A control for standard 1-1 chat''' - TYPE_ID = 'chat' + TYPE_ID = message_control.TYPE_CHAT def __init__(self, parent_win, contact, acct): ChatControlBase.__init__(self, self.TYPE_ID, parent_win, 'chat_child_vbox', diff --git a/src/groupchat_control.py b/src/groupchat_control.py index cbf801d1c..9b7ea2709 100644 --- a/src/groupchat_control.py +++ b/src/groupchat_control.py @@ -17,6 +17,7 @@ import gtk.glade import pango import gobject import gtkgui_helpers +import message_control from common import gajim from chat_control import ChatControl @@ -25,7 +26,7 @@ from conversation_textview import ConversationTextview from message_textview import MessageTextView class PrivateChatControl(ChatControl): - TYPE_ID = 'pm' + TYPE_ID = message_control.TYPE_PM def __init__(self, parent_win, contact, acct): ChatControl.__init__(self, parent_win, contact, acct) @@ -33,7 +34,7 @@ class PrivateChatControl(ChatControl): self.display_name = _('Private char') class GroupchatControl(ChatControlBase): - TYPE_ID = 'gc' + TYPE_ID = message_control.TYPE_GC def __init__(self, parent_win, contact, acct): ChatControlBase.__init__(self, self.TYPE_ID, parent_win, diff --git a/src/groupchat_window.py b/src/groupchat_window.py index 5587524e2..5c7c8557b 100644 --- a/src/groupchat_window.py +++ b/src/groupchat_window.py @@ -1184,6 +1184,7 @@ current room topic.') % command, room_jid) nick = model[iter][C_NICK].decode('utf-8') room_jid = self.get_active_jid() fjid = gajim.construct_fjid(room_jid, nick) # 'fake' jid + # FIXME if not gajim.interface.instances[self.account]['chats'].has_key(fjid): gc_c = gajim.contacts.get_gc_contact(self.account, room_jid, nick) c = gajim.contacts.contact_from_gc_contact(gc_c) @@ -1493,6 +1494,7 @@ current room topic.') % command, room_jid) no_queue = False # We print if window is opened + # FIXME if gajim.interface.instances[self.account]['chats'].has_key(fjid): chat_win = gajim.interface.instances[self.account]['chats'][fjid] chat_win.print_conversation(msg, fjid, tim = tim) @@ -1627,6 +1629,7 @@ current room topic.') % command, room_jid) if len(path) == 2: nick = model[iter][C_NICK].decode('utf-8') fjid = gajim.construct_fjid(room_jid, nick) + # FIXME if not gajim.interface.instances[self.account]['chats'].has_key(fjid): gc_c = gajim.contacts.get_gc_contact(self.account, room_jid, nick) @@ -1671,6 +1674,7 @@ current room topic.') % command, room_jid) room_jid = self.get_active_jid() nick = model[iter][C_NICK].decode('utf-8') jid = gajim.construct_fjid(room_jid, nick) + # FIXME if not gajim.interface.instances[self.account]['chats'].has_key(jid): gc_c = gajim.contacts.get_gc_contact(self.account, room_jid, nick) gajim.interface.roster.new_chat(gc_c, self.account) diff --git a/src/message_control.py b/src/message_control.py new file mode 100644 index 000000000..61c3a623d --- /dev/null +++ b/src/message_control.py @@ -0,0 +1,135 @@ +## message_control.py +## +## Copyright (C) 2005-2006 Travis Shirk +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 2 only. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +import gtk +import gtk.glade +import pango +import gobject +import common +import gtkgui_helpers + +from common import gajim + +# Derived types MUST register their type IDs here if custom behavor is required +TYPE_CHAT = 'chat' +TYPE_GC = 'gc' +TYPE_PM = 'pm' + +#################### +# FIXME: Can't this stuff happen once? +from common import i18n +_ = i18n._ +APP = i18n.APP + +GTKGUI_GLADE = 'gtkgui.glade' +#################### + +class MessageControl(gtk.VBox): + '''An abstract base widget that can embed in the gtk.Notebook of a MessageWindow''' + + def __init__(self, type_id, parent_win, widget_name, display_name, contact, account): + gtk.VBox.__init__(self) + + self.type_id = type_id + self.parent_win = parent_win + self.widget_name = widget_name + self.display_name = display_name + self.contact = contact + self.account = account + 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) + # Autoconnect glade signals + self.xml.signal_autoconnect(self) + + def shutdown(self): + # NOTE: Derived classes MUST implement this + assert(False) + def draw_widgets(self): + pass # NOTE: Derived classes SHOULD implement this + def repaint_themed_widgets(self, theme): + pass # NOTE: Derived classes SHOULD implement this + def update_state(self): + pass # NOTE: Derived classes SHOULD implement this + def toggle_emoticons(self): + pass # NOTE: Derived classes MAY implement this + def update_font(self): + 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 + return (label_str, None) + def prepare_context_menu(self): + # NOTE: Derived classes SHOULD implement this + return None + def set_compact_view(self, state): + # NOTE: Derived classes MAY implement this + self.compact_view_current = state + def check_delete(self): + '''Called when a window has been asked to delete itself. If a control is + not in a suitable shutdown state this method should return True to halt + the delete''' + # NOTE: Derived classes MAY implement this + return False + + def send_message(self, message, keyID = '', type = 'chat', chatstate = None): + '''Send the given message to the active tab''' + # refresh timers + self.reset_kbd_mouse_timeout_vars() + + jid = self.contact.jid + # Send and update history + gajim.connections[self.account].send_message(jid, message, keyID, + type = type, chatstate = chatstate) + + def position_menu_under_button(self, menu): + #FIXME: BUG http://bugs.gnome.org/show_bug.cgi?id=316786 + # pass btn instance when this bug is over + button = self.button_clicked + # here I get the coordinates of the button relative to + # window (self.window) + button_x, button_y = button.allocation.x, button.allocation.y + + # now convert them to X11-relative + window_x, window_y = self.parent_win.get_origin() + x = window_x + button_x + y = window_y + button_y + + menu_width, menu_height = menu.size_request() + + ## should we pop down or up? + if (y + button.allocation.height + menu_height + < gtk.gdk.screen_height()): + # now move the menu below the button + y += button.allocation.height + else: + # now move the menu above the button + y -= menu_height + + + # push_in is True so all the menuitems are always inside screen + push_in = True + return (x, y, push_in) + diff --git a/src/message_window.py b/src/message_window.py index 981d81cac..606487e17 100644 --- a/src/message_window.py +++ b/src/message_window.py @@ -19,6 +19,7 @@ import gobject import common import gtkgui_helpers +import message_control from common import gajim @@ -71,6 +72,7 @@ class MessageWindow: # Connect event handling for this Window self.window.connect('delete-event', self._on_window_delete) self.window.connect('destroy', self._on_window_destroy) + self.window.connect('focus-in-event', self._on_window_focus) # Restore previous window position if gajim.config.get('saveposition'): @@ -84,6 +86,24 @@ class MessageWindow: self.window.show_all() + def _on_window_focus(self, widget, event): + # FIXME: + print "_on_window_focus" + # window received focus, so if we had urgency REMOVE IT + # NOTE: we do not have to read the message (it maybe in a bg tab) + # to remove urgency hint so this functions does that + if gtk.gtk_version >= (2, 8, 0) and gtk.pygtk_version >= (2, 8, 0): + if widget.props.urgency_hint: + widget.props.urgency_hint = False + + ctl = self.get_active_control() + # Undo "unread" state display, etc. + if ctl.type_id == message_control.TYPE_GC: + self.redraw_tab(ctl.contact, 'active') + else: + # NOTE: we do not send any chatstate to preserve inactive, gone, etc. + self.redraw_tab(ctl.contact) + def _on_window_delete(self, win, event): # Make sure all controls are okay with being deleted for ctl in self._controls.values(): @@ -363,6 +383,7 @@ class MessageWindow: self.notebook.get_n_pages() - 1) +################################################################################ class MessageWindowMgr: '''A manager and factory for MessageWindow objects''' @@ -452,103 +473,3 @@ class MessageWindowMgr: 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''' - - def __init__(self, type_id, parent_win, widget_name, display_name, contact, account): - gtk.VBox.__init__(self) - - self.type_id = type_id - self.parent_win = parent_win - self.widget_name = widget_name - self.display_name = display_name - self.contact = contact - self.account = account - 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) - # Autoconnect glade signals - self.xml.signal_autoconnect(self) - - def shutdown(self): - # NOTE: Derived classes MUST implement this - assert(False) - def draw_widgets(self): - pass # NOTE: Derived classes SHOULD implement this - def repaint_themed_widgets(self, theme): - pass # NOTE: Derived classes SHOULD implement this - def update_state(self): - pass # NOTE: Derived classes SHOULD implement this - def toggle_emoticons(self): - pass # NOTE: Derived classes MAY implement this - def update_font(self): - 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 - return (label_str, None) - def prepare_context_menu(self): - # NOTE: Derived classes SHOULD implement this - return None - def set_compact_view(self, state): - # NOTE: Derived classes MAY implement this - self.compact_view_current = state - def check_delete(self): - '''Called when a window has been asked to delete itself. If a control is - not in a suitable shutdown state this method should return True to halt - the delete''' - # NOTE: Derived classes MAY implement this - return False - - def send_message(self, message, keyID = '', type = 'chat', chatstate = None): - '''Send the given message to the active tab''' - # refresh timers - self.reset_kbd_mouse_timeout_vars() - - jid = self.contact.jid - # Send and update history - gajim.connections[self.account].send_message(jid, message, keyID, - type = type, chatstate = chatstate) - - def position_menu_under_button(self, menu): - #FIXME: BUG http://bugs.gnome.org/show_bug.cgi?id=316786 - # pass btn instance when this bug is over - button = self.button_clicked - # here I get the coordinates of the button relative to - # window (self.window) - button_x, button_y = button.allocation.x, button.allocation.y - - # now convert them to X11-relative - window_x, window_y = self.parent_win.get_origin() - x = window_x + button_x - y = window_y + button_y - - menu_width, menu_height = menu.size_request() - - ## should we pop down or up? - if (y + button.allocation.height + menu_height - < gtk.gdk.screen_height()): - # now move the menu below the button - y += button.allocation.height - else: - # now move the menu above the button - y -= menu_height - - - # push_in is True so all the menuitems are always inside screen - push_in = True - return (x, y, push_in) - -