switch to type/request based JSON messages, improve GUI, add proper nickname dialog

This commit is contained in:
Xevion
2021-01-08 18:42:03 -06:00
parent 390595c0e2
commit b792d9cb9c
7 changed files with 326 additions and 233 deletions

View File

@@ -1,11 +1,14 @@
import json
import socket
from pprint import pprint
import traceback
from PyQt5.QtCore import QThread, pyqtSignal, Qt, QEvent
from PyQt5.QtWidgets import QMainWindow, QDialog, QDialogButtonBox, QVBoxLayout
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 config import config
from client.dialog import NicknameDialog
IP = '127.0.0.1'
PORT = 55555
@@ -15,6 +18,7 @@ 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):
@@ -25,73 +29,89 @@ class ReceiveWorker(QThread):
def run(self):
while True:
try:
length = int(self.client.recv(HEADER_LENGTH).decode('ascii'))
message = self.client.recv(length).decode('ascii')
if message == 'NICK':
header = f'{len(self.nickname):<{HEADER_LENGTH}}'
final = header + self.nickname
pprint(final)
self.client.send(final.encode('ascii'))
else:
self.messages.emit(message)
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 CustomDialog(QDialog):
def __init__(self, *args, **kwargs):
super(CustomDialog, self).__init__(*args, **kwargs)
self.setWindowTitle("HELLO!")
buttons = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
self.buttonBox = QDialogButtonBox(buttons)
self.buttonBox.accepted.connect(self.accept)
self.buttonBox.rejected.connect(self.reject)
self.layout = QVBoxLayout()
self.layout.addWidget(self.buttonBox)
self.setLayout(self.layout)
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))
# nicknameDialog = CustomDialog(self)
# if nicknameDialog.exec_():
# print('s')
self.nickname = 'Default'
self.textEdit.installEventFilter(self)
# 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.show()
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.textEdit:
if event.key() == Qt.Key_Return and self.textEdit.hasFocus():
self.sendMessage(self.textEdit.toPlainText())
self.textEdit.clear()
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.textBrowser.append(message)
self.messageHistory.append(message)
def sendMessage(self, message: str) -> None:
header = f'{len(message):<{HEADER_LENGTH}}'
final = header + message
pprint(final)
self.client.send(final.encode('ascii'))
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)