图标升级

This commit is contained in:
2026-05-16 00:44:37 +08:00
parent 837996c436
commit d80e8dd05d
2113 changed files with 14850 additions and 244328 deletions

View File

@@ -9,7 +9,7 @@ from utils.floating_keyboard import FloatingKeyboard
MOVE_STEP = 10 # 每次点击移动 mm (保留备用)
MOVE_DETECT_MS = 100
MOVE_DETECT_MS = 300
class JoystickWidget(QWidget):
@@ -32,7 +32,7 @@ class JoystickWidget(QWidget):
# 定时发送 GCode
self._move_timer = QTimer(self)
self._move_timer.setInterval(120) # ~8次/秒
self._move_timer.setInterval(MOVE_DETECT_MS)
self._move_timer.timeout.connect(self._emit_move)
# 回调(上层设置)
@@ -45,7 +45,9 @@ class JoystickWidget(QWidget):
return
ratio = min(dist / (self._radius_outer - self._radius_inner), 1.0)
# 速度映射30% ~ 100% * max_speed
speed = int((0.3 + ratio * 0.7) * self._max_speed)
# speed = int((0.3 + ratio * 0.7) * self._max_speed)
# ratio = min(dist / max_dist, 1.0)
speed = ratio * self._max_speed / (1000/MOVE_DETECT_MS)
if dist > 0:
nx = self._dx / dist
ny = self._dy / dist
@@ -350,12 +352,13 @@ class ControlPage(QWidget):
def _on_joystick_move(self, nx, ny, speed):
if not self._is_control_enabled():
return
step = 5.0
step = speed * MOVE_DETECT_MS / 1000
dx = nx * step
dy = ny * step
tx = max(self.x_min, min(self.x_max, self.pos_x + dx))
ty = max(self.y_min, min(self.y_max, self.pos_y + dy))
gcode = f"G1 X{tx:.1f} Y{ty:.1f} F{speed}"
print(f"Moving: X{tx:.1f} Y{ty:.1f} F{speed}")
self.api_client.send_gcode(gcode)
self.pos_x, self.pos_y = tx, ty
self._sync_inputs()
@@ -363,11 +366,11 @@ class ControlPage(QWidget):
def _on_fader_move(self, direction, speed):
if not self._is_control_enabled():
return
print(f"d:{direction} s:{speed}")
step = speed * MOVE_DETECT_MS / 1000
tz = self.pos_z + direction * step
tz = max(self.z_min, min(self.z_max, tz))
gcode = f"G1 Z{tz:.3f} F{speed}"
print(f"Moving: Z{tz:.3f} F{speed}")
self.api_client.send_gcode(gcode)
self.pos_z = tz
self._sync_inputs()

View File

@@ -18,14 +18,16 @@ from PyQt6.QtWidgets import (
QCheckBox,
)
from PyQt6.QtCore import Qt, QEvent, QObject, QThread, QTimer, QSize, pyqtSignal
from PyQt6.QtGui import QMouseEvent, QPixmap, QImage, QFont
from PyQt6.QtGui import QMouseEvent, QPixmap, QImage, QFont, QIcon
import codecs
import io
import os
import subprocess
import qrcode
import re
from utils.wifi_manager import WifiManager
from utils.floating_keyboard import FloatingKeyboard
from utils.get_bootstrap_icon import get_colored_icon, get_colored_pixmap
class DragScrollArea(QScrollArea):
@@ -318,7 +320,15 @@ class SettingPage(QWidget):
def _styled_message(icon, parent, title, text, buttons=QMessageBox.StandardButton.Ok):
"""显示与整体风格一致的暗色主题消息框"""
msg = QMessageBox(parent)
msg.setIcon(icon)
if isinstance(icon, str):
if icon == "info":
msg.setIconPixmap(get_colored_pixmap("info-circle.svg", "#f8f8f8", 40, 40))
elif icon == "warning":
msg.setIconPixmap(get_colored_pixmap("exclamation-circle.svg", "#f8f804", 40, 40))
elif icon == "error":
msg.setIconPixmap(get_colored_pixmap("x-circle.svg", "#f80404", 40, 40))
else:
msg.setIcon(icon)
msg.setWindowTitle(title)
msg.setText(text)
msg.setStandardButtons(buttons)
@@ -332,8 +342,9 @@ class SettingPage(QWidget):
}
QMessageBox QLabel {
color: #f2f2f2;
font-size: 20px;
font-size: 30px;
padding: 10px;
background-color: #3f3f3f;
}
QMessageBox QPushButton {
min-width: 130px;
@@ -819,12 +830,12 @@ class SettingPage(QWidget):
if not ssid:
self.hotspot_toggle.setChecked(False)
self.hotspot_toggle.blockSignals(False)
self._styled_message(QMessageBox.Icon.Warning, self, "提示", "请输入热点名称")
self._styled_message("waring", self, "提示", "请输入热点名称")
return
if len(password) < 8:
self.hotspot_toggle.setChecked(False)
self.hotspot_toggle.blockSignals(False)
self._styled_message(QMessageBox.Icon.Warning, self, "提示", "密码至少需要8位")
self._styled_message("waring", self, "提示", "密码至少需要8位")
return
# 按钮UI反馈 → 显示"开启中……"
@@ -871,7 +882,7 @@ class SettingPage(QWidget):
self.hotspot_password.setEnabled(False)
self._generate_qr_code(ssid, self.hotspot_password.text().strip())
else:
self._styled_message(QMessageBox.Icon.Critical, self, "错误", "开启热点失败: wpa_cli 返回失败")
self._styled_message("error", self, "错误", "开启热点失败: wpa_cli 返回失败")
self.hotspot_toggle.blockSignals(True)
self.hotspot_toggle.setChecked(False)
self.hotspot_toggle.blockSignals(False)
@@ -879,7 +890,7 @@ class SettingPage(QWidget):
self.hotspot_toggle.setEnabled(True)
def _on_hotspot_open_error(self, err_msg):
self._styled_message(QMessageBox.Icon.Critical, self, "错误", f"开启热点失败: {err_msg}")
self._styled_message("error", self, "错误", f"开启热点失败: {err_msg}")
self.hotspot_toggle.blockSignals(True)
self.hotspot_toggle.setChecked(False)
self.hotspot_toggle.blockSignals(False)
@@ -904,7 +915,7 @@ class SettingPage(QWidget):
self.qr_label.clear()
self.qr_hint.setText("开启热点后自动生成二维码")
self.hotspot_toggle.setEnabled(True)
self._styled_message(QMessageBox.Icon.Warning, self, "提示", f"关闭热点时出现异常: {err_msg}")
self._styled_message("waring", self, "提示", f"关闭热点时出现异常: {err_msg}")
def _generate_qr_code(self, ssid, password):
"""生成 WiFi 二维码并显示"""
@@ -944,7 +955,9 @@ class SettingPage(QWidget):
power_layout.addStretch()
# 重启按钮
reboot_btn = QPushButton(" 重启系统")
reboot_btn = QPushButton(" 重启系统")
reboot_btn.setIcon(get_colored_icon("arrow-clockwise.svg", "#ffffff"))
reboot_btn.setIconSize(QSize(26, 26))
reboot_btn.setStyleSheet("""
QPushButton {
min-height: 70px;
@@ -955,6 +968,7 @@ class SettingPage(QWidget):
border: 2px solid #4a9fc8;
border-radius: 14px;
padding: 10px 24px;
text-align: middle;
}
QPushButton:hover {
background-color: #3a85b3;
@@ -971,7 +985,9 @@ class SettingPage(QWidget):
power_layout.addSpacing(20)
# 关机按钮
shutdown_btn = QPushButton(" 关机")
shutdown_btn = QPushButton(" 关机")
shutdown_btn.setIcon(get_colored_icon("power.svg", "#ffffff"))
shutdown_btn.setIconSize(QSize(26, 26))
shutdown_btn.setStyleSheet("""
QPushButton {
min-height: 70px;
@@ -982,6 +998,7 @@ class SettingPage(QWidget):
border: 2px solid #e74c3c;
border-radius: 14px;
padding: 10px 24px;
text-align: middle;
}
QPushButton:hover {
background-color: #e74c3c;
@@ -1007,7 +1024,7 @@ class SettingPage(QWidget):
)
if reply == QMessageBox.StandardButton.Yes:
self._styled_message(
QMessageBox.Icon.Information, self, "重启",
"info", self, "重启",
"系统正在重启..."
)
QTimer.singleShot(500, lambda: os.system("sudo reboot"))
@@ -1021,7 +1038,7 @@ class SettingPage(QWidget):
)
if reply == QMessageBox.StandardButton.Yes:
self._styled_message(
QMessageBox.Icon.Information, self, "关机",
"info", self, "关机",
"系统正在关机..."
)
QTimer.singleShot(500, lambda: os.system("sudo poweroff"))
@@ -1070,7 +1087,7 @@ class SettingPage(QWidget):
try:
saved_networks = self.wifi_manager.list_saved_networks()
except Exception as e:
self._styled_message(QMessageBox.Icon.Critical, self, "错误", f"无法加载保存的WiFi: {str(e)}")
self._styled_message("error", self, "错误", f"无法加载保存的WiFi: {str(e)}")
return
# 比较与上次缓存的网络列表是否有变化
@@ -1122,7 +1139,7 @@ class SettingPage(QWidget):
processed = self._deduplicate_networks(networks)
if not processed:
self._styled_message(QMessageBox.Icon.Information, self, "提示", "未扫描到可用网络")
self._styled_message("info", self, "提示", "未扫描到可用网络")
return
for network in processed:
@@ -1179,7 +1196,7 @@ class SettingPage(QWidget):
"""扫描出错后的UI恢复主线程中执行"""
self.scan_button.setEnabled(True)
self.scan_button.setText("扫描网络")
self._styled_message(QMessageBox.Icon.Critical, self, "错误", f"扫描网络失败: {error_msg}")
self._styled_message("error", self, "错误", f"扫描网络失败: {error_msg}")
def _on_ssid_text_changed(self, text):
"""SSID输入框文本变化时如果清空则重置为开放网络"""
@@ -1314,13 +1331,13 @@ class SettingPage(QWidget):
"""连接已保存列表中选中的网络(后台线程)"""
item = self.saved_wifi_list.currentItem()
if item is None:
self._styled_message(QMessageBox.Icon.Warning, self, "提示", "请先选择一个已保存网络")
self._styled_message("waring", self, "提示", "请先选择一个已保存网络")
return
network = item.data(Qt.ItemDataRole.UserRole) or {}
network_id = network.get("network_id")
ssid = network.get("ssid", "")
if network_id is None:
self._styled_message(QMessageBox.Icon.Warning, self, "提示", "选中网络无效")
self._styled_message("waring", self, "提示", "选中网络无效")
return
# 按钮UI反馈
@@ -1344,27 +1361,27 @@ class SettingPage(QWidget):
self.connect_saved_button.setEnabled(True)
self.connect_saved_button.setText("连接到此网络")
if ok:
self._styled_message(QMessageBox.Icon.Information, self, "成功", f"已连接: {ssid}")
self._styled_message("info", self, "成功", f"已连接: {ssid}")
else:
self._styled_message(QMessageBox.Icon.Critical, self, "错误", "连接失败")
self._styled_message("error", self, "错误", "连接失败")
self.refresh_saved_wifi()
self.refresh_current_status()
def _on_saved_connect_error(self, err_msg):
self.connect_saved_button.setEnabled(True)
self.connect_saved_button.setText("连接到此网络")
self._styled_message(QMessageBox.Icon.Critical, self, "错误", f"连接失败: {err_msg}")
self._styled_message("error", self, "错误", f"连接失败: {err_msg}")
def remove_selected_saved_wifi(self):
item = self.saved_wifi_list.currentItem()
if item is None:
self._styled_message(QMessageBox.Icon.Warning, self, "提示", "请先选择一个已保存网络")
self._styled_message("waring", self, "提示", "请先选择一个已保存网络")
return
network = item.data(Qt.ItemDataRole.UserRole) or {}
network_id = network.get("network_id")
ssid = network.get("ssid", "")
if network_id is None:
self._styled_message(QMessageBox.Icon.Warning, self, "提示", "选中网络无效,无法删除")
self._styled_message("waring", self, "提示", "选中网络无效,无法删除")
return
# 按钮UI反馈
@@ -1388,14 +1405,14 @@ class SettingPage(QWidget):
self.remove_saved_button.setEnabled(True)
self.remove_saved_button.setText("删除选中")
if ok:
self._styled_message(QMessageBox.Icon.Information, self, "成功", f"已删除网络: {ssid}")
self._styled_message("info", self, "成功", f"已删除网络: {ssid}")
self.refresh_saved_wifi()
self.refresh_current_status()
def _on_remove_error(self, err_msg):
self.remove_saved_button.setEnabled(True)
self.remove_saved_button.setText("删除选中")
self._styled_message(QMessageBox.Icon.Critical, self, "错误", f"删除失败: {err_msg}")
self._styled_message("error", self, "错误", f"删除失败: {err_msg}")
def connect_to_wifi(self):
ssid = self.ssid_input.text().strip()
@@ -1404,15 +1421,15 @@ class SettingPage(QWidget):
auth_mode = self.auth_combo.currentData()
if not ssid:
self._styled_message(QMessageBox.Icon.Warning, self, "警告", "WiFi名称不能为空")
self._styled_message("waring", self, "警告", "WiFi名称不能为空")
return
if auth_mode == "psk" and not password:
self._styled_message(QMessageBox.Icon.Warning, self, "警告", "WPA/WPA2 认证需要密码")
self._styled_message("waring", self, "警告", "WPA/WPA2 认证需要密码")
return
if auth_mode == "eap" and (not identity or not password):
self._styled_message(QMessageBox.Icon.Warning, self, "警告", "WPA-EAP 认证需要身份和密码")
self._styled_message("waring", self, "警告", "WPA-EAP 认证需要身份和密码")
return
# 按钮UI反馈
@@ -1436,16 +1453,16 @@ class SettingPage(QWidget):
self.connect_button.setEnabled(True)
self.connect_button.setText("连接")
if ok:
self._styled_message(QMessageBox.Icon.Information, self, "成功", f"已连接: {ssid}")
self._styled_message("info", self, "成功", f"已连接: {ssid}")
else:
self._styled_message(QMessageBox.Icon.Critical, self, "错误", "连接失败")
self._styled_message("error", self, "错误", "连接失败")
self.refresh_saved_wifi()
self.refresh_current_status()
def _on_connect_error(self, err_msg):
self.connect_button.setEnabled(True)
self.connect_button.setText("连接")
self._styled_message(QMessageBox.Icon.Critical, self, "错误", f"连接WiFi失败: {err_msg}")
self._styled_message("error", self, "错误", f"连接WiFi失败: {err_msg}")
def display_setting(self, index):
if index < 0:

View File

@@ -119,10 +119,11 @@ class TempGauge(QWidget):
p.drawText(44, 16, w - 44, 24, Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter,
f"{self._actual:.0f}°")
if self._target > 0:
tgt_y = bar_y + bar_h - int((bar_h - 4) * min(self._target / 300, 1))
font2 = QFont("sans-serif", 10)
p.setFont(font2)
p.setPen(QPen(QColor("#888888")))
p.drawText(44, 34, w - 44, 20, Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter,
p.drawText(44, tgt_y - 10, w - 44, 20, Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter,
f"{self._target:.0f}°")
font3 = QFont("sans-serif", 10, QFont.Weight.Bold)
@@ -134,9 +135,10 @@ class TempGauge(QWidget):
# ── 状态页面 ────────────────────────────────────────────
class StatusPage(QWidget):
def __init__(self, api_client, parent=None):
def __init__(self, api_client, GcodeViewer=None, parent=None):
super().__init__(parent)
self.api_client = api_client
self.gcode_viewer = GcodeViewer
self.file_name = "None"
self.progress = 0.0
@@ -283,15 +285,24 @@ class StatusPage(QWidget):
# ── 右侧预留区域 ─────────────────────────────
right_frame = QFrame()
right_frame.setStyleSheet("background-color: #3a3a3a; border-radius: 10px;")
right_layout = QVBoxLayout(right_frame)
right_layout.setContentsMargins(6, 6, 6, 6)
self.right_layout = QVBoxLayout(right_frame)
self.right_layout.setContentsMargins(6, 6, 6, 6)
self.gcode_viewer = GCodeViewerWidget()
right_layout.addWidget(self.gcode_viewer)
# self.gcode_viewer = GCodeViewerWidget()
if self.gcode_viewer is not None:
self.right_layout.addWidget(self.gcode_viewer)
# self.gcode_viewer.setUpdatesEnabled(False)
# self.gcode_viewer.hide()
main_layout.addWidget(left_frame, 2)
main_layout.addWidget(right_frame, 3)
# QTimer.singleShot(5000, self.init_gcode_viewer)
# def init_gcode_viewer(self):
# self.gcode_viewer = GCodeViewerWidget()
# self.right_layout.addWidget(self.gcode_viewer)
def update_status(self):
self.fresh_status_valve()