feat: split ui in multiple files for maintainability
All checks were successful
/ mirror (push) Successful in 4s

This commit is contained in:
Florian Griffon 2025-05-24 01:04:29 +03:00
parent 225b40b34f
commit bf6ac57f51
4 changed files with 117 additions and 114 deletions

View File

@ -1,122 +1,14 @@
import sys import sys
import random import random
import socket
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QPushButton, QLabel, QFrame, QSizePolicy, QStyle QPushButton, QLabel, QFrame, QSizePolicy, QStyle
) )
from PyQt5.QtCore import Qt, QTimer, QSize, QPointF, pyqtSignal, QThread from PyQt5.QtCore import Qt, QTimer, QSize
from PyQt5.QtGui import QPainter, QColor, QPen, QLinearGradient, QBrush, QIcon, QFont from PyQt5.QtGui import QFont
from phone_client import PhoneClient
# --- Phone Client Thread --- from waveform_widget import WaveformWidget
class PhoneClient(QThread): from phone_state import PhoneState
data_received = pyqtSignal(bytes, int) # Include client_id
state_changed = pyqtSignal(str, str, int) # Include client_id
def __init__(self, host, port, client_id):
super().__init__()
self.host = host
self.port = port
self.client_id = client_id
self.sock = None
self.running = True
def run(self):
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
self.sock.settimeout(15)
self.sock.connect((self.host, self.port))
print(f"Client {self.client_id} connected to {self.host}:{self.port}")
while self.running:
try:
data = self.sock.recv(1024)
if not data:
print(f"Client {self.client_id} disconnected")
self.state_changed.emit("CALL_END", "", self.client_id)
break
decoded_data = data.decode('utf-8', errors='ignore').strip()
print(f"Client {self.client_id} received raw: {decoded_data}")
if decoded_data in ["RINGING", "CALL_END", "CALL_DROPPED", "IN_CALL"]:
self.state_changed.emit(decoded_data, "", self.client_id)
else:
self.data_received.emit(data, self.client_id)
print(f"Client {self.client_id} received audio: {decoded_data}")
except socket.timeout:
print(f"Client {self.client_id} timed out waiting for data")
continue
except Exception as e:
print(f"Client {self.client_id} error: {e}")
self.state_changed.emit("CALL_END", "", self.client_id)
break
except Exception as e:
print(f"Client {self.client_id} connection failed: {e}")
finally:
if self.sock:
self.sock.close()
def send(self, message):
if self.sock and self.running:
try:
self.sock.send(message.encode())
print(f"Client {self.client_id} sent: {message}")
except Exception as e:
print(f"Client {self.client_id} send error: {e}")
def stop(self):
self.running = False
if self.sock:
self.sock.close()
# --- Custom Waveform Widget ---
class WaveformWidget(QWidget):
def __init__(self, parent=None, dynamic=False):
super().__init__(parent)
self.dynamic = dynamic
self.setMinimumSize(200, 80)
self.setMaximumHeight(100)
self.waveform_data = [random.randint(10, 90) for _ in range(50)]
if self.dynamic:
self.timer = QTimer(self)
self.timer.timeout.connect(self.update_waveform)
self.timer.start(100)
def update_waveform(self):
self.waveform_data = self.waveform_data[1:] + [random.randint(10, 90)]
self.update()
def set_data(self, data):
amplitude = sum(byte for byte in data) % 90 + 10
self.waveform_data = self.waveform_data[1:] + [amplitude]
self.update()
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.fillRect(self.rect(), QColor("#2D2D2D"))
gradient = QLinearGradient(0, 0, 0, self.height())
gradient.setColorAt(0.0, QColor("#0078D4"))
gradient.setColorAt(1.0, QColor("#50E6A4"))
pen = QPen(QBrush(gradient), 2)
painter.setPen(pen)
bar_width = self.width() / len(self.waveform_data)
max_h = self.height() - 10
for i, val in enumerate(self.waveform_data):
bar_height = (val / 100.0) * max_h
x = i * bar_width
y = (self.height() - bar_height) / 2
painter.drawLine(QPointF(x + bar_width / 2, y), QPointF(x + bar_width / 2, y + bar_height))
def resizeEvent(self, event):
super().resizeEvent(event)
self.update()
# --- Phone State ---
class PhoneState:
IDLE = 0
CALLING = 1
IN_CALL = 2
RINGING = 3
class PhoneUI(QMainWindow): class PhoneUI(QMainWindow):
def __init__(self): def __init__(self):
@ -182,7 +74,6 @@ class PhoneUI(QMainWindow):
client.state_changed.connect(lambda state, num, cid=i: self.set_phone_state(cid, self.map_state(state), num)) client.state_changed.connect(lambda state, num, cid=i: self.set_phone_state(cid, self.map_state(state), num))
client.start() client.start()
# Corrected lambda to handle 'checked' and capture phone_id
phone_widget_container, phone_display, phone_button, phone_waveform, phone_status_label = self._create_phone_ui( phone_widget_container, phone_display, phone_button, phone_waveform, phone_status_label = self._create_phone_ui(
f"Phone {i+1}", lambda checked, phone_id=i: self.phone_action(phone_id) f"Phone {i+1}", lambda checked, phone_id=i: self.phone_action(phone_id)
) )

View File

@ -0,0 +1,61 @@
import socket
from PyQt5.QtCore import QThread, pyqtSignal
class PhoneClient(QThread):
data_received = pyqtSignal(bytes, int) # Include client_id
state_changed = pyqtSignal(str, str, int) # Include client_id
def __init__(self, host, port, client_id):
super().__init__()
self.host = host
self.port = port
self.client_id = client_id
self.sock = None
self.running = True
def run(self):
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
self.sock.settimeout(15)
self.sock.connect((self.host, self.port))
print(f"Client {self.client_id} connected to {self.host}:{self.port}")
while self.running:
try:
data = self.sock.recv(1024)
if not data:
print(f"Client {self.client_id} disconnected")
self.state_changed.emit("CALL_END", "", self.client_id)
break
decoded_data = data.decode('utf-8', errors='ignore').strip()
print(f"Client {self.client_id} received raw: {decoded_data}")
if decoded_data in ["RINGING", "CALL_END", "CALL_DROPPED", "IN_CALL"]:
self.state_changed.emit(decoded_data, "", self.client_id)
else:
self.data_received.emit(data, self.client_id)
print(f"Client {self.client_id} received audio: {decoded_data}")
except socket.timeout:
print(f"Client {self.client_id} timed out waiting for data")
continue
except Exception as e:
print(f"Client {self.client_id} error: {e}")
self.state_changed.emit("CALL_END", "", self.client_id)
break
except Exception as e:
print(f"Client {self.client_id} connection failed: {e}")
finally:
if self.sock:
self.sock.close()
def send(self, message):
if self.sock and self.running:
try:
self.sock.send(message.encode())
print(f"Client {self.client_id} sent: {message}")
except Exception as e:
print(f"Client {self.client_id} send error: {e}")
def stop(self):
self.running = False
if self.sock:
self.sock.close()

View File

@ -0,0 +1,5 @@
class PhoneState:
IDLE = 0
CALLING = 1
IN_CALL = 2
RINGING = 3

View File

@ -0,0 +1,46 @@
import random
from PyQt5.QtWidgets import QWidget
from PyQt5.QtCore import QTimer, QSize, QPointF
from PyQt5.QtGui import QPainter, QColor, QPen, QLinearGradient, QBrush
class WaveformWidget(QWidget):
def __init__(self, parent=None, dynamic=False):
super().__init__(parent)
self.dynamic = dynamic
self.setMinimumSize(200, 80)
self.setMaximumHeight(100)
self.waveform_data = [random.randint(10, 90) for _ in range(50)]
if self.dynamic:
self.timer = QTimer(self)
self.timer.timeout.connect(self.update_waveform)
self.timer.start(100)
def update_waveform(self):
self.waveform_data = self.waveform_data[1:] + [random.randint(10, 90)]
self.update()
def set_data(self, data):
amplitude = sum(byte for byte in data) % 90 + 10
self.waveform_data = self.waveform_data[1:] + [amplitude]
self.update()
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.fillRect(self.rect(), QColor("#2D2D2D"))
gradient = QLinearGradient(0, 0, 0, self.height())
gradient.setColorAt(0.0, QColor("#0078D4"))
gradient.setColorAt(1.0, QColor("#50E6A4"))
pen = QPen(QBrush(gradient), 2)
painter.setPen(pen)
bar_width = self.width() / len(self.waveform_data)
max_h = self.height() - 10
for i, val in enumerate(self.waveform_data):
bar_height = (val / 100.0) * max_h
x = i * bar_width
y = (self.height() - bar_height) / 2
painter.drawLine(QPointF(x + bar_width / 2, y), QPointF(x + bar_width / 2, y + bar_height))
def resizeEvent(self, event):
super().resizeEvent(event)
self.update()