Files
tcp-chat/client/gui.py

118 lines
3.9 KiB
Python

import json
import socket
import traceback
from PyQt5.QtCore import QThread, pyqtSignal, Qt, QEvent, QTimer
from PyQt5.QtWidgets import QMainWindow
import constants
import helpers
from client.MainWindow import Ui_MainWindow
from client.dialog import NicknameDialog
IP = '127.0.0.1'
PORT = 55555
HEADER_LENGTH = 10
class ReceiveWorker(QThread):
messages = pyqtSignal(str)
client_list = pyqtSignal(list)
error = pyqtSignal()
def __init__(self, client: socket.socket, nickname: str, parent=None):
QThread.__init__(self, parent)
self.client = client
self.nickname = nickname
def run(self):
while True:
try:
length = int(self.client.recv(HEADER_LENGTH).decode('utf-8'))
raw = self.client.recv(length).decode('utf-8')
if len(raw) == 0:
continue
message = json.loads(raw)
if message['type'] == constants.Types.REQUEST:
if message['request'] == constants.Requests.REQUEST_NICK:
self.client.send(helpers.prepare_json(
{
'type': constants.Types.NICKNAME,
'nickname': self.nickname
}
))
elif message['type'] == constants.Types.MESSAGE:
self.messages.emit(message['content'])
elif message['type'] == constants.Types.USER_LIST:
self.client_list.emit(message['users'])
except:
traceback.print_exc()
self.error.emit()
self.client.close()
break
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setupUi(self)
self.show()
# Get Nickname
nicknameDialog = NicknameDialog(self)
nicknameDialog.exec_()
self.nickname = nicknameDialog.lineEdit.text()
# Connect to server
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.client.connect((IP, PORT))
# Setup message receiving thread worker
self.receiveThread = ReceiveWorker(self.client, self.nickname)
self.receiveThread.messages.connect(self.addMessage)
self.receiveThread.client_list.connect(self.updateConnectionsList)
self.receiveThread.start()
self.connectionsListTimer = QTimer()
self.connectionsListTimer.timeout.connect(self.refreshConnectionsList)
self.connectionsListTimer.start(1000 * 30)
self.refreshConnectionsList()
self.messageBox.installEventFilter(self)
def eventFilter(self, obj, event):
if event.type() == QEvent.KeyPress and obj is self.messageBox:
if event.key() == Qt.Key_Return and self.messageBox.hasFocus():
self.sendMessage(self.messageBox.toPlainText())
self.messageBox.clear()
self.messageBox.setText('')
cursor = self.messageBox.textCursor()
cursor.setPosition(0)
self.messageBox.setTextCursor(cursor)
return super().eventFilter(obj, event)
def addMessage(self, message: str) -> None:
self.messageHistory.append(message)
def sendMessage(self, message: str) -> None:
self.client.send(helpers.prepare_json(
{
'type': constants.Types.MESSAGE,
'content': message
}
))
def refreshConnectionsList(self):
self.client.send(helpers.prepare_json(
{
'type': constants.Types.REQUEST,
'request': constants.Requests.REFRESH_CONNECTIONS_LIST
}
))
def updateConnectionsList(self, users):
self.connectionsList.clear()
self.connectionsList.addItems(users)