pypsyc/GUI/wx/devGui.py

697 lines
26 KiB
Python
Raw Blame History

# be warned this is the _dev_ version of the wx gui
# perhaps it will work, perhaps it's all borked up,
# this is a plazground shouldn't be used on a day to
# day basis
import GUI.Abstract.Gui as AbstractGui
import asyncore, sys, os
import ConfigParser
from string import split, rfind, strip
from pypsyc.PSYC.PSYCRoom import PSYCPackage
from pypsyc.PSYC.PSYCRoom import Friends as FriendsPackage
from pypsyc.PSYC import parsetext, get_user
from wxPython.wx import *
from wxPython.stc import *
from wxPython.lib.rcsizer import RowColSizer
from wxPython.lib.grids import wxFlexGridSizer
VERSION = 'pyPSYC-wx 0.0.1'
# for linux/posix this should work
CONFIG_FILE = os.getenv("HOME") + "/.pypsyc/wx-config"
# windows users should uncomment the next line and comment out the line above
# CONFIG_FILE = 'wx-config'
ID_ABOUT = 1002
ID_CONNECT = 1001
ID_DISCONNECT = 10011
ID_SAY = 3300
ID_NOTEBOOK = 3301
ID_STATUS = 9901
ID_MENU = 9902
ID_BUDDY_LIST = 9903
ID_BUDDY_LIST_DK = 990301
ID_EXIT = 1099
ID_CLOSECHATNOTEBOOK = 2099
ID_CLOSECHATNOTE = 2098
def opj(path):
"""Convert paths to the platform-specific separator"""
return apply(os.path.join, tuple(path.split('/')))
class Tab(wxPanel):
def __init__(self, context, notebook):
self.notebook = notebook
wxPanel.__init__(self, self.notebook, -1)
#panel = wxPanel(self.notebook, -1)
button = wxButton(self, ID_CLOSECHATNOTE, "close chat")
#button2 = wxButton(self, ID_STATUS, "NOOP")
self.nick_box = wxTextCtrl(self, -1, style=wxTE_READONLY)
box = wxBoxSizer(wxHORIZONTAL)
box.Add(self.nick_box, 1,wxEXPAND)
#box.Add(button2,0,wxEXPAND)
box.Add(button,0,wxEXPAND)
#scroller = wxScrolledWindow(self, -1, size=(-1,-1))
self.text_box = wxTextCtrl(self, -1, style=wxTE_MULTILINE|wxTE_RICH2|wxTE_READONLY|wxTE_AUTO_URL, size=wxDefaultSize)
self.entry_box = wxTextCtrl(self, ID_SAY, style=wxTE_PROCESS_ENTER|wxTE_PROCESS_TAB, size=wxDefaultSize)
sizer = RowColSizer()
sizer.Add(box, pos=(1,1), colspan=3,flag=wxEXPAND)
sizer.Add(self.text_box, pos=(2,1),flag=wxEXPAND, colspan=3)
#sizer.Add(scroller, pos=(2,1),flag=wxEXPAND, colspan=3)
sizer.Add(self.entry_box, pos=(3,1),flag=wxEXPAND, colspan=2)
sizer.AddGrowableCol(1)
sizer.AddGrowableRow(2)
self.SetSizer(sizer)
def append_text(self, text):
#text = text.decode('iso-8859-1')
if os.name == 'posix':
#self.text_box.SetEditable(True)
#ende = self.text_box.GetInsertionPoint()
#self.text_box.ShowPosition(ende+len(text))
self.text_box.AppendText(text)
#self.text_box.SetInsertionPointEnd()
#ende = self.text_box.GetInsertionPoint()
#self.text_box.ShowPosition(ende+len(text))
self.text_box.ScrollLines(2)
#self.text_box.SetEditable(False)
else:
self.text_box.WriteText(text)
self.text_box.ScrollLines(2)
def clear_entry(self):
self.entry_box.Clear()
self.entry_box.SetInsertionPoint(0)
def append_entry(self, text):
self.entry_box.AppendText(text)
def set_topic(self, text):
self.nick_box.Clear()
self.nick_box.AppendText(text)
def get_text(self):
return self.entry_box.GetValue()
class FriendList(wxFrame, PSYCPackage):
def __init__(self, parent=None, ID=0, title='pyPSYC', center=None, config=None, pos=wxDefaultPosition, size=wxSize(190, 400), style=wxDEFAULT_FRAME_STYLE):
# bei mir is friendlist, firendlist und maingui in einem
# zumindestens sollte es das sein ob es so klappt weiss ich noch nicht
self.global_config = config
self.config = ConfigParser.ConfigParser()
self.config.read(CONFIG_FILE)
if self.config:
pos = split(self.config.get('gui', 'wx_friend_pos'), ',')
size = split(self.config.get('gui', 'wx_friend_size'), ',')
wxFrame.__init__(self, parent, ID, title, wxPoint(int(pos[0]), int(pos[1])) , wxSize(int(size[0]), int(size[1])), style)
PSYCPackage.__init__(self)
self.currentBuddy = None
self.center = center
self.model = None
self.packagename = "Friends gui"
# we have to register by ourselves
# perhaps it's not the way to do it but it works
# no.. it's not working.. --lynX
# self.center.register(FriendsPackage(self))
# menubar, statusbar et al
self.CreateStatusBar()
self.SetStatusText("welcome to pyPSYC")
menu = wxMenu()
menu.Append(ID_CONNECT, "&Connect", "connect to the net")
menu.Append(ID_ABOUT, "&About", "tritratrullala")
menu.AppendSeparator()
menu.Append(ID_EXIT, "&Exit", "leave us")
menuBar = wxMenuBar()
menuBar.Append(menu, "&File");
self.SetMenuBar(menuBar)
##'buddy' list, perhaps ;]]
self.BuddyList = wxListCtrl(self, ID_BUDDY_LIST, style=wxLC_REPORT|wxLC_SINGLE_SEL|wxSUNKEN_BORDER)
self.BuddyList.InsertColumn(0, "ST")
self.BuddyList.InsertColumn(1, "Nick")# , wxLIST_FORMAT_RIGHT)
self.BuddyList.SetColumnWidth(0, 20)
##end buddy list
# define the buttons and so on at the bottom of the window
self.status = wxComboBox(self, ID_STATUS, "", choices=["", "This", "is a", "Place", "to put commands"], size=(150,-1), style=wxCB_DROPDOWN)
self.menu_button = wxButton( self, ID_MENU, 'pyPSYC')
self.exit_button = wxButton( self, ID_EXIT, 'exit')
self.con_menu = wxBoxSizer(wxHORIZONTAL)
self.con_menu.Add(self.menu_button, 1, wxALIGN_BOTTOM)
self.con_menu.Add(self.exit_button, 1, wxALIGN_BOTTOM)
sizer = wxFlexGridSizer(3, 0 , 0,0)
sizer.Add(self.BuddyList, 1, wxGROW)
sizer.Add(self.con_menu, 1,wxGROW)
sizer.Add(self.status, 1,wxGROW)
sizer.AddGrowableRow(0)
sizer.AddGrowableCol(0)
# do something so that the buttons don't vanish in a too small window
# this is h4x0r-style but does the job at the moment
sizer.SetItemMinSize(self.BuddyList, 30, 10)
sizer.SetMinSize(wxSize(200,280))
self.SetSizer(sizer)
self.SetAutoLayout(true)
# event handling
EVT_BUTTON( self, ID_EXIT, self.onExit )
EVT_BUTTON( self, ID_MENU, self.doConnect )
#EVT_BUTTON(self, ID_CONNECT, self.doConnect)
#EVT_BUTTON(self, ID_CLOSECHATNOTE, self.closeChat)
EVT_MENU( self, ID_EXIT, self.onExit)
EVT_MENU(self, ID_CONNECT, self.doConnect)
#EVT_LEFT_DCLICK(self.BuddyList, self.onFriend)
#EVT_LIST_ITEM_SELECTED(self, ID_BUDDY_LIST, self.OnBuddySelected)
# ect_activated muss weg sonst wird zweimal nen chat geoeffnet ;]]
##EVT_LIST_ITEM_ACTIVATED(self, ID_BUDDY_LIST, self.onFriend)
def received(self, source, mc, mmp, psyc):
# muss ueberall sein, warum weiss ich noch nicht so genau
# .._present .._absent versteh ich also is es da;]
if mc == "_notice_friend_present":
self.present(mmp.get_source())
elif mc == "_notice_friend_absent":
self.absent(mmp.get_source())
elif mc == "_notice_link" or mc == "_notice_unlink" or mc == "_status_linked":
self.set_status(mc)
def set_model(self, model):
self.model = model
def present(self, nick):
""" do what has to be done if a friend turns up """
# at the moment:
pass
#fuer das x muesste man wissen wie lang die buddy list bisher ist
#sprich vllt doch wieder nen dict dafuer bauen or so
#self.BuddyList.InsertStringItem(x ,'on')
#self.BuddyList.SetStringItem(x, 1, nick)
def absent(self, nick):
""" do what has to be done if a friend leaves us """
# at the moment also:
pass
def set_status(self, status):
""" we should tell the user if the status changes """
#print 'link status: ' + str(status)
def OnBuddySelected(self, event):
self.currentBuddy = event.m_itemIndex
event.Skip()
def doConnect(self, event, host = ''):
self.center.connect(host)
#print 'connecting...'
event.Skip()
def onExit(self, event):
""" do stuff we have to do before exiting """
#print 'exiting...'
pos = str(self.GetPositionTuple()[0]) + ', ' + str(self.GetPositionTuple()[1])
size = str(self.GetSizeTuple()[0]) + ', ' + str(self.GetSizeTuple()[1])
self.config.set('gui', 'wx_friend_pos', pos)
self.config.set('gui', 'wx_friend_size', size)
config_file = file(CONFIG_FILE, 'w')
self.config.write(config_file)
config_file.close()
self.model.set_mc("_request_execute")
self.model.set_target(self.model.center.ME())
self.model.set_text("/quit")
self.model.send()
self.Close(TRUE)
#sys.exit(0)
event.Skip()
class UeberGui(wxFrame):
def __init__(self, parent=NULL, ID=-1, title='uebergui teil', status_tab = 1, pos=wxDefaultPosition, size=wxDefaultSize, style=wxDEFAULT_FRAME_STYLE):
self.config = ConfigParser.ConfigParser()
self.config.read(CONFIG_FILE)
if self.config:
pos = split(self.config.get('gui', 'wx_room_pos'), ',')
size = split(self.config.get('gui', 'wx_room_size'), ',')
wxFrame.__init__(self, parent, ID, title, wxPoint(int(pos[0]), int(pos[1])) , wxSize(int(size[0]), int(size[1])), style)
#PSYCPackage.__init__(self)
self.notebook = wxNotebook(self, ID_NOTEBOOK)
self.tabs = [] # ein nummer zu context mapping
self.querys = []
self.buffers = {} # context : "chatter going on in this context"
self.tab_inst = {} # context : tab instanz
self.query_inst = {} # context : tab instanz
self.members = {} # dictionary a la { 'PSYC' : ['fippo', 'lethe', ...]}
if status_tab == 1:
self.addTab('status')
EVT_TEXT_ENTER(self, ID_SAY, self.say)
EVT_NOTEBOOK_PAGE_CHANGED(self, ID_NOTEBOOK, self.OnTabChange)
EVT_CLOSE(self, self.onClose )
EVT_TEXT(self, ID_SAY, self.EvtText)
def EvtText(self, event):
#print 'EvtText: %s' % event.GetString()
event.Skip()
def find_nick(self, wiesel):
positve_members= []
members = self.members[self.model.get_context()]
for member in members:
member = strip(member)
if member.startswith(wiesel):
positve_members.append(member)
return positve_members
def EvtChar(self, event):
#print 'EvtChar: ' + str(event.GetKeyCode())
if event.GetKeyCode() == 9:
# hier muessen wir nick raten und so weiter
wiesel = self.tab_inst[self.model.get_context()].get_text()
wiesel2 = wiesel
wiesel = split(wiesel, ' ')
marder = self.find_nick(wiesel[-1])
if len(marder) > 1:
print 't1'
self.tab_inst[self.model.get_context()].append_text(str(marder) + '\n')
elif len(marder) == 1:
print 't2'
nick = marder[0]
text = wiesel2
pos = - len(wiesel[-1])
text = text[:pos] + nick
self.tab_inst[self.model.get_context()].clear_entry()
self.tab_inst[self.model.get_context()].append_entry(text)
else:
print 't3'
else:
# hier passen wir einfach und reset'en den coutner
self.dep_count = 0
event.Skip()
def onClose(self,event):
print 'UeberGui.onCLose() worked'
def say(self, event):
""" wird gerufen wenn jmd enter dr<64>ckt """
text = event.GetString()
#text = text.encode('iso-8859-1')
if text != '' and text[0] == '/':
# we have a command
# if we know the command, we set the appropiate mc
# else we do _request_execute
if text.startswith("/join") and text.__len__() > 16:
# 16 == len(/join psyc://h/@r)
self.model.set_mc("_request_enter")
self.model.set_target(text.split(" ")[1])
self.model.send()
elif text.startswith("/part"):
# wie waers mit /part_logout, part_home, part_type, ...
self.model.set_mc("_request_leave")
self.model.set_target(self.model.get_context())
self.model.send()
elif text.startswith("/quit"):
self.model.set_mc("_request_execute")
self.model.set_target(self.model.center.ME())
self.model.set_text("/quit")
self.model.send()
elif text.startswith('/me') and text[3] == ' ':
self.model.set_target(self.model.get_context())
self.model.set_mc('_message_public')
self.model.set_psycvar('_action', text[4:])
self.model.set_text('')
self.model.send()
elif text.startswith('/names'):
self.model.set_target(self.model.get_context())
self.model.set_mc('_request_members')
self.model.set_text('')
self.model.send()
#elif text.startswith('/lnames'):
# context = self.model.get_context()
# self.tab_inst[context].append_text(self.members[context][0] + '\n')
elif text.startswith("/connect"):
foo = len(text.split(" "))
if foo == 2:
self.model.center.connect(text.split(" ")[1])
elif foo == 3:
self.model.center.connect(text.split(" ")[1], text.split(" ")[2])
else:
self.model.set_target(self.model.center.ME())
self.model.set_mc("_request_execute")
self.model.set_text(text)
self.model.send()
elif text != '' and text[0] == "#":
self.model.set_target(self.model.center.ME())
self.model.set_mc("_request_execute")
self.model.set_text("/" + text[1:])
self.model.send()
elif text != '' and text[0] == "!":
self.model.set_target(self.model.get_context())
self.model.set_mc("_request_execute")
self.model.set_text(text)
self.model.send()
elif text != '' and text[-1] == '?':
self.model.set_target(self.model.get_context())
self.model.set_mc("_message_public")
self.model.set_text(text)
self.model.send()
elif text != '':
#print "msg to", self.model.get_context()
self.model.set_target(self.model.get_context())
self.model.set_mc("_message_public")
self.model.set_text(text)
self.model.set_psycvar('_action', 'testet')
self.model.send()
self.tab_inst[self.model.context].clear_entry()
event.Skip()
def addTab(self, title):
panel = Tab(title, self.notebook)
if title != 'status':
short_title= title[rfind(title, '@'):]
self.model.set_context(title)
panel.append_text('heading over to ' + title + '\n')
self.model.set_target(self.model.get_context())
self.model.set_mc("_request_members")
self.model.set_text('')
self.model.send()
else:
short_title = title
self.notebook.AddPage(panel, short_title, select = 1)
self.tab_inst[title] = panel
self.SetTitle(title)
EVT_CHAR(panel.entry_box, self.EvtChar)
if title == 'status':
motd = 'Welcome to ' + VERSION + '\n for Q&A go to psyc://ve.symlynx.com/@PSYC \n or contact tim@trash-media.de for GUI problems \n for all the other problems go and talk to fippo!'
panel.append_text(motd)
self.tabs.append(title)
#self.buffers[title] = ''
def addQuery(self, title):
panel = Tab(title, self.notebook)
if title != 'status':
short_title= title[rfind(title, '~'):]
#self.model.set_context(title)
print dir(self.model)
panel.append_text('talking to ' + short_title + '\n')
#self.model.set_target(self.model.get_context())
#self.model.set_mc("_request_members")
#self.model.set_text('')
#self.model.send()
else:
short_title = title
self.notebook.AddPage(panel, short_title, select = 1)
self.query_inst[title] = panel
self.SetTitle(title)
if title == 'status':
motd = 'Welcome to ' + VERSION + '\n for Q&A go to psyc://ve.symlynx.com/@PSYC \n or contact tim@trash-media.de for GUI problems \n for all the other problems go and talk to fippo!'
panel.append_text(motd)
self.querys.append(title)
self.source = self.querys[-1]
#print (self.querys)
#print '<<<<<<<<<<<<<<'
#self.buffers[title] = ''
def OnTabChange(self, event):
old = event.GetOldSelection()
new = event.GetSelection()
self.SetTitle(self.tabs[new])
self.model.set_context(self.tabs[new])
#if self.buffers[self.model.context] != '':
# self.tab_inst[self.model.context].append_text(self.buffers[self.model.context])
# self.buffers[self.model.context] = ''
event.Skip()
def msg(self, text):
""" mehr text! """
class UserGui(UeberGui, AbstractGui.UserGui, PSYCPackage):
def __init__(self):
""" das hier is fuer querys """
PSYCPackage.__init__(self)
UeberGui.__init__(self, status_tab = 0)
self.model = None
self.source = ''
#pass
def say(self, event):
text = event.GetString()
#source self.tabs[]
source = self.source
self.model.set_target(source)
self.model.set_mc("_message_private")
self.model.psyc._assign("_nick", get_user(self.model.center.ME()))
#text = self.get_input(self.windows[source]["entryfield"])
self.model.set_text(text.strip())
#self.append_text(self.windows[source]["displayfield"], "Du sagst: " + text)
self.model.send()
self.query_inst[source].append_text('Du> ' + text + '\n')
self.query_inst[source].clear_entry()
event.Skip()
def received(self, source, mc, mmp, psyc):
context = 'status'
if mmp._query("_source") != None:
context = mmp._query("_source").lower()
else:
context = source.lower()
if mc == "_internal_message_private_window_popup":
# open a new tab
self.Show(True)
self.addQuery('test')
elif mc == "_message_echo_private":
self.Show(True)
text = ''
text += 'Du>'
if context not in self.querys:
self.addQuery(context)
text += ' ' + parsetext(mmp, psyc)
self.query_inst[context].append_text(text + '\n')
elif mc =='_message_private':
self.Show(True)
text = ''
text += 'Anderer_Nick>'
if context not in self.querys:
self.addQuery(context)
text += ' ' + parsetext(mmp, psyc)
self.query_inst[context].append_text(text + '\n')
def set_model(self, model):
self.model = model
def OnTabChange(self, event):
old = event.GetOldSelection()
new = event.GetSelection()
self.SetTitle(self.querys[new])
self.source = self.querys[new]
#self.model.set_context(self.tabs[new])
#if self.buffers[self.model.context] != '':
# self.tab_inst[self.model.context].append_text(self.buffers[self.model.context])
# self.buffers[self.model.context] = ''
event.Skip()
class RoomGui(UeberGui, AbstractGui.RoomGui, PSYCPackage):
def __init___(self):
""" das hier is fuer raeume """
PSYCPackage.__init__(self)
UeberGui.__init__(self,pos=pos, size=size)
self.model = None
EVT_CLOSE(self, self.onClose)
def onClose(self,event):
#print 'RoomGui.onClose() worked'
pos = str(self.GetPositionTuple()[0]) + ', ' + str(self.GetPositionTuple()[1])
size = str(self.GetSizeTuple()[0]) + ', ' + str(self.GetSizeTuple()[1])
self.config.set('gui', 'wx_room_pos', pos)
self.config.set('gui', 'wx_room_size', size)
config_file = file(CONFIG_FILE, 'w')
self.config.write(config_file)
config_file.close()
#self.Show(False)
event.Skip()
def set_model(self, model):
self.model = model
def received(self, source, mc, mmp, psyc):
context = 'status'
if mmp._query("_context") != None:
context = mmp._query("_context").lower()
else:
context = source.lower()
#if psyc._query('_nick_place') != None:
# context = 'psyc://ve.symlynx.com/@' + psyc._query('_nick_place').lower()
#context = source.lower()
if mc.startswith('_notice_place_leave'):
if context not in self.tabs:
self.addTab(context)
text = parsetext(mmp, psyc)
self.tab_inst[context].append_text(text + '\n')
if self.members.has_key(context):
nick = psyc._query('_nick')
self.members[context].remove(nick)
if mc.startswith('_notice_place_enter'):
self.Show(true)
if context not in self.tabs:
self.addTab(context)
text = parsetext(mmp, psyc)
self.tab_inst[context].append_text(text + '\n')
if self.members.has_key(context):
nick = psyc._query('_nick')
if nick not in self.members[context]:
self.members[context].append(nick)
elif mc == '_message_public_question':
text = ''
text += str(psyc._query("_nick"))
if context not in self.tabs:
self.addTab(context)
text += ' fragt ' + parsetext(mmp, psyc)
self.tab_inst[context].append_text(text + '\n')
elif mc.startswith('_status_place_topic') or mc.startswith('_notice_place_topic'):
topic = psyc._query('_topic')
context = source.lower()
if context not in self.tabs:
self.addTab(context)
self.tab_inst[context].set_topic(topic)
elif mc == '_message_public':
text = ''
text += str(psyc._query("_nick"))
if context not in self.tabs:
self.addTab(context)
if psyc._query("_action"):
ptext = parsetext(mmp, psyc)
if ptext == '':
text += " " + psyc._query("_action")
else:
text += " " + psyc._query("_action") + '> ' + ptext
else:
text += "> " + parsetext(mmp, psyc)
#text = text.encode('iso-8859-1')
self.tab_inst[context].append_text(text + '\n')
#print '!!' + context + ': ' + text
elif mc == '_status_place_members':
text = parsetext(mmp, psyc)
if context not in self.tabs:
self.addTab(context)
members = split(psyc._query('_members'), ', ')
self.members[context] = members
self.tab_inst[context].append_text(text + '\n')
else:
# everything we don't know goes into the status tab
# hopefully parsetext doesn't crash with' bogus' pakets
text = source.lower() + ' >>> '
text += parsetext(mmp, psyc)
self.tab_inst['status'].append_text(text + '\n')
class MainWindow(PSYCPackage):
# eigentlich brauch das kein schwein oder???
def __init__(self, argv):
""" was ich hiermit mache weiss ich noch net genau, eigentlich brauch
ich es net im moment lebt es f<>r den devel handler"""
self.center = None
PSYCPackage.__init__(self)
def title(self, text):
pass
def run(self):
pass
def quit(self):
self.center.quit()
sys.exit(0)
def connect(self):
pass
def write(self, text):
#print text
pass
class MySplashScreen(wxSplashScreen):
def __init__(self, argv, center, config):
self.center = center
self.argv = argv
self.config = config
bmp = wxImage(opj("GUI/wx/psych2o.jpg")).ConvertToBitmap()
wxSplashScreen.__init__(self, bmp,
wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT,
4000, None, -1,
style = wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP)
EVT_CLOSE(self, self.OnClose)
def OnClose(self, evt):
frame = FriendList(NULL, -1, "pyPSYC 0.0.0.0.0.1", center=self.center, config=self.config)
frame.Show()
evt.Skip()
class Application(wxApp):
def __init__(self, argv, center, config):
self.center = center
self.argv = argv
self.config = config
wxApp.__init__(self,0)
#print 'tt'
def OnInit(self):
#self.frame = FriendList(NULL, -1, "pyPSYC 0.0.0.0.0.1", center=self.center, config=self.config)
#self.frame.Show(true)
#sys.stdout = self.frame
wxInitAllImageHandlers()
splash = MySplashScreen(self.argv, self.center, self.config)
self.SetTopWindow(splash)
splash.Show()
return True
##
## self.timer = wxPyTimer(self.socket_check)
## self.timer.Start(100) # alle 100 ms
## #print 'ttt'
##
## def socket_check(self):
## asyncore.poll(timeout=0.0)
##
def run(self):
# blah mainloop
#print 'tttt'
from twisted.internet import wxsupport, reactor
wxsupport.install(self)
print "running reactor..."
reactor.run()