Files
tcp-chat/client/dialog.py

115 lines
4.3 KiB
Python

import re
from typing import Tuple
from PyQt5.QtCore import QEvent
from PyQt5.QtWidgets import QDialog, QStatusBar
from shared.constants import ConnectionOptions, DEFAULT_IP, DEFAULT_PORT
from client.ui.ConnectionDialog import Ui_ConnectionDialog
from client.nickname import Ui_NicknameDialog
class NicknameDialog(QDialog, Ui_NicknameDialog):
def __init__(self, *args, **kwargs):
super(NicknameDialog, self).__init__(*args, **kwargs)
self.setupUi(self)
self.disabled = True
self.buttonBox.setDisabled(True)
self.setWindowTitle("Set Nickname")
self.lineEdit.returnPressed.connect(self.trySubmit)
self.lineEdit.textEdited.connect(self.controlSubmit)
self.show()
def controlSubmit(self):
"""Updates whether the dialog box is allowed to proceed"""
if len(self.lineEdit.text()) > 2:
if self.disabled:
self.disabled = False
self.buttonBox.setDisabled(False)
else:
if not self.disabled:
self.disabled = True
self.buttonBox.setDisabled(True)
def trySubmit(self):
"""Tries to submit the Dialog through the QLineEdit via Enter key"""
if not self.disabled:
self.accept()
class ConnectionDialog(QDialog, Ui_ConnectionDialog):
def __init__(self, nickname: str = None, *args, **kwargs):
super(ConnectionDialog, self).__init__(*args, **kwargs)
self.setupUi(self)
self.connect_button.setDisabled(True)
if nickname:
self.nickname_input.setText(nickname)
self.validation()
self.server_address_input.textEdited.connect(self.validation)
self.port_input.textEdited.connect(self.validation)
self.nickname_input.textEdited.connect(self.validation)
self.connect_button.pressed.connect(self.connect)
self.status_bar = QStatusBar(self)
self.status_layout.addWidget(self.status_bar)
self.connect_pressed = False
self.show()
def connect(self) -> None:
self.connect_pressed = True
self.close()
def event(self, event: QEvent) -> bool:
if event.type() == QEvent.StatusTip:
self.status_bar.showMessage(event.tip())
return True
return super().event(event)
@property
def settings(self) -> ConnectionOptions:
return ConnectionOptions(ip=self.server_address_input.text() or DEFAULT_IP,
port=int(self.port_input.text() or DEFAULT_PORT),
nickname=self.nickname_input.text(),
password=self.password_input.text(),
remember=self.remember_checkbox.checkState())
def validation(self, full: bool = True) -> None:
address, port = self.validate_address()
nickname = self.validate_nickname()
if not address and not port:
self.status_bar.showMessage('Please fill in a valid server address and port.', 3000)
elif not address:
self.status_bar.showMessage('Please fill in a valid server address.', 3000)
elif not port:
self.status_bar.showMessage('Please fill in a valid port number.', 3000)
elif full and not nickname:
self.status_bar.showMessage('Please use a valid nickname. Letters and digits, 3-15 characters long.', 3000)
self.connect_button.setDisabled(not (address and port and nickname))
self.test_connection_button.setDisabled(not (address and port))
def validate_nickname(self) -> bool:
"""Returns True if the nickname follows the nickname guidelines requested."""
return re.match(r'^[A-z0-9]{3,15}$', self.nickname_input.text()) is not None
def validate_address(self) -> Tuple[bool, bool]:
"""Returns True if the server address and port combination is valid"""
address = self.server_address_input.text() or DEFAULT_IP
port = self.port_input.text() or str(DEFAULT_PORT)
valid_address = len(address) > 0 and re.match(r'^\d{1,4}\.\d{1,4}\.\d{1,4}\.\d{1,4}|localhost$',
address) is not None
valid_port = len(port) > 0 and re.match(r'^\d{4,5}$', port) is not None and 1024 <= int(port) <= 65536
return valid_address, valid_port