diff --git a/src/chat_control.py b/src/chat_control.py
index 5ad38e423..5a899cba4 100644
--- a/src/chat_control.py
+++ b/src/chat_control.py
@@ -12,6 +12,8 @@
## GNU General Public License for more details.
##
+import os, os.path
+import math
import gtk
import gtk.glade
import pango
@@ -87,6 +89,13 @@ class ChatControlBase(MessageControl):
self.nb_unread = 0
+ # Emoticons menu
+ # set image no matter if user wants at this time emoticons or not
+ # (so toggle works ok)
+ img = self.xml.get_widget('emoticons_button_image')
+ img.set_from_file(os.path.join(gajim.DATA_DIR, 'emoticons', 'smile.png'))
+ self.toggle_emoticons()
+
def _paint_banner(self):
'''Repaint banner with theme color'''
theme = gajim.config.get('roster_theme')
@@ -265,6 +274,57 @@ class ChatControlBase(MessageControl):
self.redraw_tab(jid)
self.show_title(urgent)
+ def toggle_emoticons(self):
+ '''hide show emoticons_button and make sure emoticons_menu is always there
+ when needed'''
+ emoticons_button = self.xml.get_widget('emoticons_button')
+ if gajim.config.get('useemoticons'):
+ self.emoticons_menu = self.prepare_emoticons_menu()
+ emoticons_button.show()
+ emoticons_button.set_no_show_all(False)
+ else:
+ self.emoticons_menu = None
+ emoticons_button.hide()
+ emoticons_button.set_no_show_all(True)
+
+ def prepare_emoticons_menu(self):
+ menu = gtk.Menu()
+
+ def append_emoticon(w, d):
+ buffer = self.msg_textview.get_buffer()
+ if buffer.get_char_count():
+ buffer.insert_at_cursor(' %s ' % d)
+ else: # we are the beginning of buffer
+ buffer.insert_at_cursor('%s ' % d)
+ self.msg_textview.grab_focus()
+
+ counter = 0
+ # Calculate the side lenght of the popup to make it a square
+ size = int(round(math.sqrt(len(gajim.interface.emoticons_images))))
+ for image in gajim.interface.emoticons_images:
+ item = gtk.MenuItem()
+ img = gtk.Image()
+ if type(image[1]) == gtk.gdk.PixbufAnimation:
+ img.set_from_animation(image[1])
+ else:
+ img.set_from_pixbuf(image[1])
+ item.add(img)
+ item.connect('activate', append_emoticon, image[0])
+ #FIXME: add tooltip with ascii
+ menu.attach(item,
+ counter % size, counter % size + 1,
+ counter / size, counter / size + 1)
+ counter += 1
+ menu.show_all()
+ return menu
+
+ def on_emoticons_button_clicked(self, widget):
+ '''popup emoticons menu'''
+ #FIXME: BUG http://bugs.gnome.org/show_bug.cgi?id=316786
+ self.button_clicked = widget
+ self.emoticons_menu.popup(None, None, self.position_menu_under_button, 1, 0)
+
+
class ChatControl(ChatControlBase):
'''A control for standard 1-1 chat'''
def __init__(self, parent_win, contact, acct):
@@ -475,7 +535,6 @@ class ChatControl(ChatControlBase):
self.mouse_over_in_last_30_secs = False
self.kbd_activity_in_last_30_secs = False
-
def print_conversation(self, text, frm = '', tim = None,
encrypted = False, subject = None):
'''Print a line in the conversation:
diff --git a/src/config.py b/src/config.py
index 714b84190..54736144a 100644
--- a/src/config.py
+++ b/src/config.py
@@ -502,14 +502,8 @@ class PreferencesWindow:
def toggle_emoticons(self):
'''Update emoticons state in Opened Chat Windows'''
- for a in gajim.connections:
- for kind in ('chats', 'gc'):
- windows = gajim.interface.instances[a][kind]
- if windows.has_key('tabbed'):
- windows['tabbed'].toggle_emoticons()
- else:
- for jid in windows.keys():
- windows[jid].toggle_emoticons()
+ for win in gajim.interface.msg_win_mgr.windows.values():
+ win.toggle_emoticons()
def on_add_remove_emoticons_button_clicked(self, widget):
if gajim.interface.instances.has_key('manage_emots'):
diff --git a/src/gajim.py b/src/gajim.py
index e5ea10a43..5565fe114 100755
--- a/src/gajim.py
+++ b/src/gajim.py
@@ -38,6 +38,8 @@ from common import i18n
i18n.init()
_ = i18n._
+from message_window import MessageWindowMgr
+
try:
import gtk
except RuntimeError, msg:
@@ -1450,6 +1452,9 @@ class Interface:
gobject.timeout_add(200, self.process_connections)
gobject.timeout_add(500, self.read_sleepy)
+ # This is the manager and factory of message windows
+ self.msg_win_mgr = MessageWindowMgr()
+
def test_migration(migration):
if not migration.PROCESSING:
dialog = gtk.Dialog()
diff --git a/src/gtkgui.glade b/src/gtkgui.glade
index d1d01feb3..42191fbe0 100644
--- a/src/gtkgui.glade
+++ b/src/gtkgui.glade
@@ -19395,7 +19395,7 @@ Status message
6
-
+
True
Click to insert an emoticon (Alt+E)
True
@@ -19410,7 +19410,7 @@ Status message
0
-
+
True
0.5
0.5
@@ -20034,7 +20034,7 @@ topic
6
-
+
True
Click to insert an emoticon (Alt+E)
True
@@ -20049,7 +20049,7 @@ topic
0
-
+
True
0.5
0.5
diff --git a/src/message_window.py b/src/message_window.py
index 6be780a1f..7f4572b4e 100644
--- a/src/message_window.py
+++ b/src/message_window.py
@@ -202,7 +202,12 @@ class MessageWindow:
def is_active(self):
return self.window.is_active()
+ def get_origin(self):
+ return self.window.window.get_origin()
+ def toggle_emoticons(self):
+ for ctl in self._controls.values():
+ ctl.toggle_emoticons()
class MessageWindowMgr:
'''A manager and factory for MessageWindow objects'''
@@ -286,6 +291,8 @@ class MessageControl(gtk.VBox):
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 draw_widgets(self):
pass # NOTE: Derived classes should implement this
@@ -293,6 +300,8 @@ class MessageControl(gtk.VBox):
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 send_message(self, message, keyID = '', chatstate = None):
'''Send the given message to the active tab'''
@@ -306,4 +315,33 @@ class MessageControl(gtk.VBox):
# Send and update history
gajim.connections[self.account].send_message(jid, message, keyID, 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/roster_window.py b/src/roster_window.py
index 9a41ec86a..8495906b9 100644
--- a/src/roster_window.py
+++ b/src/roster_window.py
@@ -48,7 +48,6 @@ from gajim import Contact
from common import gajim
from common import helpers
from common import i18n
-from message_window import MessageWindowMgr
from chat_control import ChatControl
_ = i18n._
@@ -1652,7 +1651,7 @@ _('If "%s" accepts this request you will know his or her status.') %jid)
def new_chat(self, contact, account):
# Get target window
- mw = self.msg_win_mgr.get_window(contact, account, None) # FIXME: type arg
+ mw = gajim.interface.msg_win_mgr.get_window(contact, account, None) # FIXME: type arg
chat_control = ChatControl(mw, contact, account)
mw.new_tab(chat_control)
@@ -2225,7 +2224,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 self.msg_win_mgr.windows.values():
+ for win in gajim.interface.msg_win_mgr.windows.values():
win.repaint_themed_widgets()
for account in gajim.connections:
for addr in gajim.interface.instances[account]['disco']:
@@ -2732,5 +2731,3 @@ _('If "%s" accepts this request you will know his or her status.') %jid)
gajim.interface.instances['account_creation_wizard'] = \
config.AccountCreationWizardWindow()
- # This is the manager and factory of message windows
- self.msg_win_mgr = MessageWindowMgr()