Files reorganisation

This commit is contained in:
Goffi 2010-12-29 01:06:29 +01:00
commit e4452c4b03
8 changed files with 10 additions and 8 deletions

View file

View file

@ -0,0 +1,437 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
helper class for making a SAT frontend
Copyright (C) 2009, 2010 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 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 <http://www.gnu.org/licenses/>.
"""
from logging import debug, info, error
from tools.jid import JID
from sat_bridge_frontend.DBus import DBusBridgeFrontend,BridgeExceptionNoService
from optparse import OptionParser
import pdb
import gettext
gettext.install('sat_frontend', "../i18n", unicode=True)
class QuickApp():
"""This class contain the main methods needed for the frontend"""
def __init__(self, single_profile=True):
self.rosterList = {}
self.profiles = {}
self.single_profile = single_profile
self.check_options()
## bridge ##
try:
self.bridge=DBusBridgeFrontend()
except BridgeExceptionNoService:
print(_(u"Can't connect to SàT backend, are you sure it's launched ?"))
import sys
sys.exit(1)
self.bridge.register("connected", self.connected)
self.bridge.register("disconnected", self.disconnected)
self.bridge.register("newContact", self.newContact)
self.bridge.register("newMessage", self.newMessage)
self.bridge.register("newAlert", self.newAlert)
self.bridge.register("presenceUpdate", self.presenceUpdate)
self.bridge.register("roomJoined", self.roomJoined)
self.bridge.register("roomUserJoined", self.roomUserJoined)
self.bridge.register("roomUserLeft", self.roomUserLeft)
self.bridge.register("roomNewSubject", self.roomNewSubject)
self.bridge.register("tarotGameStarted", self.tarotGameStarted)
self.bridge.register("tarotGameNew", self.tarotGameNew)
self.bridge.register("tarotGameChooseContrat", self.tarotChooseContrat)
self.bridge.register("tarotGameShowCards", self.tarotShowCards)
self.bridge.register("tarotGameYourTurn", self.tarotMyTurn)
self.bridge.register("tarotGameScore", self.tarotScore)
self.bridge.register("tarotGameCardsPlayed", self.tarotCardsPlayed)
self.bridge.register("tarotGameInvalidCards", self.tarotInvalidCards)
self.bridge.register("subscribe", self.subscribe)
self.bridge.register("paramUpdate", self.paramUpdate)
self.bridge.register("contactDeleted", self.contactDeleted)
self.bridge.register("updatedValue", self.updatedValue, "request")
self.bridge.register("askConfirmation", self.askConfirmation, "request")
self.bridge.register("actionResult", self.actionResult, "request")
self.bridge.register("actionResultExt", self.actionResult, "request")
self.current_action_ids = set()
self.current_action_ids_cb = {}
def check_profile(self, profile):
"""Tell if the profile is currently followed by the application"""
return profile in self.profiles.keys()
def postInit(self):
"""Must be called after initialization is done, do all automatic task (auto plug profile)"""
if self.options.profile:
if not self.bridge.getProfileName(self.options.profile):
error(_("Trying to plug an unknown profile (%s)" % self.options.profile))
else:
self.plug_profile(self.options.profile)
def check_options(self):
"""Check command line options"""
usage=_("""
%prog [options]
%prog --help for options list
""")
parser = OptionParser(usage=usage)
parser.add_option("-p", "--profile", help=_("Select the profile to use"))
(self.options, args) = parser.parse_args()
if self.options.profile:
self.options.profile = self.options.profile.decode('utf-8')
return args
def plug_profile(self, profile_key='@DEFAULT@'):
"""Tell application which profile must be used"""
if self.single_profile and self.profiles:
error(_('There is already one profile plugged (we are in single profile mode) !'))
return
profile = self.bridge.getProfileName(profile_key)
if not profile:
error(_("The profile asked doesn't exist"))
return
if self.profiles.has_key(profile):
warning(_("The profile is already plugged"))
return
self.profiles[profile]={}
if self.single_profile:
self.profile = profile
###now we get the essential params###
self.profiles[profile]['whoami']=JID(self.bridge.getParamA("JabberID","Connection", profile))
autoconnect = self.bridge.getParamA("autoconnect","Connection", profile) == "true"
self.profiles[profile]['watched']=self.bridge.getParamA("Watched", "Misc", profile).split() #TODO: put this in a plugin
## misc ##
self.profiles[profile]['onlineContact'] = set() #FIXME: temporary
#TODO: gof: manage multi-profiles here
if not self.bridge.isConnected(profile):
self.setStatusOnline(False)
else:
self.setStatusOnline(True)
### now we fill the contact list ###
for contact in self.bridge.getContacts(profile):
self.newContact(contact[0], contact[1], contact[2], profile)
presences = self.bridge.getPresenceStatus(profile)
for contact in presences:
for res in presences[contact]:
jabber_id = contact+('/'+res if res else '')
show = presences[contact][res][0]
priority = presences[contact][res][1]
statuses = presences[contact][res][2]
self.presenceUpdate(jabber_id, show, priority, statuses, profile)
#The waiting subscription requests
waitingSub = self.bridge.getWaitingSub(profile)
for sub in waitingSub:
self.subscribe(waitingSub[sub], sub, profile)
#Now we open the MUC window where we already are:
for room_args in self.bridge.getRoomJoined(profile):
self.roomJoined(*room_args, profile=profile)
for subject_args in self.bridge.getRoomSubjects(profile):
self.roomNewSubject(*subject_args, profile=profile)
if autoconnect and not self.bridge.isConnected(profile_key):
#Does the user want autoconnection ?
self.bridge.connect(profile_key)
def unplug_profile(self, profile):
"""Tell the application to not follow anymore the profile"""
if not profile in self.profiles:
warning (_("This profile is not plugged"))
return
self.profiles.remove(profile)
def clear_profile(self):
self.profiles.clear()
def connected(self, profile):
"""called when the connection is made"""
if not self.check_profile(profile):
return
debug(_("Connected"))
self.setStatusOnline(True)
def disconnected(self, profile):
"""called when the connection is closed"""
if not self.check_profile(profile):
return
debug(_("Disconnected"))
self.CM.clear()
self.contactList.clear_contacts()
self.setStatusOnline(False)
def newContact(self, JabberId, attributes, groups, profile):
if not self.check_profile(profile):
return
entity=JID(JabberId)
self.rosterList[entity.short]=(dict(attributes), list(groups))
def newMessage(self, from_jid, msg, type, to_jid, profile):
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
self.current_action_ids = set()
self.current_action_ids_cb = {}
self.chat_wins[win.short].printMessage(sender, msg, profile)
def newAlert(self, msg, title, alert_type, profile):
if not self.check_profile(profile):
return
assert alert_type in ['INFO','ERROR']
self.showDialog(unicode(msg),unicode(title),alert_type.lower())
def setStatusOnline(self, online=True):
pass
def presenceUpdate(self, jabber_id, show, priority, statuses, profile):
if not self.check_profile(profile):
return
debug (_("presence update for %(jid)s (show=%(show)s, priority=%(priority)s, statuses=%(statuses)s) [profile:%(profile)s]") % {'jid':jabber_id, 'show':show, 'priority':priority, 'statuses':statuses, 'profile':profile});
from_jid=JID(jabber_id)
debug ("from_jid.short=%(from_jid)s whoami.short=%(whoami)s" % {'from_jid':from_jid.short, 'whoami':self.profiles[profile]['whoami'].short})
if from_jid.short==self.profiles[profile]['whoami'].short:
if not type:
self.setStatusOnline(True)
elif type=="unavailable":
self.setStatusOnline(False)
return
if show != 'unavailable':
name=""
groups = []
if self.rosterList.has_key(from_jid.short):
if self.rosterList[from_jid.short][0].has_key("name"):
name=self.rosterList[from_jid.short][0]["name"]
groups=self.rosterList[from_jid.short][1]
#FIXME: must be moved in a plugin
if from_jid.short in self.profiles[profile]['watched'] and not from_jid.short in self.profiles[profile]['onlineContact']:
self.showAlert(_("Watched jid [%s] is connected !") % from_jid.short)
self.profiles[profile]['onlineContact'].add(from_jid) #FIXME onlineContact is useless with CM, must be removed
self.CM.add(from_jid)
self.CM.update(from_jid, 'name', name)
self.CM.update(from_jid, 'show', show)
self.CM.update(from_jid, 'statuses', statuses)
self.CM.update(from_jid, 'groups', groups)
cache = self.bridge.getCardCache(from_jid)
if cache.has_key('nick'):
self.CM.update(from_jid, 'nick', cache['nick'])
if cache.has_key('avatar'):
self.CM.update(from_jid, 'avatar', self.bridge.getAvatarFile(cache['avatar']))
self.contactList.replace(from_jid, self.CM.getAttr(from_jid, 'groups'))
if show=="unavailable" and from_jid in self.profiles[profile]['onlineContact']:
self.profiles[profile]['onlineContact'].remove(from_jid)
self.CM.remove(from_jid)
if not self.CM.isConnected(from_jid):
self.contactList.disconnect(from_jid)
def roomJoined(self, room_id, room_service, room_nicks, user_nick, profile):
"""Called when a MUC room is joined"""
if not self.check_profile(profile):
return
debug (_("Room [%(room_name)s] joined by %(profile)s, users presents:%(users)s") % {'room_name':room_id+'@'+room_service, 'profile': profile, 'users':room_nicks})
room_jid=room_id+'@'+room_service
self.chat_wins[room_jid].setUserNick(user_nick)
self.chat_wins[room_jid].setType("group")
self.chat_wins[room_jid].id = room_jid
self.chat_wins[room_jid].setPresents(list(set([user_nick]+room_nicks)))
def roomUserJoined(self, room_id, room_service, user_nick, user_data, profile):
"""Called when an user joined a MUC room"""
if not self.check_profile(profile):
return
room_jid=room_id+'@'+room_service
if self.chat_wins.has_key(room_jid):
self.chat_wins[room_jid].replaceUser(user_nick)
debug (_("user [%(user_nick)s] joined room [%(room_jid)s]") % {'user_nick':user_nick, 'room_jid':room_jid})
def roomUserLeft(self, room_id, room_service, user_nick, user_data, profile):
"""Called when an user joined a MUC room"""
if not self.check_profile(profile):
return
room_jid=room_id+'@'+room_service
if self.chat_wins.has_key(room_jid):
self.chat_wins[room_jid].removeUser(user_nick)
debug (_("user [%(user_nick)s] left room [%(room_jid)s]") % {'user_nick':user_nick, 'room_jid':room_jid})
def roomNewSubject(self, room_id, room_service, subject, profile):
"""Called when subject of MUC room change"""
if not self.check_profile(profile):
return
room_jid=room_id+'@'+room_service
if self.chat_wins.has_key(room_jid):
self.chat_wins[room_jid].setSubject(subject)
debug (_("new subject for room [%(room_jid)s]: %(subject)s") % {'room_jid':room_jid, "subject":subject})
def tarotGameStarted(self, room_jid, referee, players, profile):
if not self.check_profile(profile):
return
debug (_("Tarot Game Started \o/"))
if self.chat_wins.has_key(room_jid):
self.chat_wins[room_jid].startGame("Tarot", referee, players)
debug (_("new Tarot game started by [%(referee)s] in room [%(room_jid)s] with %(players)s") % {'referee':referee, 'room_jid':room_jid, 'players':[str(player) for player in players]})
def tarotGameNew(self, room_jid, hand, profile):
if not self.check_profile(profile):
return
debug (_("New Tarot Game"))
if self.chat_wins.has_key(room_jid):
self.chat_wins[room_jid].getGame("Tarot").newGame(hand)
def tarotChooseContrat(self, room_jid, xml_data, profile):
"""Called when the player has to select his contrat"""
if not self.check_profile(profile):
return
debug (_("Tarot: need to select a contrat"))
if self.chat_wins.has_key(room_jid):
self.chat_wins[room_jid].getGame("Tarot").chooseContrat(xml_data)
def tarotShowCards(self, room_jid, game_stage, cards, data, profile):
if not self.check_profile(profile):
return
debug (_("Show cards"))
if self.chat_wins.has_key(room_jid):
self.chat_wins[room_jid].getGame("Tarot").showCards(game_stage, cards, data)
def tarotMyTurn(self, room_jid, profile):
if not self.check_profile(profile):
return
debug (_("My turn to play"))
if self.chat_wins.has_key(room_jid):
self.chat_wins[room_jid].getGame("Tarot").myTurn()
def tarotScore(self, room_jid, xml_data, winners, loosers, profile):
"""Called when the game is finished and the score are updated"""
if not self.check_profile(profile):
return
debug (_("Tarot: score received"))
if self.chat_wins.has_key(room_jid):
self.chat_wins[room_jid].getGame("Tarot").showScores(xml_data, winners, loosers)
def tarotCardsPlayed(self, room_jid, player, cards, profile):
if not self.check_profile(profile):
return
debug (_("Card(s) played (%(player)s): %(cards)s") % {"player":player, "cards":cards})
if self.chat_wins.has_key(room_jid):
self.chat_wins[room_jid].getGame("Tarot").cardsPlayed(player, cards)
def tarotInvalidCards(self, room_jid, phase, played_cards, invalid_cards, profile):
if not self.check_profile(profile):
return
debug (_("Cards played are not valid: %s") % invalid_cards)
if self.chat_wins.has_key(room_jid):
self.chat_wins[room_jid].getGame("Tarot").invalidCards(phase, played_cards, invalid_cards)
def _subscribe_cb(self, answer, data):
entity, profile = data
if answer:
self.bridge.subscription("subscribed", entity.short, profile_key = profile)
else:
self.bridge.subscription("unsubscribed", entity.short, profile_key = profile)
def subscribe(self, type, raw_jid, profile):
"""Called when a subsciption management signal is received"""
if not self.check_profile(profile):
return
entity = JID(raw_jid)
if type=="subscribed":
# this is a subscription confirmation, we just have to inform user
self.showDialog(_("The contact %s has accepted your subscription") % entity.short, _('Subscription confirmation'))
elif type=="unsubscribed":
# this is a subscription refusal, we just have to inform user
self.showDialog(_("The contact %s has refused your subscription") % entity.short, _('Subscription refusal'), 'error')
elif type=="subscribe":
# this is a subscriptionn request, we have to ask for user confirmation
answer = self.showDialog(_("The contact %s wants to subscribe to your presence.\nDo you accept ?") % entity.short, _('Subscription confirmation'), 'yes/no', answer_cb = self._subscribe_cb, answer_data=(entity, profile))
def showDialog(self, message, title, type="info", answer_cb = None):
raise NotImplementedError
def showAlert(self, message):
pass #FIXME
def paramUpdate(self, name, value, namespace, profile):
if not self.check_profile(profile):
return
debug(_("param update: [%(namespace)s] %(name)s = %(value)s") % {'namespace':namespace, 'name':name, 'value':value})
if (namespace,name) == ("Connection", "JabberID"):
debug (_("Changing JID to %s"), value)
self.profiles[profile]['whoami']=JID(value)
elif (namespace,name) == ("Misc", "Watched"):
self.profiles[profile]['watched']=value.split()
def contactDeleted(self, jid, profile):
if not self.check_profile(profile):
return
target = JID(jid)
self.CM.remove(target)
self.contactList.remove(self.CM.get_full(target))
try:
self.profiles[profile]['onlineContact'].remove(target.short)
except KeyError:
pass
def updatedValue(self, name, data):
if name == "card_nick":
target = JID(data['jid'])
if target in self.contactList:
self.CM.update(target, 'nick', data['nick'])
self.contactList.replace(target)
elif name == "card_avatar":
target = JID(data['jid'])
if target in self.contactList:
filename = self.bridge.getAvatarFile(data['avatar'])
self.CM.update(target, 'avatar', filename)
self.contactList.replace(target)
def askConfirmation(self, type, id, data):
raise NotImplementedError
def actionResult(self, type, id, data):
raise NotImplementedError
def onExit(self):
"""Must be called when the frontend is terminating"""
#TODO: mange multi-profile here
try:
autodisconnect = self.bridge.getParamA("autodisconnect","Connection", self.profile) == "true"
if autodisconnect and self.bridge.isConnected(self.profile):
#Does the user want autodisconnection ?
self.bridge.disconnect(self.profile)
except:
pass

View file

@ -0,0 +1,156 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
helper class for making a SAT frontend
Copyright (C) 2009, 2010 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 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 <http://www.gnu.org/licenses/>.
"""
from logging import debug, info, error
from tools.jid import JID
class QuickCardGame():
def __init__(self, parent, referee, players, player_nick):
self._autoplay = None #XXX: use 0 to activate fake play, None else
self.parent = parent
self.referee = referee
self.players = players
self.played = {}
for player in players:
self.played[player] = None
self.player_nick = player_nick
self.bottom_nick = unicode(self.player_nick)
idx = self.players.index(self.player_nick)
idx = (idx + 1) % len(self.players)
self.right_nick = unicode(self.players[idx])
idx = (idx + 1) % len(self.players)
self.top_nick = unicode(self.players[idx])
idx = (idx + 1) % len(self.players)
self.left_nick = unicode(self.players[idx])
self.bottom_nick = unicode(player_nick)
self.selected = [] #Card choosed by the player (e.g. during ecart)
self.hand_size = 13 #number of cards in a hand
self.hand = []
self.to_show = []
self.state = None
def getPlayerLocation(self, nick):
"""return player location (top,bottom,left or right)"""
for location in ['top','left','bottom','right']:
if getattr(self,'%s_nick' % location) == nick:
return location
assert(False)
def loadCards(self):
"""Load all the cards in memory
@param dir: directory where the PNG files are"""
self.cards={}
self.deck=[]
self.cards["atout"]={} #As Tarot is a french game, it's more handy & logical to keep french names
self.cards["pique"]={} #spade
self.cards["coeur"]={} #heart
self.cards["carreau"]={} #diamond
self.cards["trefle"]={} #club
def newGame(self, hand):
"""Start a new game, with given hand"""
assert (len(self.hand) == 0)
for suit, value in hand:
self.hand.append(self.cards[suit, value])
self.hand.sort()
self.state = "init"
def contratSelected(self, contrat):
"""Called when the contrat has been choosed
@param data: form result"""
self.parent.host.bridge.tarotGameContratChoosed(self.player_nick, self.referee, contrat or 'Passe', self.parent.host.profile)
def chooseContrat(self, xml_data):
"""Called when the player as to select his contrat
@param xml_data: SàT xml representation of the form"""
raise NotImplementedError
def showCards(self, game_stage, cards, data):
"""Display cards in the middle of the game (to show for e.g. chien ou poignée)"""
self.to_show = []
for suit, value in cards:
self.to_show.append(self.cards[suit, value])
if game_stage == "chien" and data['attaquant'] == self.player_nick:
self.state = "wait_for_ecart"
else:
self.state = "chien"
def myTurn(self):
"""Called when we have to play :)"""
if self.state == "chien":
self.to_show = []
self.state = "play"
self.__fakePlay()
def __fakePlay(self):
"""Convenience method for stupid autoplay
/!\ don't forgot to comment any interactive dialog for invalid card"""
if self._autoplay == None:
return
if self._autoplay >= len(self.hand):
self._autoplay = 0
card = self.hand[self._autoplay]
self.parent.host.bridge.tarotGamePlayCards(self.player_nick, self.referee, [(card.suit, card.value)], profile_key = self.parent.host.profile)
del self.hand[self._autoplay]
self.state = "wait"
self._autoplay+=1
def showScores(self, xml_data, winners, loosers):
"""Called at the end of a game
@param xml_data: SàT xml representation of the scores
@param winners: list of winners' nicks
@param loosers: list of loosers' nicks"""
raise NotImplementedError
def cardsPlayed(self, player, cards):
"""A card has been played by player"""
if self.to_show:
self.to_show = []
pl_cards = []
if self.played[player] != None: #FIXME
for pl in self.played:
self.played[pl] = None
for suit, value in cards:
pl_cards.append(self.cards[suit, value])
self.played[player] = pl_cards[0]
def invalidCards(self, phase, played_cards, invalid_cards):
"""Invalid cards have been played
@param phase: phase of the game
@param played_cards: all the cards played
@param invalid_cards: cards which are invalid"""
if phase == "play":
self.state = "play"
elif phase == "ecart":
self.state = "ecart"
else:
error ('INTERNAL ERROR: unmanaged game phase')
for suit, value in played_cards:
self.hand.append(self.cards[suit, value])
self.hand.sort()
self.__fakePlay()

View file

@ -0,0 +1,127 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
helper class for making a SAT frontend
Copyright (C) 2009, 2010 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 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 <http://www.gnu.org/licenses/>.
"""
from logging import debug, info, warning, error
from tools.jid import JID
class QuickChat():
def __init__(self, target, host, type='one2one'):
self.target = target
self.host = host
self.type = type
self.id = ""
self.nick = None
self.occupants = set()
def setType(self, type):
"""Set the type of the chat
@param type: can be 'one2one' for single conversation or 'group' for chat à la IRC
"""
self.type = type
def setPresents(self, nicks):
"""Set the users presents in the contact list for a group chat
@param nicks: list of nicknames
"""
debug (_("Adding users %s to room") % nicks)
if self.type != "group":
error (_("[INTERNAL] trying to set presents nicks for a non group chat window"))
raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
self.occupants.update(nicks)
def replaceUser(self, nick):
"""Add user if it is not in the group list"""
debug (_("Replacing user %s") % nick)
if self.type != "group":
error (_("[INTERNAL] trying to replace user for a non group chat window"))
raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
len_before = len(self.occupants)
self.occupants.add(nick)
if len_before != len(self.occupants):
self.printInfo("=> %s has joined the room" % nick)
def setUserNick(self, nick):
"""Set the nick of the user, usefull for e.g. change the color of the user"""
self.nick = nick
def removeUser(self, nick):
"""Remove a user from the group list"""
debug(_("Removing user %s") % nick)
if self.type != "group":
error (_("[INTERNAL] trying to remove user for a non group chat window"))
raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
self.occupants.remove(nick)
self.printInfo("<= %s has left the room" % nick)
def setSubject(self, subject):
"""Set title for a group chat"""
debug(_("Setting subject to %s") % subject)
if self.type != "group":
error (_("[INTERNAL] trying to set subject for a non group chat window"))
raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
def historyPrint(self, size=20, keep_last=False, profile='@NONE@'):
"""Print the initial history"""
debug (_("now we print history"))
history=self.host.bridge.getHistory(self.host.profiles[profile]['whoami'].short, self.target, 20)
stamps=history.keys()
stamps.sort()
for stamp in stamps:
self.printMessage(JID(history[stamp][0]), history[stamp][1], profile, stamp)
if keep_last: ##FIXME hack for sortilege
self.last_history = stamps[-1] if stamps else None
def _get_nick(self, jid):
"""Return nick of this jid when possible"""
return jid.resource if self.type == "group" else (self.host.CM.getAttr(jid,'nick') or self.host.CM.getAttr(jid,'name') or jid.node)
def printMessage(self, from_jid, msg, profile, timestamp):
"""Print message in chat window. Must be implemented by child class"""
jid=JID(from_jid)
nick = self._get_nick(jid)
mymess = (jid.resource == self.nick) if self.type == "group" else (jid.short == self.host.profiles[profile]['whoami'].short) #mymess = True if message comes from local user
if msg.startswith('/me '):
self.printInfo('* %s %s' % (nick, msg[4:]),type='me')
return
return jid, nick, mymess
def printInfo(self, msg, type='normal'):
"""Print general info
@param msg: message to print
@type: one of:
normal: general info like "toto has joined the room"
me: "/me" information like "/me clenches his fist" ==> "toto clenches his fist"
"""
raise NotImplementedError
def startGame(self, game_type, referee, players):
"""Configure the chat window to start a game"""
#No need to raise an error as game are not mandatory
warning(_('startGame is not implemented in this frontend'))
def getGame(self, game_type):
"""Return class managing the game type"""
#No need to raise an error as game are not mandatory
warning(_('getGame is not implemented in this frontend'))

View file

@ -0,0 +1,41 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
helper class for making a SAT frontend
Copyright (C) 2009, 2010 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 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 <http://www.gnu.org/licenses/>.
"""
from tools.jid import JID
class QuickChatList(dict):
"""This class is used to manage the list of chat windows.
It act as a dict, but create a chat window when the name is found for the first time."""
def __init__(self, host):
dict.__init__(self)
self.host = host
def __getitem__(self,to_jid):
target=JID(to_jid)
if not self.has_key(target.short):
#we have to create the chat win
self[target.short] = self.createChat(target)
return dict.__getitem__(self,target.short)
def createChat(self, target):
raise NotImplementedError

View file

@ -0,0 +1,57 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
helper class for making a SAT frontend
Copyright (C) 2009, 2010 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 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 <http://www.gnu.org/licenses/>.
"""
from logging import debug, info, error
from tools.jid import JID
class QuickContactList():
"""This class manage the visual representation of contacts"""
def __init__(self, CM):
"""
@param CM: instance of QuickContactManagement
"""
debug(_("Contact List init"))
self.CM = CM
def __contains__(self, jid):
raise NotImplementedError
def clear_contacts(self, jid):
"""Clear all the contact list"""
raise NotImplementedError
def replace(self, jid, groups=None):
"""add a contact to the list if doesn't exist, else update it"""
raise NotImplementedError
def disconnect(self, jid):
"""mark a contact disconnected"""
raise NotImplementedError
def remove(self, jid):
"""remove a contact from the list"""
raise NotImplementedError
def add(self, jid, param_groups=None):
"""add a contact to the list"""
raise NotImplementedError

View file

@ -0,0 +1,99 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
helper class for making a SAT frontend
Copyright (C) 2009, 2010 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 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 <http://www.gnu.org/licenses/>.
"""
from logging import debug, info, warning, error
from tools.jid import JID
import pdb
class QuickContactManagement():
"""This helper class manage the contacts and ease the use of nicknames and shortcuts"""
### FIXME: is SàT a better place for all this stuff ??? ###
def __init__(self):
self.__contactlist = {}
def clear(self):
"""Clear all the contact list"""
self.__contactlist.clear()
def add(self, entity):
"""Add contact to the list, update resources"""
if not self.__contactlist.has_key(entity.short):
self.__contactlist[entity.short] = {'resources':[]}
if entity.resource in self.__contactlist[entity.short]['resources']:
self.__contactlist[entity.short]['resources'].remove(entity.resource)
self.__contactlist[entity.short]['resources'].append(entity.resource)
def getContFromGroup(self, group):
"""Return all contacts which are in given group"""
result = []
for contact in self.__contactlist:
if self.__contactlist[contact].has_key('groups'):
if group in self.__contactlist[contact]['groups']:
result.append(JID(contact))
return result
def getAttr(self, entity, name):
"""Return a specific attribute of contact, or all attributes
@param entity: jid of the contact
@param name: name of the attribute
@return: asked attribute"""
if self.__contactlist.has_key(entity.short):
if name == 'status': #FIXME: for the moment, we only use the first status
if self.__contactlist[entity.short]['statuses']:
return self.__contactlist[entity.short]['statuses'].values()[0]
if self.__contactlist[entity.short].has_key(name):
return self.__contactlist[entity.short][name]
else:
debug(_('Trying to get attribute for an unknown contact'))
return None
def isConnected(self, entity):
"""Tell if the contact is online"""
return self.__contactlist.has_key(entity.short)
def remove(self, entity):
"""remove resource. If no more resource is online or is no resource is specified, contact is deleted"""
try:
if entity.resource:
self.__contactlist[entity.short]['resources'].remove(entity.resource)
if not entity.resource or not self.__contactlist[entity.short]['resources']:
#no more resource available: the contact seems really disconnected
del self.__contactlist[entity.short]
except KeyError:
error(_('INTERNAL ERROR: Key error'))
raise
def update(self, entity, key, value):
"""Update attribute of contact
@param entity: jid of the contact
@param key: name of the attribute
@param value: value of the attribute
"""
if self.__contactlist.has_key(entity.short):
self.__contactlist[entity.short][key] = value
else:
debug (_('Trying to update an unknown contact: %s'), entity.short)
def get_full(self, entity):
return entity.short+'/'+self.__contactlist[entity.short]['resources'][-1]

View file

@ -0,0 +1,57 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
helper class for making a SAT frontend
Copyright (C) 2009, 2010 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 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 <http://www.gnu.org/licenses/>.
"""
class QuickGatewaysManager():
def __init__(self, host, gateways, title=_("Gateways manager"), server=None):
self.WARNING_MSG = _(u"""Be careful ! Gateways allow you to use an external IM (legacy IM), so you can see your contact as jabber contacts.
But when you do this, all your messages go throught the external legacy IM server, it is a huge privacy issue (i.e.: all your messages throught the gateway can be monitored, recorded, analyzed by the external server, most of time a private company).""")
self.host = host
def getGatewayDesc(self, gat_type):
"""Return a human readable description of gateway type
@param gat_type: type of gateway, as given by SàT"""
desc = _('Unknown IM')
if gat_type == 'irc':
desc = "Internet Relay Chat"
elif gat_type == 'xmpp':
desc = "XMPP"
elif gat_type == 'qq':
desc = "Tencent QQ"
elif gat_type == 'simple':
desc = "SIP/SIMPLE"
elif gat_type == 'icq':
desc = "ICQ"
elif gat_type == 'yahoo':
desc = "Yahoo! Messenger"
elif gat_type == 'gadu-gadu':
desc = "Gadu-Gadu"
elif gat_type == 'aim':
desc = "AOL Instant Messenger"
elif gat_type == 'msn':
desc = 'Windows Live Messenger'
return desc