Files reorganisation

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

View file

View file

@ -0,0 +1,254 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
wix: 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/>.
"""
import wx
import os.path, glob
import pdb
from logging import debug, info, error
from tools.jid import JID
from tools.games import TarotCard
from quick_frontend.quick_card_game import QuickCardGame
from xmlui import XMLUI
CARD_WIDTH = 74
CARD_HEIGHT = 136
MIN_WIDTH = 950 #Minimum size of the panel
MIN_HEIGHT = 500
class WxCard(TarotCard):
"""This class is used to represent a card, graphically and logically"""
def __init__(self, file):
"""@param file: path of the PNG file"""
self.bitmap = wx.Image(file).ConvertToBitmap()
root_name = os.path.splitext(os.path.basename(file))[0]
suit,value = root_name.split('_')
TarotCard.__init__(self, (suit, value))
print "Carte:",suit, value #, self.bout
def draw(self, dc, x, y):
"""Draw the card on the device context
@param dc: device context
@param x: abscissa
@param y: ordinate"""
dc.DrawBitmap(self.bitmap, x, y, True)
class CardPanel(QuickCardGame,wx.Panel):
"""This class is used to display the cards"""
def __init__(self, parent, referee, players, player_nick):
QuickCardGame.__init__(self, parent, referee, players, player_nick)
wx.Panel.__init__(self, parent)
self.SetMinSize(wx.Size(MIN_WIDTH, MIN_HEIGHT))
self.loadCards("images/cards/")
self.mouse_over_card = None #contain the card to highlight
self.visible_size = CARD_WIDTH/2 #number of pixels visible for cards
self.hand = []
self.to_show = []
self.state = None
self.SetBackgroundColour(wx.GREEN)
self.Bind(wx.EVT_SIZE, self.onResize)
self.Bind(wx.EVT_PAINT, self.onPaint)
self.Bind(wx.EVT_MOTION, self.onMouseMove)
self.Bind(wx.EVT_LEFT_UP, self.onMouseClick)
self.parent.host.bridge.tarotGameReady(player_nick, referee, profile_key = self.parent.host.profile)
def loadCards(self, dir):
"""Load all the cards in memory
@param dir: directory where the PNG files are"""
QuickCardGame.loadCards(self)
for file in glob.glob(dir+'/*_*.png'):
card = WxCard(file)
self.cards[card.suit, card.value]=card
self.deck.append(card)
def newGame(self, hand):
"""Start a new game, with given hand"""
QuickCardGame.newGame(self, hand)
self._recalc_ori()
self.Refresh()
def contratSelected(self, data):
"""Called when the contrat has been choosed
@param data: form result"""
debug (_("Contrat choosed"))
contrat = data[0][1]
QuickCardGame.contratSelected(self, contrat)
def chooseContrat(self, xml_data):
"""Called when the player as to select his contrat
@param xml_data: SàT xml representation of the form"""
misc = {'callback': self.contratSelected}
form = XMLUI(self.parent.host, xml_data, title = _('Please choose your contrat'), options = ['NO_CANCEL'], misc = misc)
def showScores(self, xml_data, winners, loosers):
"""Called when the player as to select hist contrat
@param xml_data: SàT xml representation of the form"""
form = XMLUI(self.parent.host, xml_data, title = _('You win \o/') if self.player_nick in winners else _('You loose :('), options = ['NO_CANCEL'])
def cardsPlayed(self, player, cards):
"""A card has been played by player"""
QuickCardGame.cardsPlayed(self, player, cards)
self.Refresh()
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"""
QuickCardGame.invalidCards(self, phase, played_cards, invalid_cards)
self._recalc_ori()
self.Refresh()
if self._autoplay==None: #No dialog if there is autoplay
wx.MessageDialog(self, _("Cards played are invalid !"), _("Error"), wx.OK | wx.ICON_ERROR).ShowModal()
def _is_on_hand(self, pos_x, pos_y):
"""Return True if the coordinate are on the hand cards"""
if pos_x > self.orig_x and pos_y > self.orig_y \
and pos_x < self.orig_x + (len(self.hand)+1) * self.visible_size \
and pos_y < self.end_y:
return True
return False
def onResize(self, event):
self._recalc_ori()
def _recalc_ori(self):
"""Recalculate origins of hand, must be call when hand size change"""
self.orig_x = (self.GetSizeTuple()[0]-(len(self.hand)+1)*self.visible_size)/2 #where we start to draw cards
self.orig_y = self.GetSizeTuple()[1] - CARD_HEIGHT - 20
self.end_y = self.orig_y + CARD_HEIGHT
def onPaint(self, event):
dc = wx.PaintDC(self)
#We print the names to know who play where TODO: print avatars when available
max_x, max_y = self.GetSize()
border = 10 #border between nick and end of panel
right_y = left_y = 200
right_width, right_height = dc.GetTextExtent(self.right_nick)
right_x = max_x - right_width - border
left_x = border
top_width, top_height = dc.GetTextExtent(self.top_nick)
top_x = (max_x - top_width) / 2
top_y = border
dc.DrawText(self.right_nick, right_x, right_y)
dc.DrawText(self.top_nick, top_x, top_y)
dc.DrawText(self.left_nick, left_x, left_y)
#We draw the played cards:
center_y = 200 #ordinate used as center point
left_x = (max_x - CARD_WIDTH)/2 - CARD_WIDTH - 5
right_x = (max_x/2) + (CARD_WIDTH/2) + 5
left_y = right_y = center_y - CARD_HEIGHT/2
top_x = bottom_x = (max_x - CARD_WIDTH)/2
top_y = center_y - CARD_HEIGHT - 5
bottom_y = center_y + 5
for side in ['left', 'top', 'right', 'bottom']:
card = self.played[getattr(self, side+'_nick')]
if card != None:
card.draw(dc,locals()[side+'_x'], locals()[side+'_y'])
x=self.orig_x
for card in self.hand:
if (self.state == "play" or self.state == "ecart") and card == self.mouse_over_card \
or self.state == "ecart" and card in self.selected:
y = self.orig_y - 30
else:
y = self.orig_y
card.draw(dc,x,y)
x+=self.visible_size
if self.to_show:
"""There are cards to display in the middle"""
size = len(self.to_show)*(CARD_WIDTH+10)-10
x = (max_x - size)/2
for card in self.to_show:
card.draw(dc, x, 150)
x+=CARD_WIDTH+10
def onMouseMove(self, event):
pos_x,pos_y = event.GetPosition()
if self._is_on_hand(pos_x, pos_y):
try:
self.mouse_over_card = self.hand[(pos_x-self.orig_x)/self.visible_size]
except IndexError:
self.mouse_over_card = self.hand[-1]
self.Refresh()
else:
self.mouse_over_card = None
self.Refresh()
def onMouseClick(self, event):
print "mouse click:",event.GetPosition()
pos_x,pos_y = event.GetPosition()
if self.state == "chien":
self.to_show = []
self.state = "wait"
return
elif self.state == "wait_for_ecart":
self.state = "ecart"
self.hand.extend(self.to_show)
self.hand.sort()
self.to_show = []
self._recalc_ori()
self.Refresh()
return
if self._is_on_hand(pos_x, pos_y):
idx = (pos_x-self.orig_x)/self.visible_size
if idx == len(self.hand):
idx-=1
if self.hand[idx] == self.mouse_over_card:
if self.state == "ecart":
if self.hand[idx] in self.selected:
self.selected.remove(self.hand[idx])
else:
self.selected.append(self.hand[idx])
if len(self.selected) == 6: #TODO: use variable here, as chien len can change with variants
dlg = wx.MessageDialog(self, _("Do you put these cards in chien ?"), _(u"Écart"), wx.YES_NO | wx.ICON_QUESTION)
answer = dlg.ShowModal()
if answer == wx.ID_YES:
ecart = []
for card in self.selected:
ecart.append((card.suit, card.value))
self.hand.remove(card)
del self.selected[:]
self.parent.host.bridge.tarotGamePlayCards(self.player_nick, self.referee, ecart, profile_key = self.parent.host.profile)
self.state = "wait"
self._recalc_ori()
self.Refresh()
if self.state == "play":
card = self.hand[idx]
self.parent.host.bridge.tarotGamePlayCards(self.player_nick, self.referee, [(card.suit, card.value)], profile_key = self.parent.host.profile)
del self.hand[idx]
self.state = "wait"
self._recalc_ori()
self.Refresh()

263
frontends/src/wix/chat.py Normal file
View file

@ -0,0 +1,263 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
wix: 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/>.
"""
import wx
import os.path
import time
import pdb
from logging import debug, info, error, warning
from tools.jid import JID
from quick_frontend.quick_chat import QuickChat
from contact_list import ContactList
from card_game import CardPanel
idSEND = 1
idTAROT = 2
class Chat(wx.Frame, QuickChat):
"""The chat Window for one to one conversations"""
def __init__(self, target, host, type='one2one'):
wx.Frame.__init__(self, None, title=target, pos=(0,0), size=(400,200))
QuickChat.__init__(self, target, host, type)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.sizer)
self.splitter = wx.SplitterWindow(self, -1)
self.sizer.Add(self.splitter, 1, flag = wx.EXPAND)
self.conv_panel = wx.Panel(self.splitter)
self.conv_panel.sizer = wx.BoxSizer(wx.VERTICAL)
self.subjectBox = wx.TextCtrl(self.conv_panel, -1, style = wx.TE_READONLY)
self.chatWindow = wx.TextCtrl(self.conv_panel, -1, style = wx.TE_MULTILINE | wx.TE_RICH | wx.TE_READONLY)
self.textBox = wx.TextCtrl(self.conv_panel, -1, style = wx.TE_PROCESS_ENTER)
self.conv_panel.sizer.Add(self.subjectBox, flag=wx.EXPAND)
self.conv_panel.sizer.Add(self.chatWindow, 1, flag=wx.EXPAND)
self.conv_panel.sizer.Add(self.textBox, 0, flag=wx.EXPAND)
self.conv_panel.SetSizer(self.conv_panel.sizer)
self.splitter.Initialize(self.conv_panel)
self.SetMenuBar(wx.MenuBar())
#events
self.Bind(wx.EVT_CLOSE, self.onClose, self)
self.Bind(wx.EVT_TEXT_ENTER, self.onEnterPressed, self.textBox)
#fonts
self.font={}
self.font["points"] = self.chatWindow.GetFont().GetPointSize()
self.font["family"] = self.chatWindow.GetFont().GetFamily()
#misc
self.day_change = time.strptime(time.strftime("%a %b %d 00:00:00 %Y")) #struct_time of day changing time
self.setType(self.type)
self.textBox.SetFocus()
self.Hide() #We hide because of the show toggle
def __createPresents(self):
"""Create a list of present people in a group chat"""
self.present_panel = wx.Panel(self.splitter)
self.present_panel.sizer = wx.BoxSizer(wx.VERTICAL)
self.present_panel.SetBackgroundColour(wx.BLUE)
self.present_panel.presents = ContactList(self.present_panel, self.host, type='nicks')
self.present_panel.presents.SetMinSize(wx.Size(80,20))
self.present_panel.sizer.Add(self.present_panel.presents, 1, wx.EXPAND)
self.present_panel.SetSizer(self.present_panel.sizer)
self.splitter.SplitVertically(self.present_panel, self.conv_panel, 80)
def setType(self, type):
QuickChat.setType(self, type)
if type is 'group' and not self.splitter.IsSplit():
self.__createPresents()
self.subjectBox.Show()
self.__eraseMenus()
self.__createMenus_group()
self.sizer.Layout()
elif type is 'one2one' and self.splitter.IsSplit():
self.splitter.Unsplit(self.present_panel)
del self.present_panel
self.GetMenuBar().Show()
self.subjectBox.Hide()
self.__eraseMenus()
self.__createMenus_O2O()
self.nick = None
else:
self.subjectBox.Hide()
self.__eraseMenus()
self.__createMenus_O2O()
self.historyPrint(profile=self.host.profile)
def startGame(self, game_type, referee, players):
"""Configure the chat window to start a game"""
if game_type=="Tarot":
debug (_("configure chat window for Tarot game"))
self.tarot_panel = CardPanel(self, referee, players, self.nick)
self.sizer.Prepend(self.tarot_panel, 0, flag=wx.EXPAND)
self.sizer.Layout()
self.Fit()
def getGame(self, game_type):
"""Return class managing the game type"""
#TODO: check that the game is launched, and manage errors
if game_type=="Tarot":
return self.tarot_panel
def setPresents(self, nicks):
"""Set the users presents in the contact list for a group chat
@param nicks: list of nicknames
"""
QuickChat.setPresents(self, nicks)
for nick in nicks:
self.present_panel.presents.replace(nick)
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"))
return
QuickChat.replaceUser(self, nick)
self.present_panel.presents.replace(nick)
def removeUser(self, nick):
"""Remove a user from the group list"""
QuickChat.removeUser(self, nick)
self.present_panel.presents.remove(nick)
def setSubject(self, subject):
"""Set title for a group chat"""
QuickChat.setSubject(self, subject)
self.subjectBox.SetValue(subject)
def __eraseMenus(self):
"""erase all menus"""
menuBar = self.GetMenuBar()
for i in range(menuBar.GetMenuCount()):
menuBar.Remove(i)
def __createMenus_O2O(self):
"""create menu bar for one 2 one chat"""
info("Creating menus")
self.__eraseMenus()
menuBar = self.GetMenuBar()
actionMenu = wx.Menu()
actionMenu.Append(idSEND, _("&SendFile CTRL-s"),_(" Send a file to contact"))
menuBar.Append(actionMenu,_("&Action"))
#events
wx.EVT_MENU(self, idSEND, self.onSendFile)
def __createMenus_group(self):
"""create menu bar for group chat"""
info("Creating menus")
self.__eraseMenus()
menuBar = self.GetMenuBar()
actionMenu = wx.Menu()
actionMenu.Append(idTAROT, _("Start &Tarot game CTRL-t"),_(" Start a Tarot card game")) #tmp
menuBar.Append(actionMenu,_("&Games"))
#events
wx.EVT_MENU(self, idTAROT, self.onStartTarot)
def __del__(self):
wx.Frame.__del__(self)
def onClose(self, event):
"""Close event: we only hide the frame."""
event.Veto()
self.Hide()
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,
event.GetString(),
type = "groupchat" if self.type=='group' else "chat",
profile_key=self.host.profile)
self.textBox.Clear()
def __blink(self):
"""Do wizzz and buzzz to show window to user or
at least inform him of something new"""
#TODO: use notification system
if not self.IsActive():
self.RequestUserAttention()
if not self.IsShown():
self.Show()
def printMessage(self, from_jid, msg, profile, timestamp=""):
"""Print the message with differents colors depending on where it comes from."""
try:
jid,nick,mymess = QuickChat.printMessage(self, from_jid, msg, profile, timestamp)
except TypeError:
return
print "printMessage, jid=",jid,"type=",self.type
_font_bold = wx.Font(self.font["points"], self.font["family"], wx.NORMAL, wx.BOLD)
_font_normal = wx.Font(self.font["points"], self.font["family"], wx.NORMAL, wx.NORMAL)
_font_italic = wx.Font(self.font["points"], self.font["family"], wx.ITALIC if mymess else wx.NORMAL, wx.NORMAL)
self.chatWindow.SetDefaultStyle(wx.TextAttr("GREY", font=_font_normal))
msg_time = time.localtime(timestamp or None)
time_format = "%c" if msg_time < self.day_change else "%H:%M" #if the message was sent before today, we print the full date
self.chatWindow.AppendText("[%s]" % time.strftime(time_format, msg_time ))
self.chatWindow.SetDefaultStyle(wx.TextAttr( "BLACK" if mymess else "BLUE", font=_font_bold))
self.chatWindow.AppendText("[%s] " % nick)
self.chatWindow.SetDefaultStyle(wx.TextAttr("BLACK", font=_font_italic))
self.chatWindow.AppendText("%s\n" % msg)
if not mymess:
self.__blink()
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"
"""
_font_bold = wx.Font(self.font["points"], self.font["family"], wx.NORMAL, wx.BOLD)
_font_normal = wx.Font(self.font["points"], self.font["family"], wx.NORMAL, wx.NORMAL)
self.chatWindow.SetDefaultStyle(wx.TextAttr("BLACK", font=_font_bold if type == 'normal' else _font_normal))
self.chatWindow.AppendText("%s\n" % msg)
if type=="me":
self.__blink()
### events ###
def onSendFile(self, e):
debug(_("Send File"))
filename = wx.FileSelector(_("Choose a file to send"), flags = wx.FD_FILE_MUST_EXIST)
if filename:
debug(_("filename: %s"),filename)
full_jid = self.host.CM.get_full(self.target)
id = self.host.bridge.sendFile(full_jid, filename)
self.host.waitProgress(id, _("File Transfer"), _("Copying %s") % os.path.basename(filename))
def onStartTarot(self, e):
debug (_("Starting Tarot game"))
warning (_("FIXME: temporary menu, must be changed"))
if len(self.occupants) != 4:
err_dlg = wx.MessageDialog(self, _("You need to be exactly 4 peoples in the room to start a Tarot game"), _("Can't start game"), style = wx.OK | wx.ICON_ERROR) #FIXME: gof: temporary only, need to choose the people with who the game has to be started
err_dlg.ShowModal()
else:
self.host.bridge.tarotGameCreate(self.id, list(self.occupants), self.host.profile)

View file

@ -0,0 +1,15 @@
import sys
import __builtin__
__builtin__.__dict__['APP_NAME'] = "Wix"
__builtin__.__dict__['LICENCE_PATH'] = "../../COPYING"
__builtin__.__dict__['IMAGE_DIR'] = sys.path[0]+'/images'
__builtin__.__dict__['msgOFFLINE'] = _("offline")
__builtin__.__dict__['msgONLINE'] = _("online")
__builtin__.__dict__['const_DEFAULT_GROUP'] = "Unclassed"
__builtin__.__dict__['const_STATUS'] = [("", _("Online"), None),
("chat", _("Free for chat"), "green"),
("away", _("AFK"), "brown"),
("dnd", _("DND"), "red"),
("xa", _("Away"), "red")]

View file

@ -0,0 +1,182 @@
import wx
from quick_frontend.quick_contact_list import QuickContactList
from logging import debug, info, error
from cgi import escape
from tools.jid import JID
class Group(unicode):
"""Class used to recognize groups"""
class Contact(unicode):
"""Class used to recognize groups"""
class ContactList(wx.SimpleHtmlListBox, QuickContactList):
"""Customized control to manage contacts."""
def __init__(self, parent, host, type="JID"):
"""init the contact list
@param parent: WxWidgets parent of the widget
@param host: wix main app class
@param type: type of contact list: "JID" for the usual big jid contact list
"CUSTOM" for a customized contact list (self.__presentItem must then be overrided)
"""
wx.SimpleHtmlListBox.__init__(self, parent, -1)
QuickContactList.__init__(self, host.CM)
self.host = host
self.type = type
self.__typeSwitch()
self.groups = {} #list contacts in each groups, key = group
self.Bind(wx.EVT_LISTBOX, self.onSelected)
self.Bind(wx.EVT_LISTBOX_DCLICK, self.onActivated)
def __contains__(self, jid):
return bool(self.__find_idx(jid))
def __typeSwitch(self):
if self.type == "JID":
self.__presentItem = self.__presentItemJID
elif type != "CUSTOM":
self.__presentItem = self.__presentItemDefault
def __find_idx(self, entity):
"""Find indexes of given contact (or groups) in contact list, manage jid
@return: list of indexes"""
result=[]
for i in range(self.GetCount()):
if (type(entity) == JID and type(self.GetClientData(i)) == JID and self.GetClientData(i).short == entity.short) or\
self.GetClientData(i) == entity:
result.append(i)
return result
def replace(self, contact, groups=None):
debug(_("update %s") % contact)
if not self.__find_idx(contact):
self.add(contact, groups)
else:
for i in self.__find_idx(contact):
self.SetString(i, self.__presentItem(contact))
def disconnect(self, contact):
self.remove(contact) #for now, we only show online contacts
def __eraseGroup(self, group):
"""Erase all contacts in group
@param group: group to erase
@return: True if something as been erased"""
erased = False
indexes = self.__find_idx(group)
for idx in indexes:
while idx<self.GetCount()-1 and type(self.GetClientData(idx+1)) != Group:
erased = True
self.Delete(idx+1)
return erased
def __presentGroup(self, group):
"""Make a nice presentation for the contact groups"""
html = u"""-- [%s] --""" % group
return html
def __presentItemDefault(self, contact):
"""Make a basic presentation of string contacts in the list."""
return contact
def __presentItemJID(self, jid):
"""Make a nice presentation of the contact in the list for JID contacts."""
name = self.CM.getAttr(jid,'name')
nick = self.CM.getAttr(jid,'nick')
show = filter(lambda x:x[0]==self.CM.getAttr(jid,'show'), const_STATUS)[0]
#show[0]==shortcut
#show[1]==human readable
#show[2]==color (or None)
show_html = "<font color='%s'>[%s]</font>" % (show[2], show[1]) if show[2] else ""
status = self.CM.getAttr(jid,'status') or ''
avatar = self.CM.getAttr(jid,'avatar') or IMAGE_DIR+'/empty_avatar.png'
html = """
<table border='0'>
<td>
<img height='64' width='64' src='%s' />
</td>
<td>
<b>%s</b> %s<br />
<i>%s</i>
</td>
</table>
""" % (avatar,
escape(nick or name or jid.node or jid.short),
show_html,
escape(status))
return html
def clear_contacts(self):
"""Clear all the contact list"""
self.Clear()
def add(self, contact, groups = None):
"""add a contact to the list"""
debug (_("adding %s"),contact)
if not groups:
idx = self.Insert(self.__presentItem(contact), 0, contact)
else:
for group in groups:
indexes = self.__find_idx(group)
gp_idx = 0
if not indexes: #this is a new group, we have to create it
gp_idx = self.Append(self.__presentGroup(group), Group(group))
else:
gp_idx = indexes[0]
self.Insert(self.__presentItem(contact), gp_idx+1, contact)
def remove(self, contact):
"""remove a contact from the list"""
debug (_("removing %s"), contact)
list_idx = self.__find_idx(contact)
list_idx.reverse() #as we make some deletions, we have to reverse the order
for i in list_idx:
self.Delete(i)
def onSelected(self, event):
"""Called when a contact is selected."""
data = self.getSelection()
if data == None: #we have a group
first_visible = self.GetVisibleBegin()
group = self.GetClientData(self.GetSelection())
erased = self.__eraseGroup(group)
if not erased: #the group was already erased, we can add again the contacts
contacts = self.CM.getContFromGroup(group)
contacts.sort()
id_insert = self.GetSelection()+1
for contact in contacts:
self.Insert(self.__presentItem(contact), id_insert, contact)
self.SetSelection(wx.NOT_FOUND)
self.ScrollToLine(first_visible)
event.Skip(False)
else:
event.Skip()
def onActivated(self, event):
"""Called when a contact is clicked or activated with keyboard."""
data = self.getSelection()
self.onActivatedCB(data)
event.Skip()
def getSelection(self):
"""Return the selected contact, or an empty string if there is not"""
if self.GetSelection() == wx.NOT_FOUND:
return None
data = self.GetClientData(self.GetSelection())
if type(data) == Group:
return None
return data
def registerActivatedCB(self, cb):
"""Register a callback with manage contact activation."""
self.onActivatedCB=cb

View file

@ -0,0 +1,169 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
wix: 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/>.
"""
import wx
import pdb
from xml.dom import minidom
from logging import debug, info, error
from tools.jid import JID
from quick_frontend.quick_gateways import QuickGatewaysManager
class GatewaysManager(wx.Frame,QuickGatewaysManager):
def __init__(self, host, gateways, title=_("Gateways manager"), server=None):
wx.Frame.__init__(self, None, title=title)
QuickGatewaysManager.__init__(self, host, gateways, server)
if server:
self.SetTitle(title+" (%s)" % server)
#Fonts
self.normal_font = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
self.bold_font = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD)
self.italic_font = wx.Font(8, wx.DEFAULT, wx.FONTSTYLE_ITALIC, wx.NORMAL)
self.button_font = wx.Font(6, wx.DEFAULT, wx.NORMAL, wx.BOLD)
self.modified = {} # dict of modified data (i.e. what we have to save)
self.ctl_list = {} # usefull to access ctrl, key = (name, category)
self.sizer = wx.BoxSizer(wx.VERTICAL)
warning = wx.TextCtrl(self, -1, value=self.WARNING_MSG, style = wx.TE_MULTILINE |
wx.TE_READONLY |
wx.TE_LEFT)
warning.SetFont(self.bold_font)
self.sizer.Add(warning, 0, wx.EXPAND)
warning.ShowPosition(0)
self.panel = wx.Panel(self)
self.panel.sizer = wx.FlexGridSizer(cols=5)
self.panel.SetSizer(self.panel.sizer)
self.panel.SetAutoLayout(True)
self.sizer.Add(self.panel, 1, flag=wx.EXPAND)
self.SetSizer(self.sizer)
self.SetAutoLayout(True)
#events
self.Bind(wx.EVT_CLOSE, self.onClose, self)
self.MakeModal()
self.panel.sizer.Add(wx.Window(self.panel, -1))
title_name = wx.StaticText(self.panel, -1, "Name")
title_name.SetFont(self.bold_font)
title_type = wx.StaticText(self.panel, -1, "Type")
title_type.SetFont(self.bold_font)
self.panel.sizer.Add(title_name)
self.panel.sizer.Add(title_type)
self.panel.sizer.Add(wx.Window(self.panel, -1))
self.panel.sizer.Add(wx.Window(self.panel, -1))
for gateway in gateways:
self.addGateway(gateway, gateways[gateway])
self.ext_server_panel = wx.Panel(self)
self.ext_server_panel.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.ext_server_panel.SetSizer(self.ext_server_panel.sizer)
self.ext_server_panel.SetAutoLayout(True)
self.sizer.Add(self.ext_server_panel, 0, flag=wx.EXPAND)
ext_server_label = wx.StaticText(self.ext_server_panel, -1, _("Use external XMPP server: "))
ext_server_label.SetFont(wx.ITALIC_FONT)
self.ext_server_text = wx.TextCtrl(self.ext_server_panel, -1)
ext_server_button = wx.Button(self.ext_server_panel, -1, _("GO !"))
self.ext_server_panel.Bind(wx.EVT_BUTTON, self.browseExternalServer, ext_server_button)
self.ext_server_panel.sizer.Add(ext_server_label)
self.ext_server_panel.sizer.Add(self.ext_server_text, 1, flag=wx.EXPAND)
self.ext_server_panel.sizer.Add(ext_server_button)
#self.panel.sizer.Fit(self)
self.sizer.Fit(self)
self.Show()
def browseExternalServer(self, event):
"""Open the gateway manager on given server"""
server = self.ext_server_text.GetValue()
debug(_("Opening gateways manager on [%s]") % server)
id = self.host.bridge.findGateways(server, self.host.profile)
self.host.current_action_ids.add(id)
self.host.current_action_ids_cb[id] = self.host.onGatewaysFound
self.MakeModal(False)
self.Destroy()
def addGateway(self, gateway, param):
#First The icon
isz = (16,16)
im_icon = wx.StaticBitmap(self.panel, -1, wx.ArtProvider.GetBitmap(wx.ART_GO_FORWARD, wx.ART_TOOLBAR, isz))
#Then the name
label=wx.StaticText(self.panel, -1, param['name'])
label.SetFont(self.normal_font)
#Then the transport type message
type_label_txt = self.getGatewayDesc(param['type'])
type_label = wx.StaticText(self.panel, -1, type_label_txt)
type_label.SetFont(self.italic_font)
#The buttons
def register_cb(event):
"""Called when register button is clicked"""
gateway_jid = event.GetEventObject().gateway_jid
id = self.host.bridge.in_band_register(gateway_jid, self.host.profile)
self.host.current_action_ids.add(id)
self.MakeModal(False)
self.Destroy()
def unregister_cb(event):
"""Called when unregister button is clicked"""
gateway_jid = event.GetEventObject().gateway_jid
id = self.host.bridge.gatewayRegister("CANCEL",gateway_jid, None, self.host.profile)
self.host.current_action_ids.add(id)
self.MakeModal(False)
self.Destroy()
reg_button = wx.Button(self.panel, -1, _("Register"), size=wx.Size(-1, 8))
reg_button.SetFont(self.button_font)
reg_button.gateway_jid = JID(gateway)
self.panel.Bind(wx.EVT_BUTTON, register_cb, reg_button)
unreg_button = wx.Button(self.panel, -1, _("Unregister"), size=wx.Size(-1, 8))
unreg_button.SetFont(self.button_font)
unreg_button.gateway_jid = JID(gateway)
self.panel.Bind(wx.EVT_BUTTON, unregister_cb, unreg_button)
self.panel.sizer.Add(im_icon)
self.panel.sizer.Add(label)
self.panel.sizer.Add(type_label)
self.panel.sizer.Add(reg_button, 1, wx.EXPAND)
self.panel.sizer.Add(unreg_button, 1, wx.EXPAND)
def onClose(self, event):
"""Close event"""
debug(_("close"))
self.MakeModal(False)
event.Skip()

View file

@ -0,0 +1 @@
Biggest size: 74X136

View file

@ -0,0 +1 @@
The work in this directory is licensed under the Creative Commons BY-SA License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/; or, (b) send a letter to Creative Commons, 171 2nd Street, Suite 300, San Francisco, California, 94105, USA.

View file

@ -0,0 +1,3 @@
The Tarot cards pictures come from the deck found on wikicommons (the script used to cut them is available at frontend/wix/images/split_card.sh), and available at http://upload.wikimedia.org/wikipedia/commons/8/8d/Tarotcards.jpg under Creative Commons BY-SA. The authors shown on the site are Piast and Svick. The splitted cards are, according to the license, available under the same conditions.
Notice that the Creative Common BY-SA apply only to this directory

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Some files were not shown because too many files have changed in this diff Show more