diff --git a/mitterlib/ui/helpers/gtk_messagegrid.py b/mitterlib/ui/helpers/gtk_messagegrid.py
new file mode 100644
index 0000000..f79eb8e
--- /dev/null
+++ b/mitterlib/ui/helpers/gtk_messagegrid.py
@@ -0,0 +1,364 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Mitter, a micro-blogging client with multiple interfaces.
+# Copyright (C) 2007-2010 Mitter Contributors
+#
+# 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, either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import gobject
+import gtk
+import logging
+import pango
+
+from cgi import escape as html_escape
+
+# ----------------------------------------------------------------------
+# String with the format to the message
+# ----------------------------------------------------------------------
+MESSAGE_FORMAT = ('%(favourite_star)s'
+ '%(full_name)s '
+ '(%(username)s'
+ '%(message_type)s'
+ '):'
+ '%(read_status)s '
+ '%(protected_status)s '
+ '\n'
+ '%(message)s\n'
+ '%(message_age)s')
+
+# ----------------------------------------------------------------------
+# Logging
+# ----------------------------------------------------------------------
+_log = logging.getLogger('ui.pygtk.messagegrid')
+
+# ----------------------------------------------------------------------
+# MessageGrid class
+# ----------------------------------------------------------------------
+class MessageGrid(gtk.ScrolledWindow, gobject.GObject):
+ """Custom message grid."""
+
+ __gsignals__ = {
+ "count-changed": (
+ gobject.SIGNAL_RUN_LAST,
+ gobject.TYPE_NONE,
+ (gobject.TYPE_INT, ))} # The exception
+
+ @property
+ def count(self):
+ """Number of unread messages."""
+ return self._message_count
+
+ @count.setter
+ def count(self, messages):
+ """Update the number of unread messages."""
+ self._message_count = messages
+ self.emit('count-changed', messages)
+ return
+
+ def __init__(self):
+ super(MessageGrid, self).__init__()
+
+ self.avatars = None
+ self.link_color = '#0000ff'
+ self.unread_char = '(o)'
+ self.favorite_char = '(F)'
+ self.unfavorite_char = '( )'
+ self.protected_char = '(protected)'
+
+ self._message_count = 0
+
+ store = gtk.ListStore(object)
+ store.set_sort_column_id(0, gtk.SORT_ASCENDING)
+ store.set_sort_func(0, self._order_datetime)
+
+ self._grid = gtk.TreeView(store)
+ self._grid.set_property('headers-visible', False)
+ self._grid.set_rules_hint(True) # change color for each row
+
+ user_renderer = gtk.CellRendererPixbuf()
+ user_column = gtk.TreeViewColumn('User', user_renderer)
+ user_column.set_fixed_width(48) # avatar size (we resize to 48x48)
+ user_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
+ user_column.set_cell_data_func(user_renderer,
+ self._cell_renderer_user)
+
+ message_renderer = gtk.CellRendererText()
+ message_renderer.set_property('wrap-mode', pango.WRAP_WORD)
+ message_renderer.set_property('wrap-width', 200)
+ message_column = gtk.TreeViewColumn('Message',
+ message_renderer)
+ message_column.set_cell_data_func(message_renderer,
+ self._cell_renderer_message)
+
+ self._grid.append_column(user_column)
+ self._grid.append_column(message_column)
+
+ self._grid.set_resize_mode(gtk.RESIZE_IMMEDIATE)
+ self._grid.connect('cursor-changed', self._message_selected)
+ self._grid.connect('button-press-event', self._click_message)
+ self._grid.connect('popup-menu', self._message_popup) # Menu button
+ self._grid.connect('cursor-changed', self._mark_message_read)
+
+ self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
+ self.add(self._grid)
+ return
+
+ #-----------------------------------------------------------------------
+ # Renderers
+ #-----------------------------------------------------------------------
+ def _cell_renderer_user(self, column, cell, store, position):
+ """Callback for the user column. Used to created the pixbuf of the
+ userpic."""
+
+ data = store.get_value(position, 0)
+ pic = data.author.avatar
+ cell.set_property('pixbuf', self.avatars[pic])
+
+ return
+
+ def _cell_renderer_message(self, column, cell, store, position):
+ """Callback for the message column. We need this to adjust the markup
+ property of the cell, as setting it as text won't do any markup
+ processing."""
+
+ data = store.get_value(position, 0)
+ time = timesince.timesince(data.message_time)
+
+ message_values = {}
+
+ # unescape escaped entities that pango is not okay with
+ message_values['message'] = html_escape(data.message)
+ message_values['username'] = html_escape(data.author.username)
+ message_values['full_name'] = html_escape(data.author.name)
+ message_values['message_age'] = time
+
+ # highlight URLs
+ mask = r'\1' % (self.link_color)
+ message_values['message'] = URL_RE.sub(mask,
+ message_values['message'])
+
+ # use a different highlight for the current user
+ # TODO: How to handle this with several networks?
+ #message = re.sub(r'(@'+self.twitter.username+')',
+ # r'\1',
+ # message)
+
+ if not data.read:
+ message_values['read_status'] = (' ' + self.unread_char)
+ else:
+ message_values['read_status'] = ''
+
+ if data.favourite:
+ message_values['favourite_star'] = (self.unfavourite_char)
+ else:
+ message_values['favourite_star'] = (self.favourite_char)
+
+ info = []
+ if data.reposted_by:
+ info.append(_(' — reposted by %s') %
+ (data.reposted_by.username))
+
+ if data.parent_owner:
+ info.append(_(' — in reply to %s') %
+ (data.parent_owner.username))
+
+ if data.protected:
+ message_values['protected_status'] = (self.protected_char)
+ else:
+ message_values['protected_status'] = ''
+
+ message_values['message_type'] = ''.join(info)
+ markup = MESSAGE_FORMAT % (message_values)
+
+ cell.set_property('markup', markup)
+
+ return
+
+ #-----------------------------------------------------------------------
+ # Widget callbacks
+ #-----------------------------------------------------------------------
+ def _message_selected(self, view, user_data=None):
+ """Callback when a row in the list is selected. Mostly, we'll check
+ if the message is from the logged user and we change de "sensitive"
+ property of the message actions to reflect what the user can and
+ cannot do."""
+
+ (model, iter) = view.get_selection().get_selected()
+ if not iter:
+ return
+ data = model.get_value(iter, 0)
+ data.read = True
+
+ self._delete_action.set_property('sensitive', data.deletable)
+ self._reply_action.set_property('sensitive', data.replyable)
+ self._repost_action.set_property('sensitive', data.repostable)
+ self._favourite_action.set_property('sensitive', data.favoritable)
+
+ return 0
+
+ def _click_message(self, widget, event, user_data=None):
+ """Check the click on the message and, if it's a right click, call the
+ _message_popup function to show the popup."""
+ if event.button != 3:
+ # not right click
+ return False
+
+ path = widget.get_path_at_pos(event.x, event.y)
+ if not path:
+ return False
+
+ (path, _, _, _) = path
+ return self._url_popup(widget, path, event)
+
+ def _message_popup(self, widget, user_data=None):
+ """Builds the popup with the URLs in the message."""
+ _log.debug('Popup')
+ (path, _) = widget.get_cursor()
+ if not path:
+ return True
+
+ # create a syntetic event (the popup requires one)
+ event = gtk.gdk.Event(gtk.gdk.BUTTON_PRESS)
+ event.button = 3
+ return self._url_popup(widget, path, event)
+
+ def _url_popup(self, widget, path, event):
+ """Builds the popup with URLs in the cell pointed by *path*. Requires
+ the *event* that the widget received."""
+ iter = widget.get_model().get_iter(path)
+ message = widget.get_model().get_value(iter, 0)
+
+ items = []
+ if message.link:
+ items.append((_('Open on %s') % (message.network_name),
+ message.link))
+
+ urls = URL_RE.findall(message.message)
+ for url in urls:
+ if len(url) > 20:
+ title = url[:20] + '...'
+ else:
+ title = url
+ items.append((title, url))
+
+ if len(items) == 0:
+ return
+
+ popup = gtk.Menu()
+ for url in items:
+ (title, url) = url
+ item = gtk.MenuItem(title)
+ item.connect('activate', self._open_url, url)
+ popup.append(item)
+
+ popup.show_all()
+ popup.popup(None, None, None, event.button, event.time)
+
+ return True
+
+ def _mark_message_read(self, widget, user_data=None):
+ """Mark a message as read when it's selected."""
+ (path, _) = widget.get_cursor()
+ if not path:
+ return True
+
+ iter = widget.get_model().get_iter(path)
+ message = widget.get_model().get_value(iter, 0)
+
+ if message.read:
+ return True
+
+ self.count -= 1
+ return True
+
+ def update(self, messages):
+ """Update the grid with new messages."""
+ self._grid.freeze()
+ store = self._grid.get_model()
+ for message in messages:
+ message.read = False
+ store.prepend([message])
+ store.sort_column_changed()
+ self._grid.thaw()
+ return
+
+ def _order_datetime(self, model, iter1, iter2, user_data=None):
+ """Used by the ListStore to sort the columns (in our case, "column")
+ by date."""
+ message1 = model.get_value(iter1, 0)
+ message2 = model.get_value(iter2, 0)
+
+ if (not message1) or \
+ (not message1.message_time) or \
+ (message1.message_time > message2.message_time):
+ return -1
+
+ if (not message2) or \
+ (not message2.message_time) or \
+ (message2.message_time > message1.message_time):
+ return 1
+ return 0
+
+ def clear_posts(self, widget, user_data=None):
+ """Clear the list of posts from the grid."""
+ self._grid.get_model().clear()
+ self.count = 0;
+ return
+
+ def mark_all_read(self, widget, user_data=None):
+ """Mark all messages as read."""
+ model = self._grid.get_model()
+ if len(model) == 0:
+ # no messages, so we don't worry (if I recall correctly,
+ # get_iter_first will fail if the model is empty)
+ return
+
+ iter = model.get_iter_first()
+ while iter:
+ message = model.get_value(iter, 0)
+ message.read = True
+ iter = model.iter_next(iter)
+
+ self.count = 0
+ return
+
+ def _open_url(self, widget, user_data=None):
+ """Opens an URL (used mostly from popup menu items.)"""
+ webbrowser.open_new_tab(user_data)
+ return
+
+ def update_window_size(self, size):
+ """Called when the window size changes, so the grid needs to change
+ its word-wrapping size."""
+ model = self._grid.get_model()
+ if len(model) == 0:
+ return
+
+ column = self._grid.get_column(1) # 0=avatar, 1=message
+ iter = model.get_iter_first()
+ path = model.get_path(iter)
+
+ width = win_width - 85 # 48 = icon size
+ # TODO: Find out where those 37 pixels came from and/or if they
+ # are platform specific.
+
+ for renderer in column.get_cell_renderers():
+ renderer.set_property('wrap-width', width)
+
+ while iter:
+ path = model.get_path(iter)
+ model.row_changed(path, iter)
+ iter = model.iter_next(iter)
+ return
diff --git a/mitterlib/ui/ui_pygtk.py b/mitterlib/ui/ui_pygtk.py
index 2a5880d..01d7315 100644
--- a/mitterlib/ui/ui_pygtk.py
+++ b/mitterlib/ui/ui_pygtk.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Mitter, a multiple-interface client for microblogging services.
+# Mitter, a micro-blogging client with multiple interfaces.
# Copyright (C) 2007-2010 Mitter Contributors
#
# This program is free software: you can redistribute it and/or modify
@@ -28,11 +28,10 @@ import urllib2
import webbrowser
import gettext
-from cgi import escape as html_escape
-
from mitterlib.ui.helpers.image_helpers import find_image
from mitterlib.ui.helpers.gtk_threading import ThreadManager
from mitterlib.ui.helpers.gtk_updatebox import UpdateBox
+from mitterlib.ui.helpers.gtk_messagegrid import MessageGrid
from mitterlib.constants import gpl_3, version
from mitterlib.ui.helpers import timesince
@@ -48,21 +47,6 @@ t = gettext.translation('ui_pygtk', fallback=True)
_ = t.gettext
N_ = t.ngettext
-# ----------------------------------------------------------------------
-# String with the format to the message
-# ----------------------------------------------------------------------
-MESSAGE_FORMAT = ('%(favourite_star)s'
- '%(full_name)s '
- '(%(username)s'
- '%(message_type)s'
- '):'
- '%(read_status)s '
- '%(protected_status)s '
- '\n'
- '%(message)s\n'
- '%(message_age)s')
-
-
# ----------------------------------------------------------------------
# Mitter interface object
# ----------------------------------------------------------------------
@@ -105,16 +89,8 @@ class Interface(object):
self._statusbar = self._create_statusbar()
self._main_tabs = gtk.Notebook()
- self._grids = []
-
- (grid_widget, grid) = self._create_grid('_new_message_count')
- self._main_tabs.insert_page(grid_widget, gtk.Label('Messages'))
- self._grids.append((grid, '_new_messages_count'))
-
- (replies_widget, replies) = self._create_grid(
- '_new_replies_count')
- self._main_tabs.insert_page(replies_widget, gtk.Label('Replies'))
- self._grids.append((replies, '_new_replies_count'))
+ self._main_tabs.insert_page(MessageGrid(), gtk.Label('Messages'))
+ self._main_tabs.insert_page(MessageGrid(), gtk.Label('Replies'))
update_box = gtk.VBox()
update_box.set_property('border_width', 2)
@@ -151,47 +127,6 @@ class Interface(object):
return main_window
- def _create_grid(self, counter):
- """Add the displaying grid."""
- # Store NetworkData objects only
- grid_store = gtk.ListStore(object)
- grid_store.set_sort_column_id(0, gtk.SORT_ASCENDING)
- grid_store.set_sort_func(0, self._order_datetime)
-
- grid = gtk.TreeView(grid_store)
- grid.set_property('headers-visible', False)
- grid.set_rules_hint(True) # change color for each row
-
- user_renderer = gtk.CellRendererPixbuf()
- user_column = gtk.TreeViewColumn('User', user_renderer)
- user_column.set_fixed_width(48) # avatar size (we resize to 48x48)
- user_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
- user_column.set_cell_data_func(user_renderer,
- self._cell_renderer_user)
-
- message_renderer = gtk.CellRendererText()
- message_renderer.set_property('wrap-mode', gtk.WRAP_WORD)
- message_renderer.set_property('wrap-width', 200)
- message_column = gtk.TreeViewColumn('Message',
- message_renderer)
- message_column.set_cell_data_func(message_renderer,
- self._cell_renderer_message)
-
- grid.append_column(user_column)
- grid.append_column(message_column)
-
- grid.set_resize_mode(gtk.RESIZE_IMMEDIATE)
- grid.connect('cursor-changed', self._message_selected)
- grid.connect('button-press-event', self._click_message)
- grid.connect('popup-menu', self._message_popup) # Menu button
- grid.connect('cursor-changed', self._mark_message_read, counter)
-
- scrolled_window = gtk.ScrolledWindow()
- scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
- scrolled_window.add(grid)
-
- return (scrolled_window, grid)
-
def _create_menu_and_toolbar(self):
"""Create the main menu and the toolbar."""
@@ -318,7 +253,8 @@ class Interface(object):
action_group.add_action_with_accel(self._delete_action, 'Delete')
self._reply_action = gtk.Action('Reply', _('_Reply'),
- _("Send a response to someone's else message"), gtk.STOCK_REDO)
+ _("Send a response to someone's else message"),
+ gtk.STOCK_REDO)
self._reply_action.set_property('sensitive', False)
self._reply_action.connect('activate', self._reply_message)
action_group.add_action_with_accel(self._reply_action, 'r')
@@ -399,90 +335,6 @@ class Interface(object):
about_window.run()
about_window.hide()
- # ------------------------------------------------------------
- # Cell rendering functions
- # ------------------------------------------------------------
- def _cell_renderer_user(self, column, cell, store, position):
- """Callback for the user column. Used to created the pixbuf of the
- userpic."""
-
- data = store.get_value(position, 0)
- pic = data.author.avatar
- cell.set_property('pixbuf', self._avatars[pic])
-
- return
-
- def _cell_renderer_message(self, column, cell, store, position):
- """Callback for the message column. We need this to adjust the markup
- property of the cell, as setting it as text won't do any markup
- processing."""
-
- data = store.get_value(position, 0)
- time = timesince.timesince(data.message_time)
-
- message_values = {}
-
- # unescape escaped entities that pango is not okay with
- message_values['message'] = html_escape(data.message)
- message_values['username'] = html_escape(data.author.username)
- message_values['full_name'] = html_escape(data.author.name)
- message_values['message_age'] = time
-
- # highlight URLs
- mask = r'\1' % (
- self._options[self.NAMESPACE]['link_colour'])
- message_values['message'] = URL_RE.sub(mask,
- message_values['message'])
-
- # use a different highlight for the current user
- # TODO: How to handle this with several networks?
- #message = re.sub(r'(@'+self.twitter.username+')',
- # r'\1',
- # message)
-
- if not data.read:
- message_values['read_status'] = (' ' +
- self._options[self.NAMESPACE]['unread_char'])
- else:
- message_values['read_status'] = ''
-
- if data.favourite:
- message_values['favourite_star'] = (
- self._options[self.NAMESPACE]['unfavourite_char'])
- else:
- message_values['favourite_star'] = (
- self._options[self.NAMESPACE]['favourite_char'])
-
- info = []
- if data.reposted_by:
- info.append(_(' — reposted by %s') %
- (data.reposted_by.username))
-
- if data.parent_owner:
- info.append(_(' — in reply to %s') %
- (data.parent_owner.username))
-
- if data.protected:
- message_values['protected_status'] = (
- self._options[self.NAMESPACE]['protected_char'])
- else:
- message_values['protected_status'] = ''
-
- message_values['message_type'] = ''.join(info)
- markup = MESSAGE_FORMAT % (message_values)
-
- cell.set_property('markup', markup)
-
- return
-
- def _window_to_tray(self, statusicon, user_data=None):
- """Minimize/display main window (as in minimize to tray.)"""
- if self._main_window.get_property('visible'):
- self._main_window.hide()
- else:
- self._main_window.show()
- return
-
# ------------------------------------------------------------
# Helper functions
# ------------------------------------------------------------
@@ -515,41 +367,6 @@ class Interface(object):
self._reply_message_id = None
return
- def _url_popup(self, widget, path, event):
- """Builds the popup with URLs in the cell pointed by *path*. Requires
- the *event* that the widget received."""
- iter = widget.get_model().get_iter(path)
- message = widget.get_model().get_value(iter, 0)
-
- items = []
- link = self._connection.link(message)
- if link:
- network = self._connection.name(message.network)
- items.append((_('Open on %s') % (network), link))
-
- urls = URL_RE.findall(message.message)
- for url in urls:
- if len(url) > 20:
- title = url[:20] + '...'
- else:
- title = url
- items.append((title, url))
-
- if len(items) == 0:
- return
-
- popup = gtk.Menu()
- for url in items:
- (title, url) = url
- item = gtk.MenuItem(title)
- item.connect('activate', self._open_url, url)
- popup.append(item)
-
- popup.show_all()
- popup.popup(None, None, None, event.button, event.time)
-
- return True
-
def _message_count_updated(self):
"""Update the elements in the interface that should change in case of
changes in the message count."""
@@ -565,32 +382,36 @@ class Interface(object):
if (self._new_message_count + self._new_replies_count) == 0:
self._statusicon.set_from_pixbuf(self._images['icon'])
else:
- self._statusicon.set_from_pixbuf(self._images['new-messages'])
-
- return
+ self._statusicon.set_from_pixbuf(
+ self._images['new-messages'])
- def _fill_store(self, store, data):
- """Using the results from the request, fill a gtk.Store."""
- for message in data:
- message.read = False
- pic = message.author.avatar
- if not pic in self._avatars:
- # set the user avatar to the default image, so it won't get
- # queued again. Once downloaded, the _post_download_pic will
- # update the image and force a redraw.
- self._avatars[pic] = self._images['avatar']
- self._threads.add_work(self._post_download_pic,
- self._exception_download_pic,
- self._download_pic,
- pic)
-
- store.prepend([message])
- store.sort_column_changed()
return
# ------------------------------------------------------------
# Widget callback functions
# ------------------------------------------------------------
+ def _clear_posts(self, widget):
+ """Clear the posts in the currently selected tab."""
+ page = self._main_tabs.get_current_page()
+ child = self._main_tabs.get_nth_page(page)
+ child.clear_posts()
+ return
+
+ def _mark_all_read(self, widget):
+ """Mark all messages as read in the currently selected tab."""
+ page = self._main_tabs.get_current_page()
+ child = self._main_tabs.get_nth_page(page)
+ child.mark_all_read()
+ return
+
+ def _window_to_tray(self, statusicon, user_data=None):
+ """Minimize/display main window (as in minimize to tray.)"""
+ if self._main_window.get_property('visible'):
+ self._main_window.hide()
+ else:
+ self._main_window.show()
+ return
+
def _update_status(self, widget):
"""Update your status."""
if not self._update_field.get_property('visible'):
@@ -649,99 +470,12 @@ class Interface(object):
def _grid_resize(self, widget, requisition, data=None):
"""Called when the window is resized. We use it to set the proper
word-wrapping in the message column."""
- for grid in self._grids:
- (grid, counter) = grid
- model = grid.get_model()
- if len(model) == 0:
- # don't try to update if there are no data to be updated
- return
-
- (win_width, win_height) = self._main_window.get_size()
- column = grid.get_column(1)
- iter = model.get_iter_first()
- path = model.get_path(iter)
-
- width = win_width - 85 # 48 = icon size
- # TODO: Find out where those 37 pixels came from and/or if they
- # are platform specific.
-
- for renderer in column.get_cell_renderers():
- renderer.set_property('wrap-width', width)
-
- while iter:
- path = model.get_path(iter)
- model.row_changed(path, iter)
- iter = model.iter_next(iter)
- return
-
- def _order_datetime(self, model, iter1, iter2, user_data=None):
- """Used by the ListStore to sort the columns (in our case, "column")
- by date."""
- message1 = model.get_value(iter1, 0)
- message2 = model.get_value(iter2, 0)
-
- if (not message1) or \
- (not message1.message_time) or \
- (message1.message_time > message2.message_time):
- return -1
-
- if (not message2) or \
- (not message2.message_time) or \
- (message2.message_time > message1.message_time):
- return 1
- return 0
-
- def _message_selected(self, view, user_data=None):
- """Callback when a row in the list is selected. Mostly, we'll check
- if the message is from the logged user and we change de "sensitive"
- property of the message actions to reflect what the user can and
- cannot do."""
-
- (model, iter) = view.get_selection().get_selected()
- if not iter:
- return
- data = model.get_value(iter, 0)
-
- self._delete_action.set_property('sensitive',
- self._connection.can_delete(data))
- self._reply_action.set_property('sensitive',
- self._connection.can_reply(data))
- self._repost_action.set_property('sensitive',
- self._connection.can_repost(data))
- self._favourite_action.set_property('sensitive',
- self._connection.can_favourite(data))
-
- return 0
-
- def _clear_posts(self, widget, user_data=None):
- """Clear the list of posts from the grid."""
- page = self._main_tabs.get_current_page()
- (grid, counter) = self._grids[page]
- grid.get_model().clear()
- setattr(self, counter, 0)
- self._message_count_updated()
- return
-
- def _mark_all_read(self, widget, user_data=None):
- """Mark all messages as read."""
- page = self._main_tabs.get_current_page()
- (grid, counter) = self._grids[page]
- model = grid.get_model()
- if len(model) == 0:
- # no messages, so we don't worry (if I recall correctly,
- # get_iter_first will fail if the model is empty)
- return
-
- iter = model.get_iter_first()
- while iter:
- message = model.get_value(iter, 0)
- message.read = True
- iter = model.iter_next(iter)
-
- # update the counters
- set(attr, self, counter, 0)
- self._message_count_updated()
+ (win_width, win_height) = self._main_window.get_size()
+ total_tabs = self._main_tabs.get_n_pages()
+ for page in range(0, total_tabs):
+ child = self._main_tabs.get_nth_page(page)
+ child.update_window_size(win_width)
return
def _delete_message(self, widget, user_data=None):
@@ -915,57 +649,6 @@ class Interface(object):
self._options.save()
return True
- def _click_message(self, widget, event, user_data=None):
- """Check the click on the message and, if it's a right click, call the
- _message_popup function to show the popup."""
- if event.button != 3:
- # not right click
- return False
-
- path = widget.get_path_at_pos(event.x, event.y)
- if not path:
- return False
-
- (path, _, _, _) = path
- return self._url_popup(widget, path, event)
-
- def _message_popup(self, widget, user_data=None):
- """Builds the popup with the URLs in the message."""
- _log.debug('Popup')
- (path, _) = widget.get_cursor()
- if not path:
- return True
-
- # create a syntetic event (the popup requires one)
- event = gtk.gdk.Event(gtk.gdk.BUTTON_PRESS)
- event.button = 3
- return self._url_popup(widget, path, event)
-
- def _open_url(self, widget, user_data=None):
- """Opens an URL (used mostly from popup menu items.)"""
- webbrowser.open_new_tab(user_data)
- return
-
- def _mark_message_read(self, widget, user_data=None):
- """Mark a message as read when it's selected."""
- (path, _) = widget.get_cursor()
- if not path:
- return True
-
- iter = widget.get_model().get_iter(path)
- message = widget.get_model().get_value(iter, 0)
-
- if message.read:
- return True
-
- # Do it generically, so we can reuse this function to both grids
- counter = getattr(self, user_data)
- setattr(self, user_data, counter - 1)
-
- message.read = True
- self._message_count_updated()
- return True
-
def _change_tab(self, widget, user_data=None):
"""Change the notebook tab to display a differnt tab."""
if not user_data:
@@ -1245,8 +928,8 @@ class Interface(object):
return
def __call__(self):
- """Call function; displays the interface. This method should appear on
- every interface."""
+ """Call function; displays the interface. This method should
+ appear on every interface."""
if self._options[self.NAMESPACE]['statusicon']:
self._statusicon = gtk.StatusIcon()