From e862540e142e1caea4cb4184be887e820a087c4b Mon Sep 17 00:00:00 2001 From: Xevion Date: Fri, 22 Jan 2021 12:06:30 -0600 Subject: [PATCH] data transfer stats, remove status bar, change all client.send to custom in-between method --- client/MainWindow.py | 23 +++++++++++++---------- client/MainWindow.ui | 41 ++++++++++++++++++++++++++++++----------- client/gui.py | 31 +++++++++++++++++++++++-------- client/worker.py | 24 +++++++++++++++++------- 4 files changed, 83 insertions(+), 36 deletions(-) diff --git a/client/MainWindow.py b/client/MainWindow.py index aa7c091..724cb32 100644 --- a/client/MainWindow.py +++ b/client/MainWindow.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file '.\MainWindow.ui' +# Form implementation generated from reading ui file '.\client\MainWindow.ui' # # Created by: PyQt5 UI code generator 5.15.2 # @@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") - MainWindow.resize(800, 651) + MainWindow.resize(800, 643) self.centralwidget = QtWidgets.QWidget(MainWindow) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) @@ -24,9 +24,6 @@ class Ui_MainWindow(object): self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") - self.label = QtWidgets.QLabel(self.centralwidget) - self.label.setObjectName("label") - self.gridLayout.addWidget(self.label, 0, 2, 1, 1) self.messageBox = QtWidgets.QTextEdit(self.centralwidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) @@ -36,6 +33,9 @@ class Ui_MainWindow(object): self.messageBox.setMaximumSize(QtCore.QSize(16777215, 80)) self.messageBox.setObjectName("messageBox") self.gridLayout.addWidget(self.messageBox, 2, 1, 1, 2) + self.label = QtWidgets.QLabel(self.centralwidget) + self.label.setObjectName("label") + self.gridLayout.addWidget(self.label, 0, 2, 1, 1) self.messageHistory = QtWidgets.QTextBrowser(self.centralwidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) @@ -56,16 +56,18 @@ class Ui_MainWindow(object): self.label_2 = QtWidgets.QLabel(self.centralwidget) self.label_2.setObjectName("label_2") self.gridLayout.addWidget(self.label_2, 0, 1, 1, 1) + spacerItem = QtWidgets.QSpacerItem(100, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.gridLayout.addItem(spacerItem, 3, 1, 1, 1) + self.data_stats = QtWidgets.QLabel(self.centralwidget) + self.data_stats.setObjectName("data_stats") + self.gridLayout.addWidget(self.data_stats, 3, 2, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21)) + self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26)) self.menubar.setObjectName("menubar") self.menuFile = QtWidgets.QMenu(self.menubar) self.menuFile.setObjectName("menuFile") MainWindow.setMenuBar(self.menubar) - self.statusbar = QtWidgets.QStatusBar(MainWindow) - self.statusbar.setObjectName("statusbar") - MainWindow.setStatusBar(self.statusbar) self.actionConnect_to = QtWidgets.QAction(MainWindow) self.actionConnect_to.setObjectName("actionConnect_to") self.actionSave_chat_to = QtWidgets.QAction(MainWindow) @@ -82,9 +84,10 @@ class Ui_MainWindow(object): def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate - MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) + MainWindow.setWindowTitle(_translate("MainWindow", "TCPChat")) self.label.setText(_translate("MainWindow", "Connections")) self.label_2.setText(_translate("MainWindow", "Chat History")) + self.data_stats.setText(_translate("MainWindow", "0.00KB Sent, 0.00KB Received")) self.menuFile.setTitle(_translate("MainWindow", "File")) self.actionConnect_to.setText(_translate("MainWindow", "Connect to...")) self.actionSave_chat_to.setText(_translate("MainWindow", "Export chat...")) diff --git a/client/MainWindow.ui b/client/MainWindow.ui index d836ca3..4dc737f 100644 --- a/client/MainWindow.ui +++ b/client/MainWindow.ui @@ -7,11 +7,11 @@ 0 0 800 - 651 + 643 - MainWindow + TCPChat @@ -21,13 +21,6 @@ - - - - Connections - - - @@ -44,6 +37,13 @@ + + + + Connections + + + @@ -77,6 +77,26 @@ + + + + Qt::Horizontal + + + + 100 + 20 + + + + + + + + 0.00KB Sent, 0.00KB Received + + + @@ -85,7 +105,7 @@ 0 0 800 - 21 + 26 @@ -98,7 +118,6 @@ - Connect to... diff --git a/client/gui.py b/client/gui.py index f03dcc4..acd20af 100644 --- a/client/gui.py +++ b/client/gui.py @@ -45,15 +45,17 @@ class MainWindow(QMainWindow, Ui_MainWindow): # Setup message receiving thread worker self.receiveThread = ReceiveWorker(self.client, self.nickname) - self.receiveThread.messages.connect(self.addMessage) + self.receiveThread.messages.connect(self.add_message) self.receiveThread.client_list.connect(self.update_connections) self.receiveThread.logs.connect(self.log) + self.receiveThread.data_stats.connect(self.count_stats) + self.receiveThread.sent_nick.connect(self._ready) self.receiveThread.start() + # Setup self.connectionsListTimer = QTimer() self.connectionsListTimer.timeout.connect(self.refresh_connections) self.connectionsListTimer.start(1000 * 30) - self.receiveThread.sent_nick.connect(self._ready) self.messageBox.setPlaceholderText('Type your message here...') self.messageBox.installEventFilter(self) @@ -62,6 +64,15 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.added_messages = [] self.max_message_id = -1 + self.sent, self.received = 0, 0 + + def count_stats(self, sent: bool, change: int) -> None: + if sent: + self.sent += change + else: + self.received += change + self.data_stats.setText(f'{helpers.sizeof_fmt(self.sent)} Sent, {helpers.sizeof_fmt(self.received)} Received') + def log(self, log_data: dict) -> None: logger.log(level=log_data['level'], msg=log_data['message'], exc_info=log_data['error']) @@ -84,7 +95,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): def eventFilter(self, obj, event) -> bool: 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.send_message(self.messageBox.toPlainText()) self.messageBox.clear() self.messageBox.setText('') cursor = self.messageBox.textCursor() @@ -107,7 +118,11 @@ class MainWindow(QMainWindow, Ui_MainWindow): scrollbar.setValue(scrollbar.maximum() if atMaximum else lastPosition) - def addMessage(self, message: dict) -> None: + def send(self, data: bytes, **kwargs) -> None: + self.count_stats(True, len(data)) + self.client.send(data, **kwargs) + + def add_message(self, message: dict) -> None: message_id = message['id'] if message_id not in self.added_messages: message['compiled'] = helpers.formatted_message(message) @@ -124,10 +139,10 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.refresh_messages() - def sendMessage(self, message: str) -> None: + def send_message(self, message: str) -> None: message = message.strip() if len(message) > 0: - self.client.send(helpers.prepare_json( + self.send(helpers.prepare_json( { 'type': constants.Types.MESSAGE, 'content': message @@ -136,7 +151,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): def refresh_connections(self) -> None: logger.info('Requesting connections list') - self.client.send(helpers.prepare_json( + self.send(helpers.prepare_json( { 'type': constants.Types.REQUEST, 'request': constants.Requests.REFRESH_CONNECTIONS_LIST @@ -145,7 +160,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): def get_message_history(self) -> None: logger.info('Requesting message history') - self.client.send(helpers.prepare_json( + self.send(helpers.prepare_json( { 'type': constants.Types.REQUEST, 'request': constants.Requests.GET_MESSAGE_HISTORY diff --git a/client/worker.py b/client/worker.py index 90d5a20..fa206be 100644 --- a/client/worker.py +++ b/client/worker.py @@ -14,6 +14,7 @@ class ReceiveWorker(QThread): error = pyqtSignal() sent_nick = pyqtSignal() logs = pyqtSignal(dict) + data_stats = pyqtSignal(bool, int) # bool: True if sent stats change, False if received stats change def __init__(self, client: socket.socket, nickname: str, parent=None): QThread.__init__(self, parent) @@ -43,18 +44,27 @@ class ReceiveWorker(QThread): } ) + def send(self, data: bytes, **kwargs) -> None: + self.data_stats.emit(True, len(data)) + self.client.send(data, **kwargs) + def run(self): try: while self.__isRunning: try: - raw_length = self.client.recv(constants.HEADER_LENGTH).decode('utf-8') - if not raw_length: - continue - raw = self.client.recv(int(raw_length)).decode('utf-8') - if not raw: - continue + # Receive and parse the header + raw_header = self.client.recv(constants.HEADER_LENGTH) + raw_length = raw_header.decode('utf-8') + if not raw_length: continue + + # Now receive the amount of data the header specified + raw_data = self.client.recv(int(raw_length)) + raw = raw_data.decode('utf-8') + if not raw: continue message = json.loads(raw) + self.data_stats.emit(False, len(raw_header) + len(raw_data)) + if message['type'] == constants.Types.REQUEST: self.log(f'Data[{int(raw_length)}] received, {message["type"]}/{message["request"]}.', level=logging.DEBUG) @@ -63,7 +73,7 @@ class ReceiveWorker(QThread): if message['type'] == constants.Types.REQUEST: if message['request'] == constants.Requests.REQUEST_NICK: - self.client.send(helpers.prepare_json( + self.send(helpers.prepare_json( { 'type': constants.Types.NICKNAME, 'nickname': self.nickname