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 + + + + + + + + + + + + 0 + 0 + 800 + 21 + + + + + File + + + + + + + + + + + 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 + + + + + + + + + 0 + 0 + 800 + 21 + + + + + File + + + + + + + + + + + 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