#!/usr/bin/env python
#-*- encoding: utf-8 -*-
import os
import wx
import socket
import threading
import thread
import time
CHAT_PORT = 9999
USER_LIST_SERVER_PORT = 9998
HEARTBEAT_SERVER = "202.115.5.155"
#get hostname and host ip address
host_name = socket.gethostname()
host_ip =socket.gethostbyname(host_name)
#print local information
print "host ip address: ", host_ip
#dict user_list used to store user information
user_list = [host_ip]
class MainWindow(wx.Frame):
"""
a basic frame construction
"""
def __init__(self, parent, id, title):
"""
various components and action listeners of a window
"""
wx.Frame.__init__(self, parent, id, title, size = (800, 600))
self.SetBackgroundColour(wx.Color(255, 255, 255))
self.target_ip = None # the guy you need to talk to
self.msgList = []
self.userList = []
self.statusBar = self.CreateStatusBar()
self.StatusBar.SetStatusText("Local area network chatting room")
#listbox list all the local user
self.userListBox = wx.ListBox(self, -1,\
choices = user_list, style = wx.LB_DEFAULT)
# show message received (read only)
self.msgTextCtrl = wx.TextCtrl(self, -1,\
style = wx.TE_MULTILINE | wx.TE_READONLY)
# edit message to send
self.editTextCtrl = wx.TextCtrl(self, -1,\
style = wx.TE_MULTILINE | wx.TE_PROCESS_ENTER)
self.msgButton = wx.Button(self, -1, "No Message Received")
self.sendButton = wx.Button(self, -1, "Send")
self.closeButton = wx.Button(self, -1, "Close")
self.refreshButton = wx.Button(self, -1, "Refresh")
self.hintLabel = wx.StaticText(self,-1,"Above: receive\nBelow: send")
#right_upper_area sizer
right_upper_area = wx.BoxSizer(wx.HORIZONTAL)
right_upper_area.Add(self.hintLabel, proportion = 0, flag = wx.RIGHT)
#right_bottom_area sizer
right_bottom_area = wx.BoxSizer(wx.HORIZONTAL)
right_bottom_area.Add(self.refreshButton, proportion = 0, flag = wx.EXPAND | wx.RIGHT | wx.BOTTOM)
right_bottom_area.Add(self.sendButton, proportion = 0, flag = wx.RIGHT | wx.BOTTOM)
right_bottom_area.Add(self.closeButton, proportion = 0, flag = wx.RIGHT | wx.BOTTOM)
#right area of window ,from top to bottom
right_area = wx.BoxSizer(wx.VERTICAL)
right_area.Add(self.msgTextCtrl, 1, wx.EXPAND)
right_area.Add(right_upper_area, 0, wx.EXPAND)
right_area.Add(self.editTextCtrl, 1, wx.EXPAND)
right_area.Add(right_bottom_area, 0, wx.EXPAND)
#left area of window ,from top to bottom
left_area = wx.BoxSizer(wx.VERTICAL)
left_area.Add(self.userListBox, 1, wx.EXPAND)
left_area.Add(self.msgButton, 0, wx.EXPAND)
# sizer for all
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(left_area, 1, wx.EXPAND)
sizer.Add(right_area, 2, wx.EXPAND)
#add layout
self.SetSizer(sizer)
self.SetAutoLayout(1)
#sizer.Fit(self)
#bind
self.Bind(wx.EVT_LISTBOX, self.on_user_list_box, self.userListBox) # click
self.Bind(wx.EVT_LISTBOX_DCLICK, self.d_user_list_box, self.userListBox) # double click
#button action
self.Bind(wx.EVT_BUTTON, self.show_msg_received, self.msgButton)
self.Bind(wx.EVT_BUTTON, self.on_refresh, self.refreshButton)
self.Bind(wx.EVT_BUTTON, self.on_send, self.sendButton)
self.Bind(wx.EVT_BUTTON, self.on_close, self.closeButton)
#text changed and save chatting records
self.Bind(wx.EVT_TEXT, self.save_record, self.msgTextCtrl)
#press enter and send the message
self.Bind(wx.EVT_TEXT_ENTER, self.on_send, self.editTextCtrl)
self.Show()
#received message
def show_msg_received(self, event):
"""
act on msgButton to show received message onto msgTextCtrl
act once on one message
if no received message left, change the label of Button msgButton
"""
if len(self.msgList):
print "This is message received: ", self.msgList[0]
if os.name == 'nt':
self.msgList[0] = self.msgList[0].decode('gbk')
elif os.name == 'posix':
self.msgList[0] = self.msgList[0].decode('gb2312')
else:
# if OS is unknown ,do nothing about 'decode'
print "unknown OS"
pass
self.msgTextCtrl.AppendText(self.msgList[0])
del self.msgList[0]
if len(self.userList):
# print the first user and corresponding id on user list
user_str = str(self.userList[0])
print user_str
id = self.userListBox.FindString(user_str)
print id
self.userListBox.Select(id)
del self.userList[0]
if not len(self.userList):
self.msgButton.SetLabel("No Message Received")
def save_record(self, event):
#write the chatting records to the local file
#---wait to be implemented
print "save record button clicked"
pass
def on_user_list_box(self, event):
user = event.GetString()
self.StatusBar.SetStatusText("Double click chat to %s" % user)
#double click user name and chat to him/her
def d_user_list_box(self, event):
user = event.GetString()
self.target_ip = user
self.Title = "Chat with %s" % user
self.msgTextCtrl.SetValue("")
self.editTextCtrl.SetValue("")
#refresh user list
def on_refresh(self, event):
self.userListBox.Clear()
for item in user_list:
self.userListBox.Insert(item,0)
pass
#send message
def on_send(self, event):
# the content you'd like to send
data = self.editTextCtrl.GetValue()
if self.target_ip:
if data:
#
self.send_information = data
self.target_address = (self.target_ip, CHAT_PORT)
# send data with time
now = time.localtime()
hour, min, sec = (now.tm_hour, now.tm_min, now.tm_sec)
if hour < 10:
hour = "0" + str(hour)
if min < 10:
min = "0" + str(min)
if sec < 10:
sec = "0" + str(sec)
ltime = "%s:%s:%s" % (hour, min, sec)
msgdata = socket.gethostname() + " " + ltime + "\n\t" + data + "\n"
#存储信息之后,将编辑框清空
self.editTextCtrl.SetValue("")
#先在本地机器上显示信息
self.msgTextCtrl.AppendText(msgdata)
self.send_message(self.send_information, self.target_address)
else:
d = wx.MessageDialog(self, "不能发送空信息", style = wx.OK)
d.ShowModal()
d.Destroy()
else:
d = wx.MessageDialog(self, "请先双击左侧一个用户选择为会话对象", style = wx.OK)
d.ShowModal()
d.Destroy()
#receive message
def receive_message(self, user, data):
now = time.localtime()
hour, min, sec = (now.tm_hour, now.tm_min, now.tm_sec)
if hour < 10:
hour = "0" + str(hour)
if min < 10:
min = "0" + str(min)
if sec < 10:
sec = "0" + str(sec)
l_time = "%s:%s:%s" % (hour, min, sec)
message_data = user + " " + l_time + "\n\t" + data + "\n"
self.msgList.append(message_data)
self.userList.append(user)
#close window
def on_close(self, event):
heartbeat_sender_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
heartbeat_sender_socket.sendto("LEAVE",(HEARTBEAT_SERVER,USER_LIST_SERVER_PORT))
heartbeat_sender_socket.close()