1
1
mirror of https://github.com/KenanZhu/AutoLibrary.git synced 2026-06-18 15:33:03 +08:00

refactor(gui): 编排窗口迁移至新包并移除旧的预览/编排对话框

This commit is contained in:
2026-05-18 11:15:35 +08:00
parent 33c0f4414c
commit 6cf182c8c8
12 changed files with 2468 additions and 1122 deletions
+534
View File
@@ -0,0 +1,534 @@
"""
Widget components for the AutoScript orchestration dialog.
"""
from PySide6.QtCore import Slot
from PySide6.QtWidgets import (
QComboBox,
QFrame,
QHBoxLayout,
QLabel,
QPushButton,
QSizePolicy,
QStackedWidget
)
from gui.ALAutoScriptOrchDialog._helpers import (
ACTION_TYPES,
ARITH_TYPES,
COMPARE_OPERATORS,
LOGIC_OPERATORS,
PRESET_VARIABLES,
VAR_TYPE_ORDER,
encodeValueStr,
getValueFromWidget,
isVarReference,
makeComboWidget,
makeLabel,
makeOffsetWidget,
makeValueWidget,
makeVarRefCombo,
setWidgetValue,
)
class ConditionRowFrame(QFrame):
def __init__(
self,
varMgr,
parentBlockIndex: int = 0,
isFirst: bool = False,
parent = None
):
super().__init__(parent)
self._varMgr = varMgr
self._blockIndex = parentBlockIndex
self._isFirst = isFirst
self._isBoolMode = False
self.setupUi()
self.connectSignals()
def setupUi(
self
):
self.setUpdatesEnabled(False)
self.setFrameShape(QFrame.StyledPanel)
self.setFrameShadow(QFrame.Raised)
self.setFixedHeight(32)
layout = QHBoxLayout(self)
layout.setContentsMargins(2, 2, 2, 2)
layout.setSpacing(4)
if self._isFirst:
self.logicCombo = None
else:
self.logicCombo = makeComboWidget(LOGIC_OPERATORS, min_width=110, parent=self)
layout.addWidget(self.logicCombo)
self.leftVarCombo = QComboBox(self)
self.leftVarCombo.setFixedHeight(25)
self.leftVarCombo.setMinimumWidth(120)
self.leftVarCombo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.populateLeftVarCombo()
layout.addWidget(self.leftVarCombo)
self.opCombo = makeComboWidget(COMPARE_OPERATORS, min_width=80, parent=self)
layout.addWidget(self.opCombo)
self._compTypeCombo = makeComboWidget([
("特定值", "literal"),
("变量", "variable"),
], min_width=70, parent=self)
layout.addWidget(self._compTypeCombo)
self._rhsStack = QStackedWidget(self)
self._rhsStack.setFixedHeight(25)
self._literalStack = QStackedWidget(self)
self._literalStack.setFixedHeight(25)
self._literalWidgets = {}
for vt in VAR_TYPE_ORDER:
w = makeValueWidget(vt, self._literalStack)
self._literalWidgets[vt] = w
self._literalStack.addWidget(w)
self._literalStack.setCurrentWidget(self._literalWidgets.get("String"))
self._rhsStack.addWidget(self._literalStack)
self.rhsVarCombo = makeVarRefCombo(self)
self._rhsStack.addWidget(self.rhsVarCombo)
self._rhsStack.setCurrentIndex(0)
layout.addWidget(self._rhsStack)
if not self._isFirst:
self.deleteBtn = QPushButton("×", self)
self.deleteBtn.setFixedSize(25, 25)
self.deleteBtn.setStyleSheet("color: red; font-weight: bold;")
layout.addWidget(self.deleteBtn)
else:
self.deleteBtn = None
layout.addStretch()
self.setUpdatesEnabled(True)
def populateLeftVarCombo(
self
):
self._varMgr.populateCombo(self.leftVarCombo)
def populateRhsVarCombo(
self
):
self._varMgr.populateCombo(self.rhsVarCombo)
def connectSignals(
self
):
self.leftVarCombo.currentIndexChanged.connect(self.onLeftVarChanged)
self._compTypeCombo.currentIndexChanged.connect(self.onCompTypeChanged)
@Slot(int)
def onLeftVarChanged(
self,
idx
):
if idx < 0:
return
data = self.leftVarCombo.itemData(idx)
if not data:
return
_, vartype = data
self.updateRhsLiteralWidget(vartype)
def updateRhsLiteralWidget(
self,
vartype: str
):
if vartype not in self._literalWidgets:
vartype = "String"
self._literalStack.setCurrentWidget(self._literalWidgets[vartype])
@Slot(int)
def onCompTypeChanged(
self,
idx
):
isVar = (self._compTypeCombo.currentData() == "variable")
self._rhsStack.setCurrentIndex(1 if isVar else 0)
if isVar:
self.populateRhsVarCombo()
def getLogic(
self
) -> str:
return self.logicCombo.currentData() if self.logicCombo else ""
def toConditionText(
self
) -> str:
data = self.leftVarCombo.currentData()
if not data:
return ""
name, vartype = data
opSym = self.opCombo.currentData()
isVarRef = (self._compTypeCombo.currentData() == "variable")
if isVarRef:
rd = self.rhsVarCombo.currentData()
if rd:
rhsName = rd[0]
return f"{name} {opSym} {rhsName}"
rhsText = self.rhsVarCombo.currentText().strip()
if rhsText:
return f"{name} {opSym} {rhsText}"
return ""
w = self._literalWidgets.get(vartype)
if w:
rawVal = getValueFromWidget(w)
encoded = encodeValueStr(rawVal, vartype)
return f"{name} {opSym} {encoded}"
return ""
def loadFromParts(
self,
operandName: str,
opSym: str,
valueExpr: str
):
for ci in range(self.leftVarCombo.count()):
d = self.leftVarCombo.itemData(ci)
if d and d[0] == operandName:
self.leftVarCombo.setCurrentIndex(ci)
break
if opSym:
for oi in range(self.opCombo.count()):
if self.opCombo.itemData(oi) == opSym:
self.opCombo.setCurrentIndex(oi)
break
if not valueExpr:
return
up = valueExpr.strip().upper()
data = self.leftVarCombo.currentData()
vartype = data[1] if data else "String"
if isVarReference(valueExpr) or self._isKnownVar(up):
self._compTypeCombo.setCurrentIndex(1)
self.populateRhsVarCombo()
found = self._varMgr.findExactNameEntry(self.rhsVarCombo, up)
if found >= 0:
self.rhsVarCombo.setCurrentIndex(found)
else:
self.rhsVarCombo.addItem(up, (up, "String"))
self.rhsVarCombo.setCurrentIndex(self.rhsVarCombo.count() - 1)
else:
self._compTypeCombo.setCurrentIndex(0)
w = self._literalWidgets.get(vartype)
if w:
setWidgetValue(w, vartype, valueExpr)
def _isKnownVar(
self,
name: str
) -> bool:
return self._varMgr.getInfoByName(name) is not None
def refreshVarCombos(
self
):
self.populateLeftVarCombo()
self.populateRhsVarCombo()
class ActionStepFrame(QFrame):
def __init__(
self,
varMgr,
parentBlockIndex: int = 0,
parent = None
):
super().__init__(parent)
self._varMgr = varMgr
self._blockIndex = parentBlockIndex
self._currentTargetType = "String"
self.setupUi()
self.connectSignals()
def setupUi(
self
):
self.setUpdatesEnabled(False)
self.setFrameShape(QFrame.StyledPanel)
self.setFrameShadow(QFrame.Raised)
self.setFixedHeight(35)
layout = QHBoxLayout(self)
layout.setContentsMargins(2, 2, 2, 2)
layout.setSpacing(4)
self.opTypeCombo = makeComboWidget(ACTION_TYPES, min_width=70, parent=self)
layout.addWidget(self.opTypeCombo)
layout.addWidget(makeLabel("设置", self))
self.targetCombo = QComboBox(self)
self.targetCombo.setFixedHeight(25)
self.targetCombo.setMinimumWidth(120)
self.buildTargetCombo()
layout.addWidget(self.targetCombo)
layout.addWidget(makeLabel("", self))
self._valueSrcCombo = makeComboWidget([
("特定值", "literal"),
("变量", "variable"),
], min_width=70, parent=self)
layout.addWidget(self._valueSrcCombo)
self._valueStack = QStackedWidget(self)
self._valueStack.setFixedHeight(25)
self.initValueStacks()
layout.addWidget(self._valueStack)
self.existingVarCombo = makeVarRefCombo(self)
self.existingVarCombo.setVisible(False)
layout.addWidget(self.existingVarCombo)
self.deleteBtn = QPushButton("×", self)
self.deleteBtn.setFixedSize(25, 25)
self.deleteBtn.setStyleSheet("color: red; font-weight: bold;")
layout.addWidget(self.deleteBtn)
self.setUpdatesEnabled(True)
def buildTargetCombo(
self
):
self.targetCombo.blockSignals(True)
self.targetCombo.clear()
for p in PRESET_VARIABLES:
if p["name"] in ("CURRENT_TIME", "CURRENT_DATE"):
continue
info = self._varMgr.getInfoByName(p["name"])
if info:
self.targetCombo.addItem(
info["display"],
(info["name"], info["type"])
)
self.targetCombo.blockSignals(False)
def initValueStacks(
self
):
self._literalWidgets = {}
self._offsetWidgets = {}
for vt in VAR_TYPE_ORDER:
self._literalWidgets[vt] = makeValueWidget(vt, self._valueStack)
self._valueStack.addWidget(self._literalWidgets[vt])
if vt in ARITH_TYPES:
self._offsetWidgets[vt] = makeOffsetWidget(vt, self._valueStack)
self._valueStack.addWidget(self._offsetWidgets[vt])
else:
lbl = QLabel("(不支持该操作)", self._valueStack)
lbl.setFixedHeight(25)
self._offsetWidgets[vt] = lbl
self._valueStack.addWidget(lbl)
def connectSignals(
self
):
self.opTypeCombo.currentIndexChanged.connect(self.onOpTypeChanged)
self.targetCombo.currentIndexChanged.connect(self.onTargetChanged)
self._valueSrcCombo.currentIndexChanged.connect(self.onValueSrcChanged)
@Slot(int)
def onTargetChanged(
self,
idx
):
if idx < 0:
return
data = self.targetCombo.itemData(idx)
if not data:
return
_, vartype = data
self._currentTargetType = vartype
self.updateRHSWidget()
self.onValueSrcChanged(self._valueSrcCombo.currentIndex())
@Slot(int)
def onOpTypeChanged(
self,
idx
):
self.updateRHSWidget()
def updateRHSWidget(
self
):
op = self.opTypeCombo.currentData()
isArith = (op in ("add", "sub"))
actualType = self._currentTargetType
if isArith and actualType in self._offsetWidgets:
self._valueStack.setCurrentWidget(self._offsetWidgets[actualType])
elif actualType in self._literalWidgets:
self._valueStack.setCurrentWidget(self._literalWidgets[actualType])
else:
self._valueStack.setCurrentWidget(self._literalWidgets.get("String"))
@Slot(int)
def onValueSrcChanged(
self,
idx
):
isVar = (self._valueSrcCombo.currentData() == "variable")
self._valueStack.setVisible(not isVar)
self.existingVarCombo.setVisible(isVar)
if isVar:
self._varMgr.populateCombo(self.existingVarCombo)
else:
self.updateRHSWidget()
def getTargetName(
self
) -> str:
data = self.targetCombo.currentData()
return data[0] if data else ""
def toScriptLine(
self
) -> str:
target = self.getTargetName()
if not target:
return ""
op = self.opTypeCombo.currentData()
rawVal = self._getValueRaw()
if op == "set":
vartype = self._currentTargetType
encoded = encodeValueStr(rawVal, vartype)
if vartype == "Time":
if rawVal.startswith("+"):
return f" {target} .ADD. {rawVal[1:]}"
if rawVal.startswith("-"):
return f" {target} .SUB. {rawVal[1:]}"
return f" SET {target} = {encoded}"
elif op == "add":
vartype = self._currentTargetType
if vartype == "Date" and hasattr(self._valueStack.currentWidget(), "getOffsetDays"):
days = self._valueStack.currentWidget().getOffsetDays()
return f" {target} .ADD. {days}"
if vartype == "Time" and hasattr(self._valueStack.currentWidget(), "getOffsetHours"):
hours = self._valueStack.currentWidget().getOffsetHours()
return f" {target} .ADD. {hours}"
return f" {target} .ADD. {rawVal}"
elif op == "sub":
vartype = self._currentTargetType
if vartype == "Date" and hasattr(self._valueStack.currentWidget(), "getOffsetDays"):
days = self._valueStack.currentWidget().getOffsetDays()
return f" {target} .SUB. {days}"
if vartype == "Time" and hasattr(self._valueStack.currentWidget(), "getOffsetHours"):
hours = self._valueStack.currentWidget().getOffsetHours()
return f" {target} .SUB. {hours}"
return f" {target} .SUB. {rawVal}"
return ""
def _getValueRaw(
self
) -> str:
if self._valueSrcCombo.currentData() == "variable":
return self.existingVarCombo.currentText().strip()
w = self._valueStack.currentWidget()
if w:
return getValueFromWidget(w)
return ""
def setOpType(
self,
opType: str
):
for i in range(self.opTypeCombo.count()):
if self.opTypeCombo.itemData(i) == opType:
self.opTypeCombo.setCurrentIndex(i)
break
def loadFromScript(
self,
targetVar: str,
valueExpr: str
):
targetUp = targetVar.upper().strip()
for ci in range(self.targetCombo.count()):
d = self.targetCombo.itemData(ci)
if d and d[0] == targetUp:
self.targetCombo.setCurrentIndex(ci)
break
self._setValueFromExpr(valueExpr)
def _setValueFromExpr(
self,
expr: str
):
s = expr.strip()
if not s:
return
up = s.upper()
if isVarReference(s):
self._valueSrcCombo.setCurrentIndex(1)
self._varMgr.populateCombo(self.existingVarCombo)
idx = self._varMgr.findExactNameEntry(self.existingVarCombo, up)
if idx >= 0:
self.existingVarCombo.setCurrentIndex(idx)
else:
self.existingVarCombo.addItem(up, (up, "String"))
self.existingVarCombo.setCurrentIndex(self.existingVarCombo.count() - 1)
else:
self._valueSrcCombo.setCurrentIndex(0)
w = self._valueStack.currentWidget()
if w:
setWidgetValue(w, self._currentTargetType, expr)
def refreshVarCombos(
self
):
currentData = self.targetCombo.currentData()
self.buildTargetCombo()
if currentData:
for i in range(self.targetCombo.count()):
d = self.targetCombo.itemData(i)
if d and d[0] == currentData[0]:
self.targetCombo.setCurrentIndex(i)
break
self._varMgr.populateCombo(self.existingVarCombo)