75 lines
2.9 KiB
Python
75 lines
2.9 KiB
Python
|
|
from typing import List, Optional
|
||
|
|
|
||
|
|
import pandas as pd
|
||
|
|
from PySide6.QtCore import Qt
|
||
|
|
from PySide6.QtWidgets import QDialog, QVBoxLayout, QLabel, QTableWidget, QTableWidgetItem, QSizePolicy
|
||
|
|
|
||
|
|
try:
|
||
|
|
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
|
||
|
|
except Exception:
|
||
|
|
# Fallback for older backends
|
||
|
|
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas # type: ignore
|
||
|
|
import matplotlib.pyplot as plt
|
||
|
|
|
||
|
|
|
||
|
|
class TablePreviewDialog(QDialog):
|
||
|
|
def __init__(self, title: str, df: pd.DataFrame, parent=None) -> None:
|
||
|
|
super().__init__(parent)
|
||
|
|
self.setWindowTitle(title or "表格预览")
|
||
|
|
layout = QVBoxLayout()
|
||
|
|
layout.addWidget(QLabel(title or "表格预览"))
|
||
|
|
|
||
|
|
table = QTableWidget()
|
||
|
|
if df is not None and not df.empty:
|
||
|
|
columns: List[str] = [str(c) for c in df.columns]
|
||
|
|
table.setColumnCount(len(columns))
|
||
|
|
table.setHorizontalHeaderLabels(columns)
|
||
|
|
table.setRowCount(len(df))
|
||
|
|
for r in range(len(df)):
|
||
|
|
for c, col in enumerate(columns):
|
||
|
|
val = df.iloc[r][col]
|
||
|
|
table.setItem(r, c, QTableWidgetItem(str(val)))
|
||
|
|
else:
|
||
|
|
table.setColumnCount(0)
|
||
|
|
table.setRowCount(0)
|
||
|
|
table.resizeColumnsToContents()
|
||
|
|
layout.addWidget(table)
|
||
|
|
self.setLayout(layout)
|
||
|
|
self.resize(900, 600)
|
||
|
|
|
||
|
|
|
||
|
|
class ChartPreviewDialog(QDialog):
|
||
|
|
def __init__(self, title: str, df: pd.DataFrame, fields: Optional[List[str]] = None, chart_type: str = "line", parent=None) -> None:
|
||
|
|
super().__init__(parent)
|
||
|
|
self.setWindowTitle(title or "图表预览")
|
||
|
|
layout = QVBoxLayout()
|
||
|
|
layout.addWidget(QLabel(title or "图表预览"))
|
||
|
|
|
||
|
|
fig, ax = plt.subplots(figsize=(8, 4))
|
||
|
|
canvas = FigureCanvas(fig)
|
||
|
|
canvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||
|
|
layout.addWidget(canvas)
|
||
|
|
|
||
|
|
# Attempt to plot time series by field
|
||
|
|
if df is not None and not df.empty and "_time" in df.columns and "_value" in df.columns:
|
||
|
|
plot_fields: List[str] = fields or sorted([str(f) for f in df.get("_field", pd.Series(dtype=str)).unique() if pd.notna(f)])
|
||
|
|
if not plot_fields:
|
||
|
|
plot_fields = ["_value"]
|
||
|
|
for field in plot_fields:
|
||
|
|
if "_field" in df.columns:
|
||
|
|
sdf = df[df["_field"] == field]
|
||
|
|
else:
|
||
|
|
sdf = df
|
||
|
|
if not sdf.empty:
|
||
|
|
ax.plot(pd.to_datetime(sdf["_time"]), pd.to_numeric(sdf["_value"], errors="coerce"), label=str(field))
|
||
|
|
ax.set_xlabel("Time")
|
||
|
|
ax.set_ylabel("Value")
|
||
|
|
ax.grid(True, alpha=0.3)
|
||
|
|
ax.legend(loc="best")
|
||
|
|
else:
|
||
|
|
ax.text(0.5, 0.5, "无可绘制的数据", ha="center", va="center", transform=ax.transAxes)
|
||
|
|
|
||
|
|
canvas.draw()
|
||
|
|
self.setLayout(layout)
|
||
|
|
self.resize(900, 600)
|