1
1
mirror of https://github.com/KenanZhu/AutoLibrary.git synced 2026-06-18 07:23:03 +08:00
Files
AutoLibrary/src/gui/ALAutoScriptOrchDialog/_blocks.py
T

273 lines
7.2 KiB
Python

"""
Conditional block widget for the AutoScript orchestration dialog.
"""
from PySide6.QtCore import Slot
from PySide6.QtWidgets import (
QComboBox,
QGroupBox,
QHBoxLayout,
QLabel,
QPushButton,
QSizePolicy,
QVBoxLayout,
QWidget,
)
from gui.ALAutoScriptOrchDialog._widgets import (
ActionStepFrame,
ConditionRowFrame,
)
class ConditionalBlock(QGroupBox):
def __init__(
self,
blockIndex: int,
varMgr = None,
parent = None
):
super().__init__(parent)
self.blockIndex = blockIndex
self._varMgr = varMgr
self._actionWidgets = []
self._conditionRows = []
self.setupUi()
self.connectSignals()
self.addInitialConditionRow()
def setupUi(
self
):
self.setUpdatesEnabled(False)
self.setStyleSheet(
"QGroupBox { font-weight: bold; border: 1px solid #ccc; "
"margin-top: 5px; padding-top: 5px; }"
)
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
mainLayout = QVBoxLayout(self)
mainLayout.setSpacing(6)
mainLayout.setContentsMargins(8, 8, 8, 8)
headerLayout = QHBoxLayout()
headerLayout.setSpacing(8)
self.typeCombo = QComboBox(self)
self.typeCombo.addItem("IF", "IF")
self.typeCombo.addItem("ELSE IF", "ELSE IF")
self.typeCombo.addItem("ELSE", "ELSE")
self.typeCombo.setFixedHeight(25)
if self.blockIndex == 0:
self.typeCombo.setEnabled(False)
headerLayout.addWidget(QLabel("类型:", self))
headerLayout.addWidget(self.typeCombo)
headerLayout.addStretch()
self.deleteBlockBtn = QPushButton("删除此块", self)
self.deleteBlockBtn.setStyleSheet("color: red;")
self.deleteBlockBtn.setFixedHeight(25)
headerLayout.addWidget(self.deleteBlockBtn)
mainLayout.addLayout(headerLayout)
self.conditionWidget = QWidget(self)
self.conditionWidget.setSizePolicy(
QSizePolicy.Preferred, QSizePolicy.Preferred
)
condLayout = QVBoxLayout(self.conditionWidget)
condLayout.setContentsMargins(4, 4, 4, 4)
condLayout.setSpacing(6)
self.condRowsLayout = QVBoxLayout()
self.condRowsLayout.setSpacing(4)
condLayout.addLayout(self.condRowsLayout)
self.addCondBtn = QPushButton("+ 添加条件", self.conditionWidget)
self.addCondBtn.setFixedHeight(25)
condLayout.addWidget(self.addCondBtn)
mainLayout.addWidget(self.conditionWidget)
self.actionLabel = QLabel("执行步骤:", self)
self.actionLabel.setFixedHeight(25)
mainLayout.addWidget(self.actionLabel)
self.actionsLayout = QVBoxLayout()
self.actionsLayout.setSpacing(4)
mainLayout.addLayout(self.actionsLayout)
self.addActionBtn = QPushButton("+ 添加执行步骤", self)
self.addActionBtn.setFixedHeight(25)
mainLayout.addWidget(self.addActionBtn)
self.setUpdatesEnabled(True)
def connectSignals(
self
):
self.typeCombo.currentIndexChanged.connect(self.onTypeChanged)
self.addCondBtn.clicked.connect(self.addConditionRow)
self.addActionBtn.clicked.connect(self.addActionStep)
def addInitialConditionRow(
self
):
row = ConditionRowFrame(
self._varMgr, self.blockIndex,
isFirst=True, parent=self
)
self._conditionRows.append(row)
self.condRowsLayout.addWidget(row)
def addConditionRow(
self
):
row = ConditionRowFrame(
self._varMgr, self.blockIndex,
isFirst=False, parent=self
)
row.deleteBtn.clicked.connect(lambda: self.removeConditionRow(row))
self._conditionRows.append(row)
self.condRowsLayout.addWidget(row)
def removeConditionRow(
self,
row: ConditionRowFrame
):
if row in self._conditionRows and len(self._conditionRows) > 1:
self._conditionRows.remove(row)
self.condRowsLayout.removeWidget(row)
row.hide()
row.deleteLater()
def addActionStep(
self
):
step = ActionStepFrame(self._varMgr, self.blockIndex, parent=self)
step.deleteBtn.clicked.connect(lambda: self.removeActionStep(step))
self._actionWidgets.append(step)
self.actionsLayout.addWidget(step)
def removeActionStep(
self,
step: ActionStepFrame
):
if step in self._actionWidgets:
self._actionWidgets.remove(step)
self.actionsLayout.removeWidget(step)
step.hide()
step.deleteLater()
@Slot(int)
def onTypeChanged(
self,
_idx
):
isCond = self.typeCombo.currentData() in ("IF", "ELSE IF")
self.conditionWidget.setVisible(isCond)
self.actionLabel.setText(
"执行步骤:" if isCond else "ELSE 执行步骤:"
)
def getBlockType(
self
) -> str:
return self.typeCombo.currentData()
def getConditionRows(
self
):
return list(self._conditionRows)
def getActionSteps(
self
):
return list(self._actionWidgets)
def countActionSteps(
self
) -> int:
return len(self._actionWidgets)
def toScriptLines(
self
) -> list:
blockType = self.getBlockType()
lines = []
if blockType in ("IF", "ELSE IF"):
condTexts = [
r.toConditionText() for r in self._conditionRows if r.toConditionText()
]
if not condTexts:
condTexts = [".TRUE."]
if len(condTexts) == 1:
combined = condTexts[0]
else:
parts = []
for i, ct in enumerate(condTexts):
if i > 0:
logic = self._conditionRows[i].getLogic() or ".AND."
parts.append(f" {logic} ")
parts.append(f"({ct})")
combined = "".join(parts)
if blockType == "IF":
lines.append(f"IF({combined}) THEN")
else:
lines.append(f"ELSE IF({combined}) THEN")
else:
lines.append("ELSE")
for step in self._actionWidgets:
scriptLine = step.toScriptLine()
if scriptLine:
lines.append(scriptLine)
return lines
def refreshVarCombos(
self
):
for row in self._conditionRows:
row.refreshVarCombos()
for step in self._actionWidgets:
step.refreshVarCombos()
def setPrevBlockType(
self,
prevType: str | None
):
model = self.typeCombo.model()
if model is None:
return
for data in ("ELSE IF", "ELSE"):
idx = self.typeCombo.findData(data)
if idx < 0:
continue
item = model.item(idx)
shouldEnable = prevType != "ELSE"
item.setEnabled(shouldEnable)
if prevType == "ELSE" and self.typeCombo.currentData() in ("ELSE IF", "ELSE"):
self.typeCombo.setCurrentIndex(0)