diff --git a/streaming_gui.py b/streaming_gui.py index 8685e41..59056ad 100644 --- a/streaming_gui.py +++ b/streaming_gui.py @@ -12,9 +12,13 @@ from PyQt5.QtWidgets import ( QTextEdit, QGroupBox, QFormLayout, + QTableWidget, + QTableWidgetItem, + QHeaderView, + QCheckBox, + QLabel, ) from PyQt5.QtCore import Qt, QProcess, pyqtSignal, QObject - from StreamingCommunity.run import load_search_functions search_functions = load_search_functions() @@ -40,10 +44,9 @@ class Stream(QObject): class StreamingGUI(QMainWindow): def __init__(self): super().__init__() - - # process to start script self.process = None - + self.current_context = None # 'seasons', 'episodes', or None + self.selected_season = None self.init_ui() # output redirect @@ -55,13 +58,10 @@ class StreamingGUI(QMainWindow): self.setWindowTitle("StreamingCommunity GUI") self.setGeometry(100, 100, 1000, 700) - # widget and main layout central_widget = QWidget() main_layout = QVBoxLayout() - # tabs widget tab_widget = QTabWidget() - run_tab = QWidget() run_layout = QVBoxLayout() @@ -73,7 +73,6 @@ class StreamingGUI(QMainWindow): 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) @@ -81,7 +80,6 @@ class StreamingGUI(QMainWindow): self.site_combo.setCurrentIndex(0) search_layout.addRow("Seleziona sito:", self.site_combo) - search_group.setLayout(search_layout) run_layout.addWidget(search_group) @@ -97,17 +95,39 @@ class StreamingGUI(QMainWindow): self.stop_button.setEnabled(False) control_layout.addWidget(self.stop_button) + # Console visibility checkbox + self.console_checkbox = QCheckBox("Mostra Console") + self.console_checkbox.setChecked(False) + self.console_checkbox.stateChanged.connect(self.toggle_console) + control_layout.addWidget(self.console_checkbox) + run_layout.addLayout(control_layout) + # Status label (replacing loader) + self.status_label = QLabel("Richiesta in corso...") + self.status_label.setAlignment(Qt.AlignCenter) + self.status_label.hide() + run_layout.addWidget(self.status_label) + # output area output_group = QGroupBox("Output") output_layout = QVBoxLayout() + # Table widget + self.results_table = QTableWidget() + self.results_table.setVisible(False) + self.results_table.setSelectionBehavior(QTableWidget.SelectRows) + self.results_table.setSelectionMode(QTableWidget.SingleSelection) + self.results_table.setEditTriggers(QTableWidget.NoEditTriggers) + output_layout.addWidget(self.results_table) + + # Console output self.output_text = QTextEdit() self.output_text.setReadOnly(True) + self.output_text.hide() output_layout.addWidget(self.output_text) - # add input layout + # Input controls input_layout = QHBoxLayout() self.input_field = QLineEdit() self.input_field.setPlaceholderText("Inserisci l'indice del media...") @@ -115,7 +135,6 @@ class StreamingGUI(QMainWindow): self.send_button = QPushButton("Invia") self.send_button.clicked.connect(self.send_input) - # initially hide input layout self.input_field.hide() self.send_button.hide() @@ -130,24 +149,107 @@ class StreamingGUI(QMainWindow): tab_widget.addTab(run_tab, "Esecuzione") main_layout.addWidget(tab_widget) - central_widget.setLayout(main_layout) self.setCentralWidget(central_widget) + def toggle_console(self, state): + self.output_text.setVisible(state == Qt.Checked) + + def parse_and_show_results(self, text): + # Handle seasons list + if "Seasons found:" in text: + self.status_label.hide() + num_seasons = int(text.split("Seasons found:")[1].split()[0]) + + # Setup table for seasons + self.results_table.clear() + self.results_table.setColumnCount(2) + self.results_table.setHorizontalHeaderLabels(["Index", "Season"]) + + # Populate table with seasons + self.results_table.setRowCount(num_seasons) + for i in range(num_seasons): + index_item = QTableWidgetItem(str(i + 1)) + season_item = QTableWidgetItem(f"Stagione {i + 1}") + self.results_table.setItem(i, 0, index_item) + self.results_table.setItem(i, 1, season_item) + + # Adjust columns and show table + self.results_table.horizontalHeader().setSectionResizeMode( + QHeaderView.ResizeToContents + ) + self.results_table.setVisible(True) + self.results_table.itemSelectionChanged.connect(self.handle_selection) + return + + # Handle regular table output (episodes or search results) + if "┏━━━━━━━┳" in text and "└───────┴" in text: + self.status_label.hide() + + # Extract table content + table_lines = text[text.find("┏") : text.find("└")].split("\n") + + # Parse headers + headers = table_lines[1].split("┃")[1:-1] + headers = [h.strip() for h in headers] + + # Setup table + self.results_table.clear() + self.results_table.setColumnCount(len(headers)) + self.results_table.setHorizontalHeaderLabels(headers) + + # Parse rows + rows = [] + for line in table_lines[3:]: + if line.strip() and "│" in line: + cells = line.split("│")[1:-1] + cells = [cell.strip() for cell in cells] + rows.append(cells) + + # Populate table + self.results_table.setRowCount(len(rows)) + for i, row in enumerate(rows): + for j, cell in enumerate(row): + item = QTableWidgetItem(cell) + self.results_table.setItem(i, j, item) + + # Adjust columns + self.results_table.horizontalHeader().setSectionResizeMode( + QHeaderView.ResizeToContents + ) + + # Show table and connect selection + self.results_table.setVisible(True) + self.results_table.itemSelectionChanged.connect(self.handle_selection) + + def handle_selection(self): + if self.results_table.selectedItems(): + selected_row = self.results_table.currentRow() + if self.input_field.isVisible(): + if self.current_context == "seasons": + # For seasons, we add 1 because seasons are 1-based + self.input_field.setText(str(selected_row + 1)) + else: + # For episodes and search results, use the row number directly + self.input_field.setText(str(selected_row)) + def run_script(self): if self.process is not None and self.process.state() == QProcess.Running: print("Script già in esecuzione.") return + self.current_context = None + self.selected_season = None + self.results_table.setVisible(False) + self.status_label.setText("Richiesta in corso...") + self.status_label.show() + # build command line args args = [] - - # add search terms search_terms = self.search_terms.text() if search_terms: args.extend(["-s", search_terms]) - # add site if present site_index = self.site_combo.currentIndex() if site_index >= 0: site_text = sites[site_index]["flag"] @@ -157,7 +259,6 @@ class StreamingGUI(QMainWindow): self.output_text.clear() print(f"Avvio script con argomenti: {' '.join(args)}") - # create and start process self.process = QProcess() self.process.readyReadStandardOutput.connect(self.handle_stdout) self.process.readyReadStandardError.connect(self.handle_stderr) @@ -167,46 +268,76 @@ class StreamingGUI(QMainWindow): script_path = "run_streaming.py" self.process.start(python_executable, [script_path] + args) - - # Update button state 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() - # Wait for close (with timeout) - if not self.process.waitForFinished(3000): - self.process.kill() - print("Script terminato.") - - # Update button state - 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) - # show input controls when prompted an insert + # Detect context + if "Seasons found:" in stdout: + self.current_context = "seasons" + self.input_field.setPlaceholderText( + "Inserisci il numero della stagione (es: 1, *, 1-2, 3-*)" + ) + elif "Episodes find:" in stdout: + self.current_context = "episodes" + self.input_field.setPlaceholderText( + "Inserisci l'indice dell'episodio (es: 1, *, 1-2, 3-*)" + ) + + # Parse and show results if available + if "┏━━━━━━━┳" in stdout or "Seasons found:" in stdout: + self.parse_and_show_results(stdout) + elif "Episodes find:" in stdout: + self.results_table.hide() + self.status_label.setText(stdout) + self.status_label.show() + + # Show input controls when needed if "Insert" in stdout: self.input_field.show() self.send_button.show() self.input_field.setFocus() - - # check that output has scroll to bottom self.output_text.verticalScrollBar().setValue( self.output_text.verticalScrollBar().maximum() ) def send_input(self): - if self.process and self.process.state() == QProcess.Running: - user_input = self.input_field.text() + "\n" - self.process.write(user_input.encode()) - self.input_field.clear() - self.input_field.hide() - self.send_button.hide() + if not self.process or self.process.state() != QProcess.Running: + return + + user_input = self.input_field.text().strip() + + # Handle season selection + if self.current_context == "seasons": + if "-" in user_input or user_input == "*": + # Multiple seasons selected, hide table + self.results_table.hide() + else: + # Single season selected, table will update with episodes + self.selected_season = user_input + + # Handle episode selection + elif self.current_context == "episodes": + if "-" in user_input or user_input == "*": + # Multiple episodes selected, hide table + self.results_table.hide() + + # Send input to process + self.process.write(f"{user_input}\n".encode()) + self.input_field.clear() + self.input_field.hide() + self.send_button.hide() + + # Show status label for next step + if self.current_context == "seasons" and not ( + "-" in user_input or user_input == "*" + ): + self.status_label.setText("Caricamento episodi...") + self.status_label.show() def handle_stderr(self): data = self.process.readAllStandardError() @@ -218,6 +349,7 @@ class StreamingGUI(QMainWindow): self.stop_button.setEnabled(False) self.input_field.hide() self.send_button.hide() + self.status_label.hide() print("Script terminato.") def update_output(self, text): @@ -227,16 +359,21 @@ class StreamingGUI(QMainWindow): self.output_text.setTextCursor(cursor) self.output_text.ensureCursorVisible() + def stop_script(self): + if self.process is not None and self.process.state() == QProcess.Running: + self.process.terminate() + if not self.process.waitForFinished(3000): + self.process.kill() + print("Script terminato.") + self.run_button.setEnabled(True) + self.stop_button.setEnabled(False) + def closeEvent(self, event): - # Stop all process if self.process is not None and self.process.state() == QProcess.Running: self.process.terminate() if not self.process.waitForFinished(1000): self.process.kill() - - # Restore stdout sys.stdout = sys.__stdout__ - event.accept()