diff --git a/frontends/src/primitivus/chat.py b/frontends/src/primitivus/chat.py
index a4905ddc..beaa472b 100644
--- a/frontends/src/primitivus/chat.py
+++ b/frontends/src/primitivus/chat.py
@@ -22,9 +22,9 @@ along with this program. If not, see .
import urwid
from urwid_satext import sat_widgets
from urwid_satext.files_management import FileDialog
-from sat_frontends.quick_frontend.quick_contact_list import QuickContactList
from sat_frontends.quick_frontend.quick_chat import QuickChat
from sat_frontends.primitivus.card_game import CardGame
+from sat_frontends.quick_frontend.quick_utils import unescapePrivate
import time
from sat.tools.jid import JID
@@ -145,7 +145,7 @@ class Chat(urwid.WidgetWrap, QuickChat):
self.__appendPresentPanel()
def __getDecoration(self, widget):
- return sat_widgets.LabelLine(widget, sat_widgets.SurroundedText(unicode(self.target)))
+ return sat_widgets.LabelLine(widget, sat_widgets.SurroundedText(unicode(unescapePrivate(self.target))))
def showDecoration(self, show=True):
"""Show/Hide the decoration around the chat window"""
diff --git a/frontends/src/primitivus/contact_list.py b/frontends/src/primitivus/contact_list.py
index 0277c228..71b6eb97 100644
--- a/frontends/src/primitivus/contact_list.py
+++ b/frontends/src/primitivus/contact_list.py
@@ -22,6 +22,7 @@ along with this program. If not, see .
import urwid
from urwid_satext import sat_widgets
from sat_frontends.quick_frontend.quick_contact_list import QuickContactList
+from sat_frontends.quick_frontend.quick_utils import escapePrivate, unescapePrivate
from sat.tools.jid import JID
@@ -29,10 +30,10 @@ class ContactList(urwid.WidgetWrap, QuickContactList):
signals = ['click','change']
def __init__(self, host, on_click=None, on_change=None, user_data=None):
+ QuickContactList.__init__(self)
self.host = host
self.selected = None
self.groups={}
- self.special={}
self.alert_jid=set()
self.show_status = False
self.show_disconnected = False
@@ -45,7 +46,6 @@ class ContactList(urwid.WidgetWrap, QuickContactList):
urwid.connect_signal(self, 'click', on_click, user_data)
if on_change:
urwid.connect_signal(self, 'change', on_change, user_data)
- QuickContactList.__init__(self)
def update(self):
"""Update display, keep focus"""
@@ -115,18 +115,23 @@ class ContactList(urwid.WidgetWrap, QuickContactList):
widgets = [] #list of built widgets
for contact in contacts:
- jid=JID(contact)
- name = self.getCache(jid, 'name')
- nick = self.getCache(jid, 'nick')
- status = self.getCache(jid, 'status')
- show = self.getCache(jid, 'show')
- if show == None:
- show = "unavailable"
- if (not self.show_disconnected and show == "unavailable"
- and not contact in self.alert_jid and contact != self.selected):
- continue
- show_icon, show_attr = const_SHOW_ICON.get(show,('','default'))
- contact_disp = ('alert' if contact in self.alert_jid else show_attr, nick or name or jid.node or jid.short)
+ if contact.startswith(const_PRIVATE_PREFIX):
+ contact_disp = ('alert' if contact in self.alert_jid else "show_normal", unescapePrivate(contact))
+ show_icon = ''
+ status = ''
+ else:
+ jid=JID(contact)
+ name = self.getCache(jid, 'name')
+ nick = self.getCache(jid, 'nick')
+ status = self.getCache(jid, 'status')
+ show = self.getCache(jid, 'show')
+ if show == None:
+ show = "unavailable"
+ if (not self.show_disconnected and show == "unavailable"
+ and not contact in self.alert_jid and contact != self.selected):
+ continue
+ show_icon, show_attr = const_SHOW_ICON.get(show,('','default'))
+ contact_disp = ('alert' if contact in self.alert_jid else show_attr, nick or name or jid.node or jid.short)
display = [ show_icon + " " , contact_disp]
if self.show_status:
status_disp = ('status',"\n " + status) if status else ""
@@ -147,7 +152,7 @@ class ContactList(urwid.WidgetWrap, QuickContactList):
def __buildSpecials(self, content):
"""Build the special entities"""
- specials = self.special.keys()
+ specials = self.specials.keys()
specials.sort()
for special in specials:
jid=JID(special)
@@ -168,7 +173,7 @@ class ContactList(urwid.WidgetWrap, QuickContactList):
content = urwid.SimpleListWalker([])
self.__buildSpecials(content)
- if self.special:
+ if self.specials:
content.append(urwid.Divider('='))
group_keys = self.groups.keys()
@@ -198,6 +203,7 @@ class ContactList(urwid.WidgetWrap, QuickContactList):
def clearContacts(self):
"""clear all the contact list"""
+ QuickContactList.clearContacts(self)
self.groups={}
self.selected = None
self.unselectAll()
@@ -205,7 +211,8 @@ class ContactList(urwid.WidgetWrap, QuickContactList):
def replace(self, jid, groups=None, attributes=None):
"""add a contact to the list if doesn't exist, else update it"""
- if jid.short in self.special:
+ QuickContactList.replace(self, jid, groups, attributes)
+ if jid.short in self.specials:
return
if not groups:
groups = [None]
@@ -227,10 +234,10 @@ class ContactList(urwid.WidgetWrap, QuickContactList):
self.list_wid.changeValues(contacts)
self._emit('change')"""
- def remove(self, param_jid):
+ def remove(self, jid):
"""remove a contact from the list"""
+ QuickContactList.remove(self, jid)
groups_to_remove = []
- jid = JID(param_jid)
for group in self.groups:
contacts = self.groups[group][1]
if jid.short in contacts:
@@ -239,10 +246,6 @@ class ContactList(urwid.WidgetWrap, QuickContactList):
groups_to_remove.append(group)
for group in groups_to_remove:
del self.groups[group]
- try:
- del self.special[jid.short]
- except KeyError:
- pass
self.update()
def add(self, jid, param_groups=[None]):
@@ -254,7 +257,7 @@ class ContactList(urwid.WidgetWrap, QuickContactList):
@param jid: jid of the entity
@param _type: special type (e.g.: "MUC")
"""
- self.special[special_jid.short] = special_type
+ QuickContactList.setSpecial(self, special_jid, special_type)
if None in self.groups:
folded,group_jids = self.groups[None]
for group_jid in group_jids:
@@ -265,5 +268,5 @@ class ContactList(urwid.WidgetWrap, QuickContactList):
def updatePresence(self, jid, show, priority, statuses):
#XXX: for the moment, we ignore presence updates for special entities
- if jid.short not in self.special:
+ if jid.short not in self.specials:
QuickContactList.updatePresence(self, jid, show, priority, statuses)
diff --git a/frontends/src/primitivus/primitivus b/frontends/src/primitivus/primitivus
index 724e5fc1..624ee6f9 100755
--- a/frontends/src/primitivus/primitivus
+++ b/frontends/src/primitivus/primitivus
@@ -24,8 +24,6 @@ import urwid
from urwid_satext import sat_widgets
from sat_frontends.quick_frontend.quick_app import QuickApp
from sat_frontends.quick_frontend.quick_chat_list import QuickChatList
-from sat_frontends.quick_frontend.quick_contact_list import QuickContactList
-from sat_frontends.quick_frontend.quick_contact_management import QuickContactManagement
from sat_frontends.primitivus.profile_manager import ProfileManager
from sat_frontends.primitivus.contact_list import ContactList
from sat_frontends.primitivus.chat import Chat
@@ -47,9 +45,6 @@ logging.basicConfig(level=logging.CRITICAL, #TODO: configure it to put messages
class ChatList(QuickChatList):
"""This class manage the list of chat windows"""
- def __init__(self, host):
- QuickChatList.__init__(self, host)
-
def createChat(self, target):
return Chat(target, self.host)
@@ -300,7 +295,7 @@ class PrimitivusApp(QuickApp):
if contact:
chat = self.chat_wins[contact]
try:
- self.bridge.sendMessage(contact,
+ self.sendMessage(contact,
editBar.get_edit_text(),
mess_type = "groupchat" if chat.type == 'group' else "chat",
profile_key=self.profile)
@@ -308,18 +303,17 @@ class PrimitivusApp(QuickApp):
self.notify(_("Error while sending message"))
editBar.set_edit_text('')
- def newMessage(self, from_jid, msg, type, to_jid, profile):
- if not self.check_profile(profile):
- return
- sender = JID(from_jid)
- if not sender in self.contact_list and sender.short != self.profiles[profile]['whoami'].short:
+ def newMessage(self, from_jid, to_jid, msg, _type, profile):
+ QuickApp.newMessage(self, from_jid, to_jid, msg, _type, profile)
+
+ if not from_jid in self.contact_list and from_jid.short != self.profiles[profile]['whoami'].short:
#XXX: needed to show entities which haven't sent any
# presence information and which are not in roster
#TODO: put these entities in a "not in roster" list
- self.contact_list.replace(sender)
- QuickApp.newMessage(self, from_jid, msg, type, to_jid, profile)
- if JID(self.contact_list.selected).short != sender.short:
- self.contact_list.putAlert(sender)
+ self.contact_list.replace(from_jid)
+
+ if JID(self.contact_list.selected).short != from_jid.short:
+ self.contact_list.putAlert(from_jid)
def _dialogOkCb(self, widget, data):
self.removePopUp()
diff --git a/frontends/src/quick_frontend/constants.py b/frontends/src/quick_frontend/constants.py
new file mode 100644
index 00000000..365caa5e
--- /dev/null
+++ b/frontends/src/quick_frontend/constants.py
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Primitivus: a SAT frontend
+Copyright (C) 2009, 2010, 2011, 2012 Jérôme Poisson (goffi@goffi.org)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero 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 Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+"""
+import __builtin__
+
+__builtin__.__dict__['const_PRIVATE_PREFIX'] = "@PRIVATE@"
diff --git a/frontends/src/quick_frontend/quick_app.py b/frontends/src/quick_frontend/quick_app.py
index b503f5fa..f8308d4a 100644
--- a/frontends/src/quick_frontend/quick_app.py
+++ b/frontends/src/quick_frontend/quick_app.py
@@ -22,8 +22,11 @@ along with this program. If not, see .
from logging import debug, info, warning, error
from sat.tools.jid import JID
from sat_frontends.bridge.DBus import DBusBridgeFrontend,BridgeExceptionNoService
+from sat_frontends.quick_frontend.quick_utils import escapePrivate, unescapePrivate
from optparse import OptionParser
+import sat_frontends.quick_frontend.constants
+
import gettext
gettext.install('sat_frontend', "../i18n", unicode=True)
@@ -46,7 +49,7 @@ class QuickApp():
self.bridge.register("disconnected", self.disconnected)
self.bridge.register("connectionError", self.connectionError)
self.bridge.register("newContact", self.newContact)
- self.bridge.register("newMessage", self.newMessage)
+ self.bridge.register("newMessage", self._newMessage)
self.bridge.register("newAlert", self.newAlert)
self.bridge.register("presenceUpdate", self.presenceUpdate)
self.bridge.register("subscribe", self.subscribe)
@@ -230,17 +233,48 @@ class QuickApp():
return
entity=JID(JabberId)
_groups = list(groups)
- self.contact_list._replace(entity, _groups, attributes)
-
- def newMessage(self, from_jid, msg, type, to_jid, profile):
+ self.contact_list.replace(entity, _groups, attributes)
+
+ def _newMessage(self, from_jid_s, msg, _type, to_jid_s, profile):
+ """newMessage premanagement: a dirty hack to manage private messages
+ if a private MUC message is detected, from_jid or to_jid is prefixed and resource is escaped"""
if not self.check_profile(profile):
return
- sender=JID(from_jid)
- addr=JID(to_jid)
- win = addr if sender.short == self.profiles[profile]['whoami'].short else sender
+ from_jid = JID(from_jid_s)
+ to_jid = JID(to_jid_s)
+
+ from_me = from_jid.short == self.profiles[profile]['whoami'].short
+ win = to_jid if from_me else from_jid
+
+ if _type != "groupchat" and self.contact_list.getSpecial(win) == "MUC":
+ #we have a private message in a MUC room
+ #XXX: normaly we use bare jid as key, here we need the full jid
+ # so we cheat by replacing the "/" before the resource by
+ # a "@", so the jid is invalid,
+ new_jid = escapePrivate(win)
+ if from_me:
+ to_jid = new_jid
+ else:
+ from_jid = new_jid
+ if new_jid not in self.contact_list:
+ self.contact_list.add(new_jid)
+
+ self.newMessage(from_jid, to_jid, msg, _type, profile)
+
+ def newMessage(self, from_jid, to_jid, msg, _type, profile):
+ from_me = from_jid.short == self.profiles[profile]['whoami'].short
+ win = to_jid if from_me else from_jid
+
self.current_action_ids = set()
self.current_action_ids_cb = {}
- self.chat_wins[win.short].printMessage(sender, msg, profile)
+
+ self.chat_wins[win.short].printMessage(from_jid, msg, profile)
+
+ def sendMessage(self, to_jid, message, subject='', mess_type="auto", profile_key="@DEFAULT@"):
+ if to_jid.startswith(const_PRIVATE_PREFIX):
+ to_jid = unescapePrivate(to_jid)
+ mess_type = "chat"
+ self.bridge.sendMessage(to_jid, message, subject, mess_type, profile_key)
def newAlert(self, msg, title, alert_type, profile):
if not self.check_profile(profile):
@@ -292,13 +326,13 @@ class QuickApp():
self.chat_wins[room_jid].setPresents(list(set([user_nick]+room_nicks)))
self.contact_list.setSpecial(JID(room_jid), "MUC")
- def roomLeft(self, room_jid, profile):
+ def roomLeft(self, room_jid_s, profile):
"""Called when a MUC room is left"""
if not self.check_profile(profile):
return
- debug (_("Room [%(room_jid)s] left by %(profile)s") % {'room_jid':room_jid, 'profile': profile})
- del self.chat_wins[room_jid]
- self.contact_list.remove(room_jid)
+ debug (_("Room [%(room_jid)s] left by %(profile)s") % {'room_jid':room_jid_s, 'profile': profile})
+ del self.chat_wins[room_jid_s]
+ self.contact_list.remove(JID(room_jid_s))
def roomUserJoined(self, room_jid, user_nick, user_data, profile):
"""Called when an user joined a MUC room"""
@@ -504,12 +538,12 @@ class QuickApp():
if key == "nick":
if jid in self.contact_list:
self.contact_list.setCache(jid, 'nick', value)
- self.contact_list._replace(jid)
+ self.contact_list.replace(jid)
elif key == "avatar":
if jid in self.contact_list:
filename = self.bridge.getAvatarFile(value)
self.contact_list.setCache(jid, 'avatar', filename)
- self.contact_list._replace(jid)
+ self.contact_list.replace(jid)
def askConfirmation(self, type, id, data):
raise NotImplementedError
diff --git a/frontends/src/quick_frontend/quick_chat.py b/frontends/src/quick_frontend/quick_chat.py
index a0964acc..abcfd5fc 100644
--- a/frontends/src/quick_frontend/quick_chat.py
+++ b/frontends/src/quick_frontend/quick_chat.py
@@ -21,7 +21,7 @@ along with this program. If not, see .
from logging import debug, info, warning, error
from sat.tools.jid import JID
-
+from sat_frontends.quick_frontend.quick_utils import unescapePrivate
class QuickChat():
@@ -110,6 +110,8 @@ class QuickChat():
def _get_nick(self, jid):
"""Return nick of this jid when possible"""
+ if jid.startswith(const_PRIVATE_PREFIX):
+ return unescapePrivate(jid).resource
return jid.resource if self.type == "group" else (self.host.contact_list.getCache(jid,'nick') or self.host.contact_list.getCache(jid,'name') or jid.node)
def printMessage(self, from_jid, msg, profile, timestamp):
diff --git a/frontends/src/quick_frontend/quick_contact_list.py b/frontends/src/quick_frontend/quick_contact_list.py
index 40447773..3a83776e 100644
--- a/frontends/src/quick_frontend/quick_contact_list.py
+++ b/frontends/src/quick_frontend/quick_contact_list.py
@@ -28,6 +28,7 @@ class QuickContactList():
def __init__(self):
debug(_("Contact List init"))
self._cache = {}
+ self.specials={}
def update_jid(self, jid):
"""Update the jid in the list when something changed"""
@@ -51,31 +52,34 @@ class QuickContactList():
def clearContacts(self, jid):
"""Clear all the contact list"""
- raise NotImplementedError
+ self.specials.clear()
- def _replace(self, jid, groups=None, attributes=None):
+ def replace(self, jid, groups=None, attributes=None):
+ """add a contact to the list if doesn't exist, else update it"""
if attributes and 'name' in attributes:
self.setCache(jid, 'name', attributes['name'])
- self.replace(jid, groups, attributes)
-
- def replace(self, jid, groups, attributes):
- """add a contact to the list if doesn't exist, else update it"""
- raise NotImplementedError
def remove(self, jid):
"""remove a contact from the list"""
- raise NotImplementedError
+ try:
+ del self.specials[jid.short]
+ except KeyError:
+ pass
def add(self, jid, param_groups=None):
"""add a contact to the list"""
raise NotImplementedError
+ def getSpecial(self, jid):
+ """Return special type of jid, or None if it's not special"""
+ return self.specials.get(jid.short)
+
def setSpecial(self, jid, _type):
"""Set entity as a special
@param jid: jid of the entity
@param _type: special type (e.g.: "MUC")
"""
- raise NotImplementedError
+ self.specials[jid.short] = _type
def updatePresence(self, jid, show, priority, statuses):
"""Update entity's presence status
diff --git a/frontends/src/quick_frontend/quick_utils.py b/frontends/src/quick_frontend/quick_utils.py
new file mode 100644
index 00000000..2e531b88
--- /dev/null
+++ b/frontends/src/quick_frontend/quick_utils.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Primitivus: a SAT frontend
+Copyright (C) 2009, 2010, 2011, 2012 Jérôme Poisson (goffi@goffi.org)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero 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 Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+"""
+
+from sat.tools.jid import JID
+
+def escapePrivate(ori_jid):
+ """Escape a private jid"""
+ return JID(const_PRIVATE_PREFIX + ori_jid.short + '@' + ori_jid.resource)
+
+def unescapePrivate(escaped_jid):
+ if not escaped_jid.startswith(const_PRIVATE_PREFIX):
+ return escaped_jid
+ escaped_split = tuple(escaped_jid[len(const_PRIVATE_PREFIX):].split('@'))
+ assert(len(escaped_split) == 3)
+ return JID("%s@%s/%s" % escaped_split)
diff --git a/frontends/src/wix/chat.py b/frontends/src/wix/chat.py
index 9122e89c..4dfefcb0 100644
--- a/frontends/src/wix/chat.py
+++ b/frontends/src/wix/chat.py
@@ -201,7 +201,7 @@ class Chat(wx.Frame, QuickChat):
def onEnterPressed(self, event):
"""Behaviour when enter pressed in send line."""
- self.host.bridge.sendMessage(self.target.short if self.type=='group' else self.target,
+ self.host.sendMessage(self.target.short if self.type=='group' else self.target,
event.GetString(),
mess_type = "groupchat" if self.type=='group' else "chat",
profile_key=self.host.profile)
diff --git a/frontends/src/wix/contact_list.py b/frontends/src/wix/contact_list.py
index eaa066ce..92c5cc78 100644
--- a/frontends/src/wix/contact_list.py
+++ b/frontends/src/wix/contact_list.py
@@ -169,8 +169,7 @@ class ContactList(wx.SimpleHtmlListBox, QuickContactList):
self.Insert(_present, gp_idx+1, contact)
def setSpecial(self, special_jid, special_type):
- pass
-
+ QuickContactList.setSpecial(self, special_jid, special_type)
def remove(self, contact):
"""remove a contact from the list"""
diff --git a/frontends/src/wix/main_window.py b/frontends/src/wix/main_window.py
index a6a1c43b..f9cd664f 100644
--- a/frontends/src/wix/main_window.py
+++ b/frontends/src/wix/main_window.py
@@ -22,7 +22,6 @@ along with this program. If not, see .
from sat_frontends.quick_frontend.quick_chat_list import QuickChatList
from sat_frontends.quick_frontend.quick_app import QuickApp
-from sat_frontends.quick_frontend.quick_contact_management import QuickContactManagement
import wx
from sat_frontends.wix.contact_list import ContactList
from sat_frontends.wix.chat import Chat
@@ -31,9 +30,7 @@ from sat_frontends.wix.xmlui import XMLUI
from sat_frontends.wix.gateways import GatewaysManager
from sat_frontends.wix.profile import Profile
from sat_frontends.wix.profile_manager import ProfileManager
-import gobject
import os.path
-import pdb
from sat.tools.jid import JID
from logging import debug, info, warning, error
import sat_frontends.wix.constants
@@ -52,9 +49,6 @@ idFIND_GATEWAYS = range(10)
class ChatList(QuickChatList):
"""This class manage the list of chat windows"""
- def __init__(self, host):
- QuickChatList.__init__(self, host)
-
def createChat(self, target):
return Chat(target, self.host)
@@ -186,8 +180,8 @@ class MainWindow(wx.Frame, QuickApp):
wx.EVT_MENU(self, idFIND_GATEWAYS, self.onFindGateways)
- def newMessage(self, from_jid, msg, type, to_jid, profile):
- QuickApp.newMessage(self, from_jid, msg, type, to_jid, profile)
+ def newMessage(self, from_jid, to_jid, msg, _type, profile):
+ QuickApp.newMessage(self, from_jid, to_jid, msg, _type, profile)
def showAlert(self, message):
# TODO: place this in a separate class