diff --git a/client.py b/client.py
deleted file mode 100644
index 03d39b7..0000000
--- a/client.py
+++ /dev/null
@@ -1,33 +0,0 @@
-import socket
-import threading
-
-nickname = input("Nickname: ")
-
-client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-client.connect(('127.0.0.1', 55555))
-
-def receive():
- while True:
- try:
- message = client.recv(1024).decode('ascii')
- if message == 'NICK':
- client.send(nickname.encode('ascii'))
- else:
- print(message)
- except:
- print("Error! Disconnecting.")
- client.close()
- break
-
-# Sending Messages To Server
-def write():
- while True:
- message = '{}: {}'.format(nickname, input(''))
- client.send(message.encode('ascii'))
-
-# Starting Threads For Listening And Writing
-receive_thread = threading.Thread(target=receive)
-receive_thread.start()
-
-write_thread = threading.Thread(target=write)
-write_thread.start()
diff --git a/client/MainWindow.py b/client/MainWindow.py
new file mode 100644
index 0000000..ea64ca6
--- /dev/null
+++ b/client/MainWindow.py
@@ -0,0 +1,82 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file '.\MainWindow.ui'
+#
+# Created by: PyQt5 UI code generator 5.15.2
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic5 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+
+class Ui_MainWindow(object):
+ def setupUi(self, MainWindow):
+ MainWindow.setObjectName("MainWindow")
+ MainWindow.resize(800, 609)
+ self.centralwidget = QtWidgets.QWidget(MainWindow)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth())
+ self.centralwidget.setSizePolicy(sizePolicy)
+ self.centralwidget.setObjectName("centralwidget")
+ self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
+ self.gridLayout.setObjectName("gridLayout")
+ self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+ self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.textBrowser.sizePolicy().hasHeightForWidth())
+ self.textBrowser.setSizePolicy(sizePolicy)
+ self.textBrowser.setMaximumSize(QtCore.QSize(16777215, 16777215))
+ self.textBrowser.setObjectName("textBrowser")
+ self.horizontalLayout_2.addWidget(self.textBrowser)
+ self.gridLayout.addLayout(self.horizontalLayout_2, 0, 0, 1, 1)
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.textEdit.sizePolicy().hasHeightForWidth())
+ self.textEdit.setSizePolicy(sizePolicy)
+ self.textEdit.setMaximumSize(QtCore.QSize(16777215, 70))
+ self.textEdit.setObjectName("textEdit")
+ self.horizontalLayout.addWidget(self.textEdit)
+ self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1)
+ MainWindow.setCentralWidget(self.centralwidget)
+ self.menubar = QtWidgets.QMenuBar(MainWindow)
+ self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
+ 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)
+ self.actionSave_chat_to.setObjectName("actionSave_chat_to")
+ self.actionQuit = QtWidgets.QAction(MainWindow)
+ self.actionQuit.setObjectName("actionQuit")
+ self.menuFile.addAction(self.actionConnect_to)
+ self.menuFile.addAction(self.actionSave_chat_to)
+ self.menuFile.addAction(self.actionQuit)
+ self.menubar.addAction(self.menuFile.menuAction())
+
+ self.retranslateUi(MainWindow)
+ QtCore.QMetaObject.connectSlotsByName(MainWindow)
+
+ def retranslateUi(self, MainWindow):
+ _translate = QtCore.QCoreApplication.translate
+ MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
+ self.menuFile.setTitle(_translate("MainWindow", "File"))
+ self.actionConnect_to.setText(_translate("MainWindow", "Connect to..."))
+ self.actionSave_chat_to.setText(_translate("MainWindow", "Export chat..."))
+ self.actionQuit.setText(_translate("MainWindow", "Quit"))
diff --git a/client/MainWindow.ui b/client/MainWindow.ui
new file mode 100644
index 0000000..dcd03b8
--- /dev/null
+++ b/client/MainWindow.ui
@@ -0,0 +1,107 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 800
+ 609
+
+
+
+ MainWindow
+
+
+
+
+ 0
+ 0
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+
+
+
+ -
+
+
+ QLayout::SetDefaultConstraint
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 70
+
+
+
+
+
+
+
+
+
+
+
+
+ Connect to...
+
+
+
+
+ Export chat...
+
+
+
+
+ Quit
+
+
+
+
+
+
diff --git a/client/__init__.py b/client/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/client/gui.py b/client/gui.py
new file mode 100644
index 0000000..9891961
--- /dev/null
+++ b/client/gui.py
@@ -0,0 +1,76 @@
+import socket
+
+from PyQt5.QtCore import QThread, pyqtSignal
+from PyQt5.QtWidgets import QMainWindow, QDialog, QDialogButtonBox, QVBoxLayout
+
+from config import config
+from client.MainWindow import Ui_MainWindow
+
+IP = '127.0.0.1'
+PORT = 55555
+
+HEADER_LENGTH = int(config.get(IP, 'HeaderLength'))
+
+class ReceiveWorker(QThread):
+ messages = pyqtSignal(str)
+ 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('ascii'))
+ message = self.client.recv(length)
+ if message == 'NICK':
+ self.client.send(self.nickname.encode('ascii'))
+ else:
+ self.messages.emit(message)
+ except:
+ 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.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.receiveThread = ReceiveWorker(self.client, self.nickname)
+ self.receiveThread.messages.connect(self.addMessage)
+ self.receiveThread.start()
+ self.show()
+
+ def addMessage(self, message: str):
+ self.textBrowser.append(message)
diff --git a/client/gui.ui b/client/gui.ui
new file mode 100644
index 0000000..d836ca3
--- /dev/null
+++ b/client/gui.ui
@@ -0,0 +1,120 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 800
+ 651
+
+
+
+ MainWindow
+
+
+
+
+ 0
+ 0
+
+
+
+ -
+
+
+ Connections
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 80
+
+
+
+
+ -
+
+
+
+ 0
+ 5
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 200
+ 16777215
+
+
+
+
+ -
+
+
+ Chat History
+
+
+
+
+
+
+
+
+
+ Connect to...
+
+
+
+
+ Export chat...
+
+
+
+
+ Quit
+
+
+
+
+
+
diff --git a/client/main.py b/client/main.py
new file mode 100644
index 0000000..508e010
--- /dev/null
+++ b/client/main.py
@@ -0,0 +1,40 @@
+from PyQt5.QtWidgets import QApplication
+from client.gui import MainWindow
+
+import socket
+import threading
+
+# nickname = input("Nickname: ")
+
+app = QApplication([])
+app.setApplicationName("TCPChat Client")
+m = MainWindow()
+
+# client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+# client.connect(('127.0.0.1', 55555))
+#
+# def receive():
+# while True:
+# try:
+# message = client.recv(1024).decode('ascii')
+# if message == 'NICK':
+# client.send(nickname.encode('ascii'))
+# else:
+# m.addMessage(message)
+# # print(message)
+# except:
+# print("Error! Disconnecting.")
+# client.close()
+# break
+#
+# Sending Messages To Server
+# def write():
+# while True:
+# message = '{}: {}'.format(nickname, input(''))
+# client.send(message.encode('ascii'))
+#
+# Starting Threads For Listening And Writing
+# receive_thread = threading.Thread(target=receive)
+# receive_thread.start()
+
+app.exec_()
diff --git a/config.ini b/config.ini
new file mode 100644
index 0000000..3ecc730
--- /dev/null
+++ b/config.ini
@@ -0,0 +1,2 @@
+[DEFAULT]
+HeaderLength = 10
diff --git a/config.py b/config.py
new file mode 100644
index 0000000..8e8fa13
--- /dev/null
+++ b/config.py
@@ -0,0 +1,5 @@
+from configparser import ConfigParser
+
+
+config = ConfigParser()
+config.read('config.ini')
diff --git a/launch.py b/launch.py
new file mode 100644
index 0000000..e69de29
diff --git a/out.py b/out.py
new file mode 100644
index 0000000..9fbbec8
--- /dev/null
+++ b/out.py
@@ -0,0 +1,82 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'client\gui.ui'
+#
+# Created by: PyQt5 UI code generator 5.15.2
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic5 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+
+class Ui_MainWindow(object):
+ def setupUi(self, MainWindow):
+ MainWindow.setObjectName("MainWindow")
+ MainWindow.resize(800, 609)
+ self.centralwidget = QtWidgets.QWidget(MainWindow)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth())
+ self.centralwidget.setSizePolicy(sizePolicy)
+ self.centralwidget.setObjectName("centralwidget")
+ self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
+ self.gridLayout.setObjectName("gridLayout")
+ self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+ self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.textBrowser.sizePolicy().hasHeightForWidth())
+ self.textBrowser.setSizePolicy(sizePolicy)
+ self.textBrowser.setMaximumSize(QtCore.QSize(16777215, 16777215))
+ self.textBrowser.setObjectName("textBrowser")
+ self.horizontalLayout_2.addWidget(self.textBrowser)
+ self.gridLayout.addLayout(self.horizontalLayout_2, 0, 0, 1, 1)
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.textEdit.sizePolicy().hasHeightForWidth())
+ self.textEdit.setSizePolicy(sizePolicy)
+ self.textEdit.setMaximumSize(QtCore.QSize(16777215, 70))
+ self.textEdit.setObjectName("textEdit")
+ self.horizontalLayout.addWidget(self.textEdit)
+ self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1)
+ MainWindow.setCentralWidget(self.centralwidget)
+ self.menubar = QtWidgets.QMenuBar(MainWindow)
+ self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
+ 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)
+ self.actionSave_chat_to.setObjectName("actionSave_chat_to")
+ self.actionQuit = QtWidgets.QAction(MainWindow)
+ self.actionQuit.setObjectName("actionQuit")
+ self.menuFile.addAction(self.actionConnect_to)
+ self.menuFile.addAction(self.actionSave_chat_to)
+ self.menuFile.addAction(self.actionQuit)
+ self.menubar.addAction(self.menuFile.menuAction())
+
+ self.retranslateUi(MainWindow)
+ QtCore.QMetaObject.connectSlotsByName(MainWindow)
+
+ def retranslateUi(self, MainWindow):
+ _translate = QtCore.QCoreApplication.translate
+ MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
+ self.menuFile.setTitle(_translate("MainWindow", "File"))
+ self.actionConnect_to.setText(_translate("MainWindow", "Connect to..."))
+ self.actionSave_chat_to.setText(_translate("MainWindow", "Export chat..."))
+ self.actionQuit.setText(_translate("MainWindow", "Quit"))
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..e407f05
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
+pyqt5-tools~=5.15
diff --git a/server.py b/server.py
deleted file mode 100644
index 43b1f89..0000000
--- a/server.py
+++ /dev/null
@@ -1,65 +0,0 @@
-import socket
-import threading
-
-# Connection Data
-host = '127.0.0.1'
-port = 55555
-
-# Starting Server
-server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-server.bind((host, port))
-server.listen()
-
-# Lists For Clients and Their Nicknames
-clients = []
-nicknames = []
-
-
-# Sending Messages To All Connected Clients
-def broadcast(message):
- for client in clients:
- client.send(message)
-
-
-# Handling Messages From Clients
-def handle(client):
- while True:
- try:
- # Broadcasting Messages
- message = client.recv(1024)
- broadcast(message)
- except:
- # Removing And Closing Clients
- index = clients.index(client)
- clients.remove(client)
- client.close()
- nickname = nicknames[index]
- broadcast('{} left!'.format(nickname).encode('ascii'))
- nicknames.remove(nickname)
- break
-
-
-# Receiving / Listening Function
-def receive():
- while True:
- # Accept Connection
- client, address = server.accept()
- print("Connected with {}".format(str(address)))
-
- # Request And Store Nickname
- client.send('NICK'.encode('ascii'))
- nickname = client.recv(1024).decode('ascii')
- nicknames.append(nickname)
- clients.append(client)
-
- # Print And Broadcast Nickname
- print("Nickname is {}".format(nickname))
- broadcast("{} joined!".format(nickname).encode('ascii'))
- client.send('Connected to server!'.encode('ascii'))
-
- # Start Handling Thread For Client
- thread = threading.Thread(target=handle, args=(client,))
- thread.start()
-
-
-receive()
diff --git a/server/gui.py b/server/gui.py
new file mode 100644
index 0000000..e69de29
diff --git a/server/main.py b/server/main.py
new file mode 100644
index 0000000..e69de29