Aug-19-2019, 10:25 AM
(Jul-19-2019, 04:11 AM)micseydel Wrote: I'd be interested in helping if you can reproduce the problem with fewer lines of code (I'm thinking 10-20 tops) and only necessary imports.
Ahh, I'm really sorry, i forgot to check back after no one replied initially. Anyways I found the problem myself, i.e. human errors, while reviewing. I took the project a little further with some more features then abandoned it after i got bored and started new projects @.@
The final (at the time) code is as below for anyone interested.
from PyQt5 import QtWidgets import sys import socket import threading import ipaddress import time import pickle class MainWindow(QtWidgets.QWidget): def __init__(self): super(MainWindow, self).__init__() self.service = "" self.server = socket.socket() self.client = socket.socket() self.machineIP = socket.gethostbyname(socket.gethostname()) self.isconnected = "" self.connectedusers = [] self.unreadcount = 0 self.oldtime = time.time() self.chatwindow = QtWidgets.QListWidget() self.userwindow = QtWidgets.QListWidget() self.typingfield = QtWidgets.QLineEdit() self.typingfield.returnPressed.connect(self.sendpressed) self.sendbutton = QtWidgets.QPushButton("Send") self.sendbutton.clicked.connect(self.sendpressed) self.tray_icon = QtWidgets.QSystemTrayIcon(self) self.tray_icon.activated.connect(self.onTrayIconActivated) self.tray_icon.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_ComputerIcon)) show_action = QtWidgets.QAction("Show", self) quit_action = QtWidgets.QAction("Exit", self) show_action.triggered.connect(self.show) quit_action.triggered.connect(self.shutdownapp) tray_menu = QtWidgets.QMenu() tray_menu.addAction(show_action) tray_menu.addAction(quit_action) self.tray_icon.setContextMenu(tray_menu) self.tray_icon.show() self.setupUI() self.show() def closeEvent(self, event): if self.service == "server": event.ignore() self.hide() self.tray_icon.showMessage( "TAG IM", "App Minimized (Running as Host)", QtWidgets.QSystemTrayIcon.Information, 1000) elif self.service == "client": event.ignore() self.hide() self.tray_icon.showMessage( "TAG IM", "App Minimized (Running as Client)", QtWidgets.QSystemTrayIcon.Information, 1000) def shutdownapp(self): if self.service == "server": self.service == "" self.broadcast("Host has shutdown") self.server.close() app.quit() elif self.service == "client": self.service == "" message = "Left the chat" self.client.send(message.encode()) self.client.close() print("Client closed manually") app.quit() elif self.service == "": app.quit() def onTrayIconActivated(self, reason): if reason == QtWidgets.QSystemTrayIcon.Trigger: self.show() self.focusWidget() def setupUI(self): mainlayout = QtWidgets.QVBoxLayout() displaybox = QtWidgets.QHBoxLayout() userlist = QtWidgets.QVBoxLayout() userlist.addWidget(QtWidgets.QLabel("Users Connected:")) userlist.addWidget(self.userwindow) displaybox.addWidget(self.chatwindow, 3) displaybox.addLayout(userlist, 1) inputbox = QtWidgets.QHBoxLayout() inputbox.addWidget(self.typingfield) inputbox.addWidget(self.sendbutton) mainlayout.addLayout(displaybox) mainlayout.addLayout(inputbox) self.setLayout(mainlayout) self.chatwindow.addItem("/host to setup server on local host (Port 7000)") self.chatwindow.addItem("/[email protected] to connect to server on local host (Port 7000)") self.chatwindow.scrollToBottom() self.typingfield.setFocus() self.setWindowTitle("TAG CHAT") def sendpressed(self): typedtext = self.typingfield.text() if typedtext: if typedtext[0] == "/": self.metaprocessor(typedtext) else: if self.service: if self.service == "server": self.broadcast(typedtext) elif self.service == "client": self.client.send(typedtext.encode()) else: self.chatwindow.addItem("Not connected to any group.") self.chatwindow.scrollToBottom() self.typingfield.clear() self.typingfield.setFocus() def metaprocessor(self, typedtext): if typedtext == "/host": serverstart = threading.Thread(target=self.makeserver, args=()) serverstart.daemon = True serverstart.start() elif typedtext[0:9] == "/connect@" and len(typedtext) > 9: userip = typedtext[9:] try: ipaddress.ip_address(userip) clientstart = threading.Thread(target=self.startclient, args=(userip, 7000)) clientstart.daemon = True clientstart.start() except ValueError: self.chatwindow.addItem("Invalid IP address provided '" + userip + "'") self.chatwindow.scrollToBottom() elif typedtext == "/quit": self.shutdownapp() else: self.chatwindow.addItem("Invalid syntax") self.chatwindow.scrollToBottom() def startclient(self, serverip, port): self.client.connect((str(serverip), port)) self.service = "client" while True: try: message = self.client.recv(4096) if message[0:10] == "~connected".encode(): connectedusers = pickle.loads(message[10:]) self.updateclientlistclient(connectedusers) else: self.unreadnotification() self.chatwindow.addItem(message.decode()) self.chatwindow.scrollToBottom() except: self.chatwindow.addItem("Host has closed the connection".decode()) self.chatwindow.scrollToBottom() self.userwindow.clear() self.service = "" break def makeserver(self): self.chatwindow.addItem("Creating server @ " + self.machineIP + ":7000") self.server.bind((self.machineIP, 7000)) self.chatwindow.addItem("Server started successfully...\nListening to all connections") self.chatwindow.scrollToBottom() self.service = "server" self.server.listen(100) while True: conn, addr = self.server.accept() message = "Connected to " + self.machineIP + ":7000" conn.send(message.encode()) self.connectedusers.append((conn, addr)) self.updateclientlistserver(self.connectedusers) newconnection = threading.Thread(target=self.startconnection, args=(conn, addr)) newconnection.daemon = True newconnection.start() def startconnection(self, conn, addr): self.chatwindow.addItem("User " + str(addr) + " has joined the group.") self.chatwindow.scrollToBottom() while True: try: data = conn.recv(4096) self.unreadnotification() self.broadcast(data.decode()) except: print("Client closing caught by server") conn.close() self.connectedusers.remove((conn, addr)) self.updateclientlistserver(self.connectedusers) break def updateclientlistserver(self, connectedusers): self.userwindow.clear() for each in connectedusers: self.userwindow.addItem(each[1][0]) def updateclientlistclient(self, connectedusers): self.userwindow.clear() for each in connectedusers: self.userwindow.addItem(each) def broadcast(self, typedtext): servermessage = self.machineIP + " : " + str(typedtext) self.chatwindow.addItem(servermessage) self.chatwindow.scrollToBottom() for each in self.connectedusers: message = each[1][0] + " : " + str(typedtext) each[0].send(message.encode()) iplist = [] for ips in self.connectedusers: iplist.append(ips[1][0]) data = pickle.dumps(iplist) each[0].send("~connected".encode() + data) def unreadnotification(self): if not self.isVisible(): self.unreadcount += 1 if time.time() - self.oldtime > 60: self.oldtime = time.time() self.tray_icon.showMessage( "TAG IM", str(self.unreadcount) + " messages unread", QtWidgets.QSystemTrayIcon.Information, 1000) else: self.unreadcount = 0 if __name__ == "__main__": # Back up the reference to the exceptionhook sys._excepthook = sys.excepthook def my_exception_hook(exctype, value, traceback): # Print the error and traceback print(exctype, value, traceback) # Call the normal Exception hook after sys._excepthook(exctype, value, traceback) sys.exit(1) # Set the exception hook to our wrapping function sys.excepthook = my_exception_hook app = QtWidgets.QApplication(sys.argv) mainApplication = MainWindow() try: sys.exit(app.exec_()) except: print("Exiting")