Window/control shutdown
This commit is contained in:
parent
c30ee542dc
commit
6036368b6e
|
@ -14,12 +14,14 @@
|
|||
|
||||
import os, os.path
|
||||
import math
|
||||
import time
|
||||
import gtk
|
||||
import gtk.glade
|
||||
import pango
|
||||
import gobject
|
||||
import gtkgui_helpers
|
||||
import message_window
|
||||
import dialogs
|
||||
|
||||
from common import gajim
|
||||
from common import helpers
|
||||
|
@ -289,8 +291,7 @@ class ChatControlBase(MessageControl):
|
|||
self.nb_unread += 1
|
||||
if gajim.interface.systray_enabled and\
|
||||
gajim.config.get('trayicon_notification_on_new_messages'):
|
||||
gajim.interface.systray.add_jid(jid, self.account,
|
||||
self.get_message_type(jid))
|
||||
gajim.interface.systray.add_jid(jid, self.account, self.type)
|
||||
self.redraw_tab(jid)
|
||||
self.show_title(urgent)
|
||||
|
||||
|
@ -395,11 +396,11 @@ class ChatControlBase(MessageControl):
|
|||
################################################################################
|
||||
class ChatControl(ChatControlBase):
|
||||
'''A control for standard 1-1 chat'''
|
||||
TYPE_ID = 1
|
||||
TYPE_ID = 'chat'
|
||||
|
||||
def __init__(self, parent_win, contact, acct):
|
||||
ChatControlBase.__init__(self, self.TYPE_ID, parent_win, 'chat_child_vbox',
|
||||
_('Chat'), contact, acct);
|
||||
_('Chat'), contact, acct)
|
||||
self.compact_view_always = gajim.config.get('always_compact_view_chat')
|
||||
self.set_compact_view(self.compact_view_always)
|
||||
|
||||
|
@ -857,3 +858,32 @@ class ChatControl(ChatControlBase):
|
|||
contact.our_chatstate = state
|
||||
if contact.our_chatstate == 'active':
|
||||
self.reset_kbd_mouse_timeout_vars()
|
||||
|
||||
def shutdown(self):
|
||||
# Send 'gone' chatstate
|
||||
self.send_chatstate('gone', self.contact.jid)
|
||||
self.contact.chatstate = None
|
||||
self.contact.our_chatstate = None
|
||||
# Disconnect timer callbacks
|
||||
gobject.source_remove(self.possible_paused_timeout_id)
|
||||
gobject.source_remove(self.possible_inactive_timeout_id)
|
||||
if self.print_time_timeout_id:
|
||||
gobject.source_remove(self.print_time_timeout_id)
|
||||
# Clean up systray
|
||||
if gajim.interface.systray_enabled and self.nb_unread > 0:
|
||||
gajim.interface.systray.remove_jid(self.contact.jid, self.account,
|
||||
self.type)
|
||||
|
||||
def check_delete(self):
|
||||
jid = self.contact.jid
|
||||
if time.time() - gajim.last_message_time[self.account][jid] < 2:
|
||||
# 2 seconds
|
||||
dialog = dialogs.ConfirmationDialog(
|
||||
#%s is being replaced in the code with JID
|
||||
_('You just received a new message from "%s"' % jid),
|
||||
_('If you close this tab and you have history disabled, '\
|
||||
'this message will be lost.'))
|
||||
if dialog.get_response() != gtk.RESPONSE_OK:
|
||||
return True #stop the propagation of the event
|
||||
return False
|
||||
|
||||
|
|
|
@ -19,12 +19,21 @@ import gobject
|
|||
import gtkgui_helpers
|
||||
|
||||
from common import gajim
|
||||
from chat_control import ChatControl
|
||||
from chat_control import ChatControlBase
|
||||
from conversation_textview import ConversationTextview
|
||||
from message_textview import MessageTextView
|
||||
|
||||
class PrivateChatControl(ChatControl):
|
||||
TYPE_ID = 'pm'
|
||||
|
||||
def __init__(self, parent_win, contact, acct):
|
||||
ChatControl.__init__(self, parent_win, contact, acct)
|
||||
self.TYPE_ID = 'pm'
|
||||
self.display_name = _('Private char')
|
||||
|
||||
class GroupchatControl(ChatControlBase):
|
||||
TYPE_ID = 2
|
||||
TYPE_ID = 'gc'
|
||||
|
||||
def __init__(self, parent_win, contact, acct):
|
||||
ChatControlBase.__init__(self, self.TYPE_ID, parent_win,
|
||||
|
@ -33,3 +42,42 @@ class GroupchatControl(ChatControlBase):
|
|||
# muc attention states (when we are mentioned in a muc)
|
||||
# if the room jid is in the list, the room has mentioned us
|
||||
self.muc_attentions = []
|
||||
|
||||
def markup_tab_label(self, label_str, chatstate):
|
||||
'''Markup the label if necessary. Returns a tuple such as:
|
||||
(new_label_str, color)
|
||||
either of which can be None
|
||||
if chatstate is given that means we have HE SENT US a chatstate'''
|
||||
|
||||
num_unread = self.nb_unread
|
||||
|
||||
has_focus = self.parent_win.get_property('has-toplevel-focus')
|
||||
current_tab = self.parent_win.get_active_control() == self
|
||||
color = None
|
||||
theme = gajim.config.get('roster_theme')
|
||||
if chatstate == 'attention' and (not has_focus or not current_tab):
|
||||
if jid not in self.muc_attentions:
|
||||
self.muc_attentions.append(jid)
|
||||
color = gajim.config.get_per('themes', theme,
|
||||
'state_muc_directed_msg')
|
||||
elif chatstate:
|
||||
if chatstate == 'active' or (current_tab and has_focus):
|
||||
if jid in self.muc_attentions:
|
||||
self.muc_attentions.remove(jid)
|
||||
color = gajim.config.get_per('themes', theme,
|
||||
'state_active_color')
|
||||
elif chatstate == 'newmsg' and (not has_focus or not current_tab) and\
|
||||
jid not in self.muc_attentions:
|
||||
color = gajim.config.get_per('themes', theme, 'state_muc_msg')
|
||||
if color:
|
||||
color = gtk.gdk.colormap_get_system().alloc_color(color)
|
||||
# The widget state depend on whether this tab is the "current" tab
|
||||
if current_tab:
|
||||
nickname.modify_fg(gtk.STATE_NORMAL, color)
|
||||
else:
|
||||
nickname.modify_fg(gtk.STATE_ACTIVE, color)
|
||||
|
||||
if num_unread: # if unread, text in the label becomes bold
|
||||
label_str = '<b>' + str(num_unread) + label_str + '</b>'
|
||||
return (label_str, color)
|
||||
|
||||
|
|
|
@ -85,7 +85,12 @@ class MessageWindow:
|
|||
self.window.show_all()
|
||||
|
||||
def _on_window_delete(self, win, event):
|
||||
print "MessageWindow._on_window_delete:", win, event
|
||||
# Make sure all controls are okay with being deleted
|
||||
for ctl in self._controls.values():
|
||||
if not ctl.check_delete():
|
||||
return True # halt the delete
|
||||
|
||||
# FIXME: Do based on type, main, never, peracct, pertype
|
||||
if gajim.config.get('saveposition'):
|
||||
# save the window size and position
|
||||
x, y = win.get_position()
|
||||
|
@ -96,8 +101,13 @@ class MessageWindow:
|
|||
gajim.config.set('msgwin-height', height)
|
||||
|
||||
return False
|
||||
|
||||
def _on_window_destroy(self, win):
|
||||
# FIXME
|
||||
print "MessageWindow._on_window_destroy:", win
|
||||
for ctl in self._controls.values():
|
||||
ctl.shutdown()
|
||||
self._controls.clear()
|
||||
|
||||
def new_tab(self, control):
|
||||
assert(not self._controls.has_key(control.contact.jid))
|
||||
|
@ -284,11 +294,21 @@ class MessageWindow:
|
|||
for ctl in self._controls.values():
|
||||
ctl.update_tags()
|
||||
|
||||
def get_control_from_jid(self, jid):
|
||||
for ctl in self._controls.values():
|
||||
if ctl.contact.jid == jid:
|
||||
return ctl
|
||||
return None
|
||||
def get_control(self, arg):
|
||||
'''Return the MessageControl for jid or n, where n is the notebook page index'''
|
||||
if isinstance(arg, unicode):
|
||||
jid = arg
|
||||
for ctl in self._controls.values():
|
||||
if ctl.contact.jid == jid:
|
||||
return ctl
|
||||
return None
|
||||
else:
|
||||
page_num = arg
|
||||
notebook = self.notebook
|
||||
if page_num == None:
|
||||
page_num = notebook.get_current_page()
|
||||
nth_child = notebook.get_nth_page(page_num)
|
||||
return self._widgetToControl(nth_child)
|
||||
|
||||
def controls(self):
|
||||
for ctl in self._controls.values():
|
||||
|
@ -307,6 +327,41 @@ class MessageWindow:
|
|||
ctl.print_time_timeout_id = gobject.timeout_add(300000,
|
||||
ctl.print_time_timeout, None)
|
||||
|
||||
def move_to_next_unread_tab(self, forward):
|
||||
ind = self.notebook.get_current_page()
|
||||
current = ind
|
||||
found = False
|
||||
# loop until finding an unread tab or having done a complete cycle
|
||||
while True:
|
||||
if forward == True: # look for the first unread tab on the right
|
||||
ind = ind + 1
|
||||
if ind >= self.notebook.get_n_pages():
|
||||
ind = 0
|
||||
else: # look for the first unread tab on the right
|
||||
ind = ind - 1
|
||||
if ind < 0:
|
||||
ind = self.notebook.get_n_pages() - 1
|
||||
if ind == current:
|
||||
break # a complete cycle without finding an unread tab
|
||||
ctl = self.get_control(ind)
|
||||
if ctl.nb_unread > 0:
|
||||
found = True
|
||||
break # found
|
||||
if found:
|
||||
self.notebook.set_current_page(ind)
|
||||
else: # not found
|
||||
if forward: # CTRL + TAB
|
||||
if current < (self.notebook.get_n_pages() - 1):
|
||||
self.notebook.next_page()
|
||||
else: # traverse for ever (eg. don't stop at last tab)
|
||||
self.notebook.set_current_page(0)
|
||||
else: # CTRL + SHIFT + TAB
|
||||
if current > 0:
|
||||
self.notebook.prev_page()
|
||||
else: # traverse for ever (eg. don't stop at first tab)
|
||||
self.notebook.set_current_page(
|
||||
self.notebook.get_n_pages() - 1)
|
||||
|
||||
|
||||
class MessageWindowMgr:
|
||||
'''A manager and factory for MessageWindow objects'''
|
||||
|
@ -334,7 +389,6 @@ class MessageWindowMgr:
|
|||
def _new_window(self):
|
||||
win = MessageWindow()
|
||||
# we track the lifetime of this window
|
||||
win.window.connect('delete-event', self._on_window_delete)
|
||||
win.window.connect('destroy', self._on_window_destroy)
|
||||
return win
|
||||
|
||||
|
@ -344,17 +398,17 @@ class MessageWindowMgr:
|
|||
return w
|
||||
return None
|
||||
|
||||
def _on_window_delete(self, win, event):
|
||||
# FIXME
|
||||
print "MessageWindowMgr._on_window_delete:", win
|
||||
def _on_window_destroy(self, win):
|
||||
# FIXME
|
||||
print "MessageWindowMgr._on_window_destroy:", win
|
||||
# TODO: Clean up windows
|
||||
for k in self._windows.keys():
|
||||
if self._windows[k].window == win:
|
||||
del self._windows[k]
|
||||
return
|
||||
# How was the window not in out list?!? Assert.
|
||||
assert(False)
|
||||
|
||||
def get_window(self, jid):
|
||||
for win in self._windows.values():
|
||||
if win.get_control_from_jid(jid):
|
||||
if win.get_control(jid):
|
||||
return win
|
||||
return None
|
||||
def has_window(self, jid):
|
||||
|
@ -384,9 +438,10 @@ class MessageWindowMgr:
|
|||
return win
|
||||
|
||||
def get_control(self, jid):
|
||||
'''Amonst all windows, return the MessageControl for jid'''
|
||||
win = self.get_window(jid)
|
||||
if win:
|
||||
return win.get_control_from_jid(jid)
|
||||
return win.get_control(jid)
|
||||
return None
|
||||
|
||||
def windows(self):
|
||||
|
@ -419,8 +474,11 @@ class MessageControl(gtk.VBox):
|
|||
# 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
|
||||
pass # NOTE: Derived classes SHOULD implement this
|
||||
def repaint_themed_widgets(self, theme):
|
||||
pass # NOTE: Derived classes SHOULD implement this
|
||||
def update_state(self):
|
||||
|
@ -445,7 +503,14 @@ class MessageControl(gtk.VBox):
|
|||
# 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'''
|
||||
|
|
|
@ -712,7 +712,7 @@ class RosterWindow:
|
|||
if gajim.interface.msg_win_mgr.has_window(contact.jid):
|
||||
jid = contact.jid
|
||||
win = gajim.interface.msg_win_mgr.get_window(contact.jid)
|
||||
ctl = win.get_control_from_jid(jid)
|
||||
ctl = win.get_control(jid)
|
||||
ctl.update_state()
|
||||
|
||||
name = contact.name
|
||||
|
|
Loading…
Reference in New Issue