# --- VERSIONE FINALE CON COLONNE FR EVIDENZIATE: containers/dashboards/dash_diritti/pivot_table_diritti_widget.py --- import logging import pandas as pd from PyQt6.QtWidgets import QTableWidget, QTableWidgetItem, QHeaderView, QAbstractItemView from PyQt6.QtCore import Qt, pyqtSignal from PyQt6.QtGui import QColor logger = logging.getLogger(__name__) def safe_format_value(value): if pd.isna(value) or value == 0: return "" try: return str(int(value)) except (ValueError, TypeError): return "" class PivotTableDirittiWidget(QTableWidget): """ Widget specializzato per visualizzare la pivot dei diritti. Evidenzia le colonne First Run (FR) con uno sfondo colorato. """ cell_selected_for_detail = pyqtSignal(str, str, str) def __init__(self, theme: dict): super().__init__() self.theme = theme self.pivot_df = None self._setup_ui() def _setup_ui(self): self.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectItems) self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) self.verticalHeader().setVisible(True) self.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Interactive) self.cellClicked.connect(self._on_cell_clicked) self.setAlternatingRowColors(False) # Disabilitato per un look pulito self._apply_styling() def clear_table(self): self.setRowCount(0); self.setColumnCount(0); self.pivot_df = None def populate(self, data: pd.DataFrame, active_fr_rr_filter=None): self.clear_table() if data.empty: return try: # ... (la logica di pivot rimane identica) self.pivot_df = data.pivot_table( index='tipologia', columns='anno', values=['first_run_count', 're_run_count'], aggfunc='sum' ).sort_index() flat_columns = [f"{year}-{'FR' if metric == 'first_run_count' else 'RR'}" for metric, year in self.pivot_df.columns] self.pivot_df.columns = flat_columns self.pivot_df = self.pivot_df.sort_index(axis=1) tipologie = self.pivot_df.index.tolist() col_headers = self.pivot_df.columns.tolist() self.setRowCount(len(tipologie)) self.setColumnCount(len(col_headers)) self.setVerticalHeaderLabels(tipologie) self.setHorizontalHeaderLabels(col_headers) fr_background_color = QColor("#FFFACD") # LemonChiffon for row_idx, tipologia in enumerate(tipologie): for col_idx, header in enumerate(col_headers): value = self.pivot_df.loc[tipologia, header] item_value = QTableWidgetItem(safe_format_value(value)) item_value.setTextAlignment(Qt.AlignmentFlag.AlignCenter) if header.endswith('-FR'): item_value.setBackground(fr_background_color) self.setItem(row_idx, col_idx, item_value) # --- MODIFICA CHIAVE 2: Logica per mostrare/nascondere le colonne --- for i in range(self.columnCount()): header_text = self.horizontalHeaderItem(i).text() # Caso: filtro "Solo First Run" attivo, nascondi le colonne RR if active_fr_rr_filter == 'F' and header_text.endswith('-RR'): self.setColumnWidth(i, 0) # Caso: filtro "Solo Re Run" attivo, nascondi le colonne FR elif active_fr_rr_filter == 'R' and header_text.endswith('-FR'): self.setColumnWidth(i, 0) # Altrimenti, mostra la colonna else: self.setColumnWidth(i, 65) self.verticalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) except Exception as e: logger.error(f"Errore durante il popolamento della pivot dei diritti: {e}", exc_info=True) def _on_cell_clicked(self, row, column): if self.pivot_df is None or row < 0 or column < 0: return try: tipologia = self.verticalHeaderItem(row).text() header_text = self.horizontalHeaderItem(column).text() parts = header_text.split('-') anno, fr_rr_short = parts[0], parts[1] fr_rr_value = 'F' if fr_rr_short == 'FR' else 'R' self.cell_selected_for_detail.emit(tipologia, anno, fr_rr_value) except (AttributeError, IndexError) as e: logger.warning(f"Click su una cella non valida: {e}") def _apply_styling(self): table_colors = self.theme.get('table', {}) fonts = self.theme.get('fonts', {}) stylesheet = f""" QTableWidget {{ gridline-color: {table_colors.get('border', '#EDEBE9')}; border: 1px solid {table_colors.get('border', '#EDEBE9')}; }} QHeaderView::section {{ background-color: {table_colors.get('header_bg', '#0078D4')}; color: {table_colors.get('header_text', '#FFFFFF')}; padding: 4px; border: 1px solid {table_colors.get('border', '#EDEBE9')}; font-weight: 600; }} QTableWidget::item {{ padding: 5px; }} QTableWidget::item:selected {{ background-color: {table_colors.get('selected_bg', '#DEECF9')}; color: {table_colors.get('selected_text', '#323130')}; }} """ self.setStyleSheet(stylesheet)