mirror of
https://github.com/Xevion/tcp-chat.git
synced 2025-12-07 20:08:38 -06:00
data transfer stats, remove status bar, change all client.send to custom in-between method
This commit is contained in:
@@ -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..."))
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>651</height>
|
||||
<height>643</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
<string>TCPChat</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<property name="sizePolicy">
|
||||
@@ -21,13 +21,6 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Connections</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="QTextEdit" name="messageBox">
|
||||
<property name="sizePolicy">
|
||||
@@ -44,6 +37,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Connections</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QTextBrowser" name="messageHistory">
|
||||
<property name="sizePolicy">
|
||||
@@ -77,6 +77,26 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="data_stats">
|
||||
<property name="text">
|
||||
<string>0.00KB Sent, 0.00KB Received</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
@@ -85,7 +105,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>21</height>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
@@ -98,7 +118,6 @@
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<action name="actionConnect_to">
|
||||
<property name="text">
|
||||
<string>Connect to...</string>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user