TSI_Config/tmrrelayassociation.cpp

341 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "tmrrelayassociation.h"
#include "ui_tmrrelayassociation.h"
#include "vibrationdata.h"
#include <QStack>
#include <QMenu>
TMRRelayAssociation::TMRRelayAssociation(int slot,int cardtype,QWidget *parent)
: QDialog(parent)
, ui(new Ui::TMRRelayAssociation)
{
ui->setupUi(this);
slot_no = slot;
car_type = static_cast<CardType>(cardtype);
ui->label_slot_no->setText(QString::number(slot_no));
QVBoxLayout *layout_available = new QVBoxLayout(ui->widget_available);
list_widget_available = new DraggableListWidget;
layout_available->addWidget(list_widget_available);
list_widget_available->setDragEnabled(true);
QVBoxLayout *layout_relay = new QVBoxLayout(ui->widget_relay);
treeView_relay = new QTreeView;
layout_relay->addWidget(treeView_relay);
treeView_relay->setDragEnabled(true); // 启用拖动
treeView_relay->setAcceptDrops(true); // 接受放下
treeView_relay->setDropIndicatorShown(true); // 显示放置指示器
treeView_relay->setDragDropMode(QAbstractItemView::DropOnly);
model_Relay = new DropTreeModel(this); //创建模型指定父类
treeView_relay->setModel(model_Relay);
treeView_relay->setHeaderHidden(true);
btnGroup_slot = new QButtonGroup(this);
btnGroup_slot->addButton(ui->pushButton_slot1);
btnGroup_slot->addButton(ui->pushButton_slot2);
btnGroup_slot->addButton(ui->pushButton_slot3);
btnGroup_slot->addButton(ui->pushButton_slot4);
btnGroup_slot->addButton(ui->pushButton_slot5);
btnGroup_slot->addButton(ui->pushButton_slot6);
btnGroup_slot->addButton(ui->pushButton_slot7);
btnGroup_slot->addButton(ui->pushButton_slot8);
btnGroup_slot->addButton(ui->pushButton_slot9);
btnGroup_slot->addButton(ui->pushButton_slot10);
btnGroup_slot->addButton(ui->pushButton_slot11);
btnGroup_slot->addButton(ui->pushButton_slot12);
btnGroup_slot->addButton(ui->pushButton_slot13);
btnGroup_slot->addButton(ui->pushButton_slot14);
btnGroup_slot->addButton(ui->pushButton_slot15);
btnGroup_slot->addButton(ui->pushButton_slot16);
connect(btnGroup_slot, SIGNAL(buttonClicked(QAbstractButton *)), this, SLOT(OnButtonGroup(QAbstractButton *)));
connect(ui->comboBox_relay_ch, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &TMRRelayAssociation::onComboBoxIndexChanged);
treeView_relay->setContextMenuPolicy(Qt::CustomContextMenu);
connect(treeView_relay,&QTreeView::customContextMenuRequested,this,&TMRRelayAssociation::on_treeView_Relay_customContextMenuRequested);
Init();
current_index = ui->comboBox_relay_ch->currentIndex();
// QString expr = "((S01C01A1 + S01C02A1 + (S02C01A1 * S02C01A2)) * (S02C01A2 + S02C01A1 + (S02C01A1 + S02C01A2)) * (S02C01A1 * S02C01A2))";
// setExpressionToTreeView(treeView_relay, expr);
}
TMRRelayAssociation::~TMRRelayAssociation()
{
delete ui;
}
void TMRRelayAssociation::Init(){
}
ExprNode* TMRRelayAssociation::parseExpression(const QString& expr, int& pos) {
auto skipSpaces = [&]() {
while (pos < expr.length() && expr[pos].isSpace()) pos++;
};
QStack<ExprNode*> nodeStack;
QStack<QString> opStack;
while (pos < expr.length()) {
skipSpaces();
if (pos >= expr.length()) break;
QChar ch = expr[pos];
if (ch == '(') {
pos++;
nodeStack.push(parseExpression(expr, pos));
} else if (ch == ')') {
pos++;
break;
} else if (ch == '+' || ch == '*') {
opStack.push(QString(ch));
pos++;
} else {
QString token;
while (pos < expr.length() && expr[pos].isLetterOrNumber()) {
token += expr[pos++];
}
nodeStack.push(new ExprNode{token, {}});
}
while (opStack.size() > 0 && nodeStack.size() >= 2) {
QString op = opStack.pop();
ExprNode* right = nodeStack.pop();
ExprNode* left = nodeStack.pop();
if (left->value == op) {
left->children.append(right);
nodeStack.push(left);
} else if (right->value == op) {
right->children.prepend(left);
nodeStack.push(right);
} else {
ExprNode* parent = new ExprNode{op, {left, right}};
nodeStack.push(parent);
}
}
}
return nodeStack.isEmpty() ? nullptr : nodeStack.top();
}
QStandardItem* TMRRelayAssociation::buildItemTree(ExprNode* node) {
if (!node) return nullptr;
QStandardItem* item = new QStandardItem(node->value);
for (ExprNode* child : node->children) {
item->appendRow(buildItemTree(child));
}
return item;
}
void TMRRelayAssociation::setExpressionToTreeView(QTreeView* treeView, const QString& expr) {
int pos = 0;
ExprNode* root = parseExpression(expr, pos);
QStandardItem* rootItem = buildItemTree(root);
QStandardItemModel* model = new QStandardItemModel();
model->appendRow(rootItem);
treeView->setModel(model);
treeView->expandAll();
}
QString TMRRelayAssociation::buildLogicExpression(QStandardItem *item) {
if (!item) return "";
int childCount = item->rowCount();
QString text = item->text().trimmed();
if (childCount == 0) {
// 叶子节点,直接返回表达式,比如 S01C01A1
return text;
}
// 判断当前是 +OR还是 *AND
QString opStr = (text == "+") ? "+" :
(text == "*") ? "*" : "";
// 如果不是 +/*,视为叶子节点
if (opStr.isEmpty()) {
return text;
}
QStringList subExprs;
for (int i = 0; i < childCount; ++i) {
QStandardItem *child = item->child(i);
subExprs << buildLogicExpression(child);
}
return "(" + subExprs.join(" " + opStr + " ") + ")";
}
QStandardItem* TMRRelayAssociation::parseExpression(const QString &expr) {
QStack<QStandardItem*> stack; // 用来存储节点
QStack<QString> ops; // 用来存储操作符
int pos = 0;
int length = expr.length();
while (pos < length) {
QRegExp regex("(\\()|([A-Za-z0-9]+)|([+*])|(\\))");
if (regex.indexIn(expr, pos) != -1) {
QString matchedText = regex.cap(0);
QString group1 = regex.cap(1); // (
QString group2 = regex.cap(2); // S01C01A1
QString group3 = regex.cap(3); // + or *
QString group4 = regex.cap(4); // )
// 处理左括号,表示子表达式的开始
if (!group1.isEmpty()) {
ops.push("("); // 推入栈
}
// 处理右括号,表示子表达式的结束
else if (!group4.isEmpty()) {
// 遇到右括号时开始弹出栈中的操作符,直到遇到左括号
while (!ops.isEmpty() && ops.top() != "(") {
QString op = ops.pop();
QStandardItem* right = stack.pop();
QStandardItem* left = stack.pop();
QStandardItem* node = new QStandardItem(op);
node->appendRow(left); // 左子树
node->appendRow(right); // 右子树
stack.push(node); // 将新的节点推入栈
}
ops.pop(); // 弹出左括号
}
// 处理操作符 + 和 *
else if (!group3.isEmpty()) {
ops.push(group3); // 操作符入栈
}
// 处理终端元素(比如 S01C01A1
else if (!group2.isEmpty()) {
QStandardItem* item = new QStandardItem(group2);
stack.push(item); // 将数据节点推入栈
}
pos = regex.pos(0) + regex.matchedLength();
} else {
break; // 防止无限循环
}
}
// 最终合并栈中的所有内容
while (!ops.isEmpty()) {
QString op = ops.pop();
QStandardItem* right = stack.pop();
QStandardItem* left = stack.pop();
QStandardItem* node = new QStandardItem(op);
node->appendRow(left); // 左子树
node->appendRow(right); // 右子树
stack.push(node);
}
// 返回栈顶的节点,应该是根节点
return stack.isEmpty() ? nullptr : stack.pop();
}
void TMRRelayAssociation::buildTreeFromExpression(QTreeView *treeView, const QString &expr) {
QStandardItemModel* model = new QStandardItemModel();
QStandardItem* rootItem = parseExpression(expr);
if (rootItem) {
model_Relay->appendRow(rootItem);
}
treeView_relay->setModel(model_Relay);
}
void TMRRelayAssociation::OnButtonGroup(QAbstractButton *slot_btn) {
if (slot_btn != NULL) {
list_widget_available->clear();
QString object_name = slot_btn->objectName();
qDebug() << object_name ;
int button_id = object_name.right(object_name.length() - 15).toInt();
std::shared_ptr<CardBase> base_ptr = ConfigMgr::Instance()->GetSlotPtr(button_id);
std::shared_ptr<VibrationData> ptr = std::dynamic_pointer_cast<VibrationData>(base_ptr);
for(int var = 0; var < CHANNEL_COUNT ; ++var){
if(ptr->alert_danger[var].direct_enable ||
ptr->alert_danger[var].x1_ampl_enable ||
ptr->alert_danger[var].x2_ampl_enable){
QString item_str = QString("S%1C%2A1 (槽位 %3 通道 %4 警报)").arg(QString::number(button_id, 10).rightJustified(2, '0')).arg(QString::number(var+1, 10).rightJustified(2, '0')).arg(button_id).arg(var+1);
QListWidgetItem *item = new QListWidgetItem(item_str);
QString item_data = QString("S%1C%2A1").arg(QString::number(button_id, 10).rightJustified(2, '0')).arg(QString::number(var+1, 10).rightJustified(2, '0'));
item->setData(Qt::UserRole, item_data);
list_widget_available->addItem(item);
}
if(ptr->alert_danger[var].danger_enable){
QString item_str = QString("S%1C%2A2 (槽位 %3 通道 %4 危险)").arg(QString::number(button_id, 10).rightJustified(2, '0')).arg(QString::number(var+1, 10).rightJustified(2, '0')).arg(button_id).arg(var+1);
QListWidgetItem *item = new QListWidgetItem(item_str);
QString item_data = QString("S%1C%2A2").arg(QString::number(button_id, 10).rightJustified(2, '0')).arg(QString::number(var+1, 10).rightJustified(2, '0'));
item->setData(Qt::UserRole, item_data);
list_widget_available->addItem(item);
}
}
QString item_str = QString("*");
QListWidgetItem *item_or = new QListWidgetItem("*");
item_or->setData(Qt::UserRole, "*");
list_widget_available->addItem(item_or);
QListWidgetItem *item_and = new QListWidgetItem("+");
item_and->setData(Qt::UserRole, "+");
list_widget_available->addItem(item_and);
}
}
void TMRRelayAssociation::on_pushButton_cancel_clicked()
{
this->close();
}
void TMRRelayAssociation::on_pushButton_confirm_clicked()
{
QStandardItemModel *model = qobject_cast<QStandardItemModel *>(treeView_relay->model());
if (!model) return;
QStandardItem *root = model->invisibleRootItem();
QString finalExpr;
for (int i = 0; i < root->rowCount(); ++i) {
QStandardItem *topItem = root->child(i);
QString expr = buildLogicExpression(topItem);
if (!finalExpr.isEmpty()) {
finalExpr += " OR ";
}
finalExpr += expr;
}
qDebug() << "逻辑表达式:" << finalExpr;
this->close();
}
void TMRRelayAssociation::onComboBoxIndexChanged(int index){
}
void TMRRelayAssociation::on_pushButton_and_clicked()
{
}
void TMRRelayAssociation::on_pushButton_or_clicked()
{
}
void TMRRelayAssociation::slotDeleteItem()
{
QModelIndex curIndex = treeView_relay->currentIndex();
if(curIndex.isValid()){
model_Relay->removeRow(curIndex.row(),curIndex.parent());
}
}
void TMRRelayAssociation::on_treeView_Relay_customContextMenuRequested(const QPoint &pos)
{
qDebug() << "on_treeView_Relay_customContextMenuRequested" <<endl;
QModelIndex curIndex = treeView_relay->indexAt(pos); //当前点击的元素的index
QModelIndex index = curIndex.sibling(curIndex.row(),0); //该行的第1列元素的index
QMenu menu(this);
if (index.isValid()){
//添加一行菜单,进行展开
menu.addAction(QStringLiteral("删除"), this, SLOT(slotDeleteItem()));
menu.addSeparator(); //添加一个分隔线
}
menu.exec(QCursor::pos()); //显示菜单
}