mirror of
https://github.com/Arrowar/StreamingCommunity.git
synced 2025-06-06 11:35:29 +00:00
Enhance GUI with results table and console toggle features
This commit is contained in:
parent
7685b4e121
commit
5d515e4e09
223
streaming_gui.py
223
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()
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user