From 4e2d6ca73f995f15601f908f29620b62204a38c1 Mon Sep 17 00:00:00 2001 From: Francesco Grazioso Date: Tue, 25 Feb 2025 11:57:17 +0100 Subject: [PATCH] Add GUI for script execution using PyQt5 and update dependencies This commit introduces a new graphical user interface (GUI) implemented in `streaming_gui.py`, enabling users to execute and interact with the script more intuitively. The GUI includes features for search inputs, site selection, script control, and real-time output display. Additionally, the `requirements.txt` file has been updated to include the PyQt5 dependency. --- requirements.txt | 3 +- streaming_gui.py | 200 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 streaming_gui.py diff --git a/requirements.txt b/requirements.txt index 0dca602..97ca848 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,4 +11,5 @@ pathvalidate pycryptodomex ua-generator qbittorrent-api -pyTelegramBotAPI \ No newline at end of file +pyTelegramBotAPI +PyQt5 \ No newline at end of file diff --git a/streaming_gui.py b/streaming_gui.py new file mode 100644 index 0000000..ee3c6ab --- /dev/null +++ b/streaming_gui.py @@ -0,0 +1,200 @@ +import sys +from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, + QHBoxLayout, QLineEdit, QPushButton, + QComboBox, QTabWidget, QTextEdit, QGroupBox, + QFormLayout) +from PyQt5.QtCore import Qt, QProcess, pyqtSignal, QObject + +from StreamingCommunity.run import load_search_functions + +search_functions = load_search_functions() +sites = [] +for alias, (_, use_for) in search_functions.items(): + sites.append({"index": len(sites), "name": alias.split("_")[0], "flag": alias[:3].upper()}) + +class Stream(QObject): + """Reindirizza l'output dello script alla GUI""" + newText = pyqtSignal(str) + + def write(self, text): + self.newText.emit(str(text)) + + def flush(self): + pass + + +class StreamingGUI(QMainWindow): + def __init__(self): + super().__init__() + + # Processo per eseguire lo script + self.process = None + + self.init_ui() + + # Reindirizzamento dell'output + self.stdout_stream = Stream() + self.stdout_stream.newText.connect(self.update_output) + sys.stdout = self.stdout_stream + + def init_ui(self): + self.setWindowTitle("StreamingCommunity GUI") + self.setGeometry(100, 100, 1000, 700) + + # Widget e layout principale + central_widget = QWidget() + main_layout = QVBoxLayout() + + # Crea un widget a schede + tab_widget = QTabWidget() + + # Scheda 1: Esecuzione script + run_tab = QWidget() + run_layout = QVBoxLayout() + + # Gruppo per i parametri di ricerca + search_group = QGroupBox("Parametri di Ricerca") + search_layout = QFormLayout() + + self.search_terms = QLineEdit() + search_layout.addRow("Termini di ricerca:", self.search_terms) + + self.site_combo = QComboBox() + + for site in sites: + self.site_combo.addItem(f"{site['name']}", site['index']) + self.site_combo.setItemData(site['index'], site['flag'], Qt.ToolTipRole) + if self.site_combo.count() > 0: + self.site_combo.setCurrentIndex(0) + # Qui dovresti popolare il combobox con i siti disponibili + # Per ora lo lascio vuoto, ma andrebbe riempito dinamicamente + search_layout.addRow("Seleziona sito:", self.site_combo) + + search_group.setLayout(search_layout) + run_layout.addWidget(search_group) + + # Bottoni di controllo + control_layout = QHBoxLayout() + + self.run_button = QPushButton("Esegui Script") + self.run_button.clicked.connect(self.run_script) + control_layout.addWidget(self.run_button) + + self.stop_button = QPushButton("Ferma Script") + self.stop_button.clicked.connect(self.stop_script) + self.stop_button.setEnabled(False) + control_layout.addWidget(self.stop_button) + + run_layout.addLayout(control_layout) + + # Area di output + output_group = QGroupBox("Output") + output_layout = QVBoxLayout() + + self.output_text = QTextEdit() + self.output_text.setReadOnly(True) + output_layout.addWidget(self.output_text) + + output_group.setLayout(output_layout) + run_layout.addWidget(output_group) + + run_tab.setLayout(run_layout) + tab_widget.addTab(run_tab, "Esecuzione") + + main_layout.addWidget(tab_widget) + + central_widget.setLayout(main_layout) + self.setCentralWidget(central_widget) + + + def run_script(self): + if self.process is not None and self.process.state() == QProcess.Running: + print("Script giĆ  in esecuzione.") + return + + # Costruisci la command line con gli argomenti + args = [] + + # Aggiungi i termini di ricerca + search_terms = self.search_terms.text() + if search_terms: + args.extend(['-s', search_terms]) + + # Aggiungi il sito selezionato se presente + site_index = self.site_combo.currentIndex() + if site_index >= 0: + site_text = sites[site_index]['flag'] + # Assumo che il nome del sito sia il primo elemento del testo + site_name = site_text.split()[0].upper() + args.append(f'-{site_name}') + + self.output_text.clear() + print(f"Avvio script con argomenti: {' '.join(args)}") + + # Creiamo e avviamo il processo + self.process = QProcess() + self.process.readyReadStandardOutput.connect(self.handle_stdout) + self.process.readyReadStandardError.connect(self.handle_stderr) + self.process.finished.connect(self.process_finished) + + python_executable = sys.executable + script_path = "run_streaming.py" + + self.process.start(python_executable, [script_path] + args) + + # Aggiorna lo stato dei pulsanti + self.run_button.setEnabled(False) + self.stop_button.setEnabled(True) + + def stop_script(self): + if self.process is not None and self.process.state() == QProcess.Running: + self.process.terminate() + # Attendi che si chiuda (con timeout) + if not self.process.waitForFinished(3000): + self.process.kill() + print("Script terminato.") + + # Aggiorna lo stato dei pulsanti + self.run_button.setEnabled(True) + self.stop_button.setEnabled(False) + + def handle_stdout(self): + data = self.process.readAllStandardOutput() + stdout = bytes(data).decode('utf8', errors='replace') + self.update_output(stdout) + + def handle_stderr(self): + data = self.process.readAllStandardError() + stderr = bytes(data).decode('utf8', errors='replace') + self.update_output(stderr) + + def process_finished(self): + self.run_button.setEnabled(True) + self.stop_button.setEnabled(False) + print("Script terminato.") + + def update_output(self, text): + cursor = self.output_text.textCursor() + cursor.movePosition(cursor.End) + cursor.insertText(text) + self.output_text.setTextCursor(cursor) + self.output_text.ensureCursorVisible() + + def closeEvent(self, event): + # Fermae qualsiasi processo in esecuzione prima di chiudere + if self.process is not None and self.process.state() == QProcess.Running: + self.process.terminate() + if not self.process.waitForFinished(1000): + self.process.kill() + + # Ripristina stdout + sys.stdout = sys.__stdout__ + + event.accept() + + +if __name__ == '__main__': + app = QApplication(sys.argv) + gui = StreamingGUI() + gui.show() + sys.exit(app.exec_()) \ No newline at end of file