From 6bf43bf9746e35fa5d9bd479c33f85844c3868e0 Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 12 Jun 2025 13:49:41 +0200 Subject: [PATCH] =?UTF-8?q?Mejora=20en=20la=20gesti=C3=B3n=20de=20plots=20?= =?UTF-8?q?y=20enlaces=20interactivos.=20Se=20a=C3=B1ade=20manejo=20de=20e?= =?UTF-8?q?rrores=20para=20la=20disponibilidad=20de=20Matplotlib=20y=20se?= =?UTF-8?q?=20optimiza=20la=20creaci=C3=B3n=20de=20plots=20con=20un=20fond?= =?UTF-8?q?o=20oscuro.=20Se=20implementa=20el=20cambio=20de=20cursor=20al?= =?UTF-8?q?=20pasar=20sobre=20enlaces=20en=20el=20editor=20de=20texto,=20m?= =?UTF-8?q?ejorando=20la=20experiencia=20del=20usuario.=20Se=20a=C3=B1aden?= =?UTF-8?q?=20mensajes=20de=20depuraci=C3=B3n=20para=20el=20seguimiento=20?= =?UTF-8?q?de=20eventos=20de=20clic=20en=20enlaces.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .data/history.txt | 20 +------------------- app/gui_evaluation.py | 3 ++- app/gui_main.py | 1 + app/gui_popup.py | 35 +++++++++++++++++++++++++++-------- app/gui_widgets.py | 21 +++++++++++++++++++++ 5 files changed, 52 insertions(+), 28 deletions(-) diff --git a/.data/history.txt b/.data/history.txt index dc6dece..0938bf3 100644 --- a/.data/history.txt +++ b/.data/history.txt @@ -1,19 +1 @@ - -salario=horas*tarifa -#salario=8000 -#tarifa=36 - -horas=? - - -plot(sin(x),(x,0,1)) - - - - - - - - - - +plot(sin(x), (x, 0, 1)) \ No newline at end of file diff --git a/app/gui_evaluation.py b/app/gui_evaluation.py index a4af69b..31d796b 100644 --- a/app/gui_evaluation.py +++ b/app/gui_evaluation.py @@ -40,7 +40,7 @@ class EvaluationManager: 'custom_type': self._create_format("#4ec9b0"), 'plot': self._create_format("#569cd6", underline=True), 'type_indicator': self._create_format("#808080"), - 'clickable': self._create_format("#4fc3f7", underline=True), + 'clickable': self._create_format("#4fc3f7", underline=True, bold=True), 'helper': self._create_format("#ffd700", italic=True) } @@ -254,6 +254,7 @@ class EvaluationManager: cursor.insertText(display_text, self.output_formats.get('clickable')) end_pos = cursor.position() self.main_window.output_text.clickable_links[(start_pos, end_pos)] = (link_id, result_object) + self.logger.debug(f"🔗 Link creado: {display_text} en posición {start_pos}-{end_pos}, ID: {link_id}") elif len(part_data) >= 2: tag, content = part_data[0], part_data[1] diff --git a/app/gui_main.py b/app/gui_main.py index e868336..c025385 100644 --- a/app/gui_main.py +++ b/app/gui_main.py @@ -293,6 +293,7 @@ class HybridCalculatorPySide6(QMainWindow): def _handle_output_link_click(self, link_id: str, result_object): """Maneja clicks en links del output""" + self.logger.debug(f"🖱️ Click en link recibido: {link_id}, objeto: {type(result_object).__name__}") # Delegar al evaluation manager self.evaluation_manager.handle_output_link_click(link_id, result_object) diff --git a/app/gui_popup.py b/app/gui_popup.py index 174305e..bc46d36 100644 --- a/app/gui_popup.py +++ b/app/gui_popup.py @@ -8,8 +8,13 @@ from PySide6.QtGui import QFont, QTextCursor, QTextCharFormat, QColor from PySide6.QtWebEngineWidgets import QWebEngineView import sympy from typing import Any, Optional, Dict, List, Tuple -import matplotlib.pyplot as plt -from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg +try: + import matplotlib.pyplot as plt + from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg + MATPLOTLIB_AVAILABLE = True +except ImportError: + print("⚠️ Matplotlib no disponible - plots no funcionarán") + MATPLOTLIB_AVAILABLE = False import numpy as np @@ -127,12 +132,9 @@ class InteractiveResultManager(QWidget): def handle_interactive_click(self, result: Any, is_mathjax_click: bool = False): """Maneja clicks en elementos interactivos""" if isinstance(result, PlotResult): - if not is_mathjax_click: - # Primera vez: mostrar en MathJax - self.plot_requested.emit(result) - else: - # Click en MathJax: abrir ventana emergente - self._show_plot_window(result) + # Abrir ventana de plot directamente + print(f"🖱️ Abriendo ventana de plot para: {result.plot_type}") + self._show_plot_window(result) else: # Otros tipos siempre abren ventana self._handle_other_interactive_click(result) @@ -303,7 +305,18 @@ class InteractiveResultManager(QWidget): if not parent_frame.layout(): parent_frame.setLayout(QVBoxLayout()) + if not MATPLOTLIB_AVAILABLE: + error_label = QLabel("Matplotlib no está disponible.\nInstala con: pip install matplotlib") + error_label.setStyleSheet("color: #f44747; font-size: 12px;") + error_label.setWordWrap(True) + parent_frame.layout().addWidget(error_label) + return + + print(f"📊 Creando plot {plot_result.plot_type} con args: {plot_result.args}") + fig, ax = plt.subplots(figsize=(8, 6)) + fig.patch.set_facecolor('#1a1a1a') # Fondo oscuro + ax.set_facecolor('#1a1a1a') if plot_result.plot_type == "plot": self._create_2d_plot(fig, ax, plot_result.args, plot_result.kwargs) @@ -314,7 +327,13 @@ class InteractiveResultManager(QWidget): canvas = FigureCanvasQTAgg(fig) parent_frame.layout().addWidget(canvas) + print("✅ Plot creado exitosamente") + except Exception as e: + print(f"❌ Error creando plot: {e}") + import traceback + traceback.print_exc() + if not parent_frame.layout(): parent_frame.setLayout(QVBoxLayout()) diff --git a/app/gui_widgets.py b/app/gui_widgets.py index c36eea8..d03243e 100644 --- a/app/gui_widgets.py +++ b/app/gui_widgets.py @@ -41,6 +41,7 @@ class OutputTextEdit(QTextEdit): self.setReadOnly(True) self.setFont(QFont("Consolas", 11)) self.clickable_links = {} # {(start, end): (link_id, object)} + self.setMouseTracking(True) # Habilitar tracking del mouse def mousePressEvent(self, event): """Detecta clicks en links""" @@ -59,6 +60,26 @@ class OutputTextEdit(QTextEdit): return super().mousePressEvent(event) + + def mouseMoveEvent(self, event): + """Cambia el cursor cuando está sobre un link""" + cursor = self.cursorForPosition(event.pos()) + pos = cursor.position() + + # Verificar si el mouse está sobre un link + over_link = False + for (start, end), (link_id, obj) in self.clickable_links.items(): + if start <= pos <= end: + over_link = True + break + + # Cambiar cursor + if over_link: + self.setCursor(Qt.PointingHandCursor) + else: + self.setCursor(Qt.ArrowCursor) + + super().mouseMoveEvent(event) class ExpandableLatexButton(QPushButton):