#include "PhysicsWidget.h" #include "MainWindow/MainWindow.h" #include "DataProperty/modelTreeItemType.h" #include "DialogCreatePhysicsModel.h" #include "ConfigOptions/ProjectTreeConfig.h" #include "ModelData/modelDataSingleton.h" #include "ModelData/modelDataBase.h" #include #include #include #include #include #include #include #include #include #include "ProjectTree/ProjectTreeWithBasicNode.h" #include "QApplication" #include "QFileDialog" #include "Settings/BusAPI.h" #include "ConfigOptions/ConfigOptions.h" #include "ConfigOptions/GlobalConfig.h" #include "ProjectTreeExtend/ProjectTreeExtend.h" #include "DialogCreateMaterial.h" #include "Material/MaterialSingletion.h" #include "Material/Material.h" #include "PythonModule/PyAgent.h" #include #include "PropertyTable.h" #include "IO/ProjectTemplete.h" #include "ProjectTreeFactory.h" #include "Common/Types.h" namespace MainWidget { int PhysicsWidget::CurrentID = -1; PhysicsWidget::PhysicsWidget(GUI::MainWindow *mainwindow, QWidget *parent) : _mainWindow(mainwindow) { Q_UNUSED(parent) _materialRoot = new QTreeWidgetItem(this, TreeItemType::MaterialRoot); // 材料 _materialRoot->setText(0, tr("Materials")); _materialRoot->setIcon(0, QIcon(":/QUI/icon/material.png")); _physicsModelRoot = new QTreeWidgetItem(this, TreeItemType::PhyaicsModelRoot); // 算例处理节点 _physicsModelRoot->setText(0, tr("Case")); _physicsModelRoot->setIcon(0, QIcon(":/QUI/icon/physics.png")); this->addTopLevelItem(_materialRoot); this->addTopLevelItem(_physicsModelRoot); init(); connect(this, SIGNAL(endaleGraphWinKey(bool)), _mainWindow, SIGNAL(enableGraphWindowKeyBoard(bool))); setStyleSheet("QTreeWidget::item{height:20px;}"); } PhysicsWidget::~PhysicsWidget() { this->clearData(); this->clear(); } int PhysicsWidget::getCurrentProjectID() { return CurrentID; } void PhysicsWidget::clearData() { QList trees = _idTreeHash.values(); for (int i = 0; i < trees.size(); ++i) { delete trees.at(i); } _idTreeHash.clear(); } void PhysicsWidget::init() { this->setHeaderHidden(true); ///注册了TreeWidget 左键单击 connect(this, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(singleClicked(QTreeWidgetItem *, int))); ///注册了TreeWidget 左键双击 connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(doubleClicked(QTreeWidgetItem *, int))); ///注册鼠标事件传递通知给mainWindow connect(this, SIGNAL(mouseEvent(int, QTreeWidgetItem *, int)), _mainWindow, SIGNAL(treeMouseEvent(int, QTreeWidgetItem *, int))); ///注册由mainWindow传递通知过来更新树 connect(_mainWindow, SIGNAL(updatePhysicsTreeSignal()), this, SLOT(updateTree())); /*鼠标事件 */ connect(_mainWindow, SIGNAL(treeMouseEvent(int, QTreeWidgetItem *, int)), this, SLOT(on_TreeMouseEvent(int, QTreeWidgetItem *, int))); /*创建物理模型 */ connect(_mainWindow, SIGNAL(createPhysiceModelSig()), this, SLOT(createPhysicsModel())); /*显示属性窗口 */ connect(this, SIGNAL(disPlayProp(DataProperty::DataBase *)), _mainWindow, SIGNAL(updateProperty(DataProperty::DataBase *))); // 求解 connect(this, SIGNAL(solveProject(int)), _mainWindow, SLOT(solveProject(int))); connect(this, SIGNAL(updateActionStates()), _mainWindow, SIGNAL(updateActionStatesSig())); connect(_mainWindow, SIGNAL(updateMaterialTreeSig()), this, SLOT(updateMaterialTree())); connect(this, SIGNAL(updatePhysicsTreePySig()), this, SLOT(updatePhysicsTree())); // connect(this, SIGNAL(deleteCaseSig(int)), this, SLOT(deleteCase(int))); connect(this, SIGNAL(importProjectSig(int)), this, SLOT(importProject(int))); // connect(this, SIGNAL(caseRenameSig(int, QString)), this, SLOT(caseRename(int, QString))); connect(this, SIGNAL(showMessage(ModuleBase::Message)), _mainWindow, SIGNAL(printMessageToMessageWindow(ModuleBase::Message))); ///< MG 节点变换 // connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(slot_selected_item_changed())); // // connect(_mainWindow, SIGNAL(sig_action_open()), this, SLOT(slot_action_open())); } QTreeWidgetItem *PhysicsWidget::getProjectRoot(QTreeWidgetItem *item) const { if (nullptr == item && nullptr == _curretnItem) return nullptr; if (item == nullptr) item = _curretnItem; if (item->parent() == nullptr) return item; if (item->type() == TreeItemType::MaterialRoot || item->parent()->type() == TreeItemType::MaterialRoot) return item; while (item->type() != TreeItemType::ProjectRoot) { item = item->parent(); if (item == nullptr) break; } if (item != nullptr) return item; return nullptr; } QTreeWidgetItem *PhysicsWidget::getProjectRoot(const int pid) const { int n = _physicsModelRoot->childCount(); for (int i = 0; i < n; ++i) { QTreeWidgetItem *item = _physicsModelRoot->child(i); int id = item->data(0, Qt::UserRole).toInt(); if (id == pid) return item; } return nullptr; } /// contextMenuEvent 重写了底层函数 相当于右键点击 void PhysicsWidget::contextMenuEvent(QContextMenuEvent *event) { Q_UNUSED(event) _curretnItem = currentItem(); if (!_curretnItem) return; QTreeWidgetItem *item = getProjectRoot(_curretnItem); if (nullptr == item) return; assert(item); const int proID = item->data(0, Qt::UserRole).toInt(); // on_TreeMouseEvent(1, _curretnItem, proID); emit(mouseEvent(1, _curretnItem, proID)); } void PhysicsWidget::singleClicked(QTreeWidgetItem *item, int col) { Q_UNUSED(col) _curretnItem = item; QTreeWidgetItem *rootitem = getProjectRoot(_curretnItem); assert(rootitem); const int proID = rootitem->data(0, Qt::UserRole).toInt(); bool e = false; switch (item->type()) { case TreeItemType::ProjectRoot: // 工程节点 { emit disPlayProp(ModelData::ModelDataSingleton::getinstance()->getModelByID(proID)); e = true; break; } case TreeItemType::MaterialChild: // 材料子节点 { int materialID = item->data(0, Qt::UserRole).toInt(); Material::Material *material = Material::MaterialSingleton::getInstance()->getMaterialByID(materialID); emit disPlayProp(material); e = true; break; } case TreeItemType::MaterialRoot: { emit disPlayProp(nullptr); e = true; break; } case TreeItemType::PhyaicsModelRoot: { emit disPlayProp(nullptr); e = true; break; } // default: // emit disPlayProp(nullptr); } if (!e) emit mouseEvent(0, _curretnItem, proID); } void PhysicsWidget::doubleClicked(QTreeWidgetItem *item, int col) { Q_UNUSED(col) _curretnItem = item; QTreeWidgetItem *rootitem = getProjectRoot(_curretnItem); assert(rootitem); const int proID = rootitem->data(0, Qt::UserRole).toInt(); emit mouseEvent(2, item, proID); } void PhysicsWidget::on_TreeMouseEvent(int evevntType, QTreeWidgetItem *item, int id) { CurrentID = id; if (id == 0 || item->type() == TreeItemType::ProjectRoot || item->type() == TreeItemType::MaterialChild) { switch (evevntType) { case 0: //左键单击 on_singleClicked(item); break; case 1: //右键单击 createContextMenu(item); break; case 2: //左键双击 on_doubleClicked(item); break; default: assert(0); break; } } if (_idTreeHash.contains(id)) { ProjectTree::ProjectTreeBase *tree = _idTreeHash[id]; tree->on_MouseEvent(evevntType, item); } } void PhysicsWidget::on_singleClicked(QTreeWidgetItem *item) { Q_UNUSED(item) } void PhysicsWidget::on_doubleClicked(QTreeWidgetItem *item) { Q_UNUSED(item) } void PhysicsWidget::createContextMenu(QTreeWidgetItem *item) { singleClicked(item, -1); QMenu pop_menu; QAction *action = nullptr; if (item->type() == TreeItemType::MaterialRoot) { action = pop_menu.addAction(tr("Load From Material Lib")); connect(action, SIGNAL(triggered()), this, SLOT(slot_load_from_material_lib())); action = pop_menu.addAction(tr("Create Material")); connect(action, SIGNAL(triggered()), this, SLOT(slot_create_material())); pop_menu.addSeparator(); action = pop_menu.addAction(tr("Remove From Material Lib")); connect(action, SIGNAL(triggered()), this, SLOT(slot_remove_from_material_lib())); } else if (item->type() == TreeItemType::MaterialChild) { action = pop_menu.addAction(tr("Delete Material")); connect(action, SIGNAL(triggered()), this, SLOT(slot_delete_material())); action = pop_menu.addAction(tr("Add to Material Lib")); connect(action, SIGNAL(triggered()), this, SLOT(slot_add_to_material_lib())); } else if (item->type() == TreeItemType::PhyaicsModelRoot) { action = pop_menu.addAction(tr("Create Case")); connect(action, SIGNAL(triggered()), this, SLOT(createPhysicsModel())); } else if (item->type() == TreeItemType::ProjectRoot) { action = pop_menu.addAction(tr("Delete Case")); connect(action, SIGNAL(triggered()), this, SLOT(deleteProject())); action = pop_menu.addAction(tr("Solve Case")); connect(action, SIGNAL(triggered()), this, SLOT(solveProject())); action = pop_menu.addAction(tr("Rename Case")); connect(action, SIGNAL(triggered()), this, SLOT(renameProject())); action = pop_menu.addAction(tr("Import Templete")); connect(action, SIGNAL(triggered()), this, SLOT(importProjectPy())); action = pop_menu.addAction(tr("Open Dir")); connect(action, SIGNAL(triggered()), this, SLOT(openProjectPath())); action = pop_menu.addAction(tr("Import INP File")); connect(action, SIGNAL(triggered()), _mainWindow, SLOT(on_importMesh())); const int modelId = _curretnItem->data(0, Qt::UserRole).toInt(); action->setObjectName(QString("Only INP_%1").arg(modelId)); action = pop_menu.addAction(tr("Export INP File")); connect(action, SIGNAL(triggered()), _mainWindow, SLOT(on_exportMesh())); action->setObjectName(QString("Only INP_%1").arg(modelId)); int id = item->data(0, Qt::UserRole).toInt(); auto tree = _idTreeHash.value(id); if (tree != nullptr) { pop_menu.addSeparator(); tree->setCurrentItem(item); tree->contextMenu(&pop_menu); } } pop_menu.exec(QCursor::pos()); } void PhysicsWidget::createPhysicsModel() { CreatePhysicsModel dlg(this, _mainWindow); dlg.exec(); } void PhysicsWidget::updateMaterialTree() { _materialRoot->takeChildren(); _materialRoot->setText(0, tr("Materials")); _materialRoot->setExpanded(true); Material::MaterialSingleton *s = Material::MaterialSingleton::getInstance(); int n = s->getMaterialCount(); for (int iCnt = 0; iCnt < n; ++iCnt) { Material::Material *material = s->getMaterialAt(iCnt); QTreeWidgetItem *materialItem = new QTreeWidgetItem(_materialRoot, TreeItemType::MaterialChild); materialItem->setText(0, material->getName()); materialItem->setIcon(0, QIcon(":/QUI/icon/material.png")); materialItem->setData(0, Qt::UserRole, material->getID()); } _materialRoot->setExpanded(true); } void PhysicsWidget::updatePhysicsTree() { _physicsModelRoot->takeChildren(); _physicsModelRoot->setText(0, tr("Case")); _physicsModelRoot->setExpanded(true); QList ptrees = _idTreeHash.values(); for (int i = 0; i < ptrees.size(); ++i) delete ptrees.at(i); _idTreeHash.clear(); CurrentID = -1; ModelData::ModelDataSingleton *s = ModelData::ModelDataSingleton::getinstance(); int n = s->getModelCount(); for (int i = 0; i < n; ++i) { ModelData::ModelDataBase *model = s->getModelAt(i); const ProjectTreeType treeType = model->getTreeType(); const int modelid = model->getID(); // ConfigOption::ProjectTreeConfig* treeconfig = ConfigOption::ConfigOption::getInstance()->getTreeConfig(); ProjectTree::ProjectTreeBase *tree = ProjectTreeFactory::creatTree(treeType, _mainWindow); if (tree == nullptr) continue; tree->setData(model); tree->createTree(_physicsModelRoot, _mainWindow); tree->updateTree(); _idTreeHash[modelid] = tree; CurrentID = modelid; } _physicsModelRoot->setExpanded(true); } void PhysicsWidget::removeCaseComponentSlot(int cpID) { QHash::iterator it; for (it = _idTreeHash.begin(); it != _idTreeHash.end(); ++it) { auto tree = dynamic_cast(it.value()); if (!tree->getComponentIDList().contains(cpID)) continue; tree->removeCaseComponentByID(cpID); } } void PhysicsWidget::renameCaseComponentSlot(int cpID) { QHash::iterator it; for (it = _idTreeHash.begin(); it != _idTreeHash.end(); ++it) { auto tree = dynamic_cast(it.value()); if (!tree->getComponentIDList().contains(cpID)) continue; tree->renameCaseComponentByID(cpID); } } void PhysicsWidget::updateTree() { updateMaterialTree(); updatePhysicsTree(); } void PhysicsWidget::renameProject() { if (_curretnItem->type() != TreeItemType::ProjectRoot) return; emit endaleGraphWinKey(false); // this->grabKeyboard(); this->editItem(_curretnItem); } void PhysicsWidget::deleteProject() { if (_curretnItem->type() != TreeItemType::ProjectRoot) return; QMessageBox::StandardButton b = QMessageBox::warning(this, tr("Warning"), tr("Confirm to delete?"), QMessageBox::Yes | QMessageBox::No); if (b == QMessageBox::No) return; const int id = _curretnItem->data(0, Qt::UserRole).toInt(); QString code = QString("ControlPanel.deleteCase(%1)").arg(id); Py::PythonAgent::getInstance()->submit(code); } void PhysicsWidget::deleteCase(int id) { ModelData::ModelDataSingleton *modelSing = ModelData::ModelDataSingleton::getinstance(); modelSing->removeModelByID(id); if (_curretnItem != nullptr) { _curretnItem->takeChildren(); _physicsModelRoot->removeChild(_curretnItem); ProjectTree::ProjectTreeBase *tree = _idTreeHash.value(id); _idTreeHash.remove(id); if (tree != nullptr) delete tree; CurrentID = -1; } else { updatePhysicsTree(); } emit updateActionStates(); } void PhysicsWidget::solveProject() { if (_curretnItem->type() != TreeItemType::ProjectRoot) return; const int id = _curretnItem->data(0, Qt::UserRole).toInt(); if (id > 0) emit solveProject(id); } void PhysicsWidget::importProjectPy() { // IO::ProjectTemplete *template_file = new IO::ProjectTemplete(); // QStringList file_text = template_file->getTempletefromFile(); const int id = _curretnItem->data(0, Qt::UserRole).toInt(); //获取ID QString code = QString("ControlPanel.importProject(%1)").arg(id); Py::PythonAgent::getInstance()->submit(code); } void PhysicsWidget::importProject(int id) { IO::ProjectTemplete *template_file = new IO::ProjectTemplete(); QStringList file_text = template_file->getTempletefromFile(); // const int id = _curretnItem->data(0, Qt::UserRole).toInt();//liu template_file->importTemplete(id, file_text); ModuleBase::Message msg(Common::Message::Normal, tr("Template import successfully!")); emit showMessage(msg); emit updatePropertyTableTree(); return; } void PhysicsWidget::slot_load_from_material_lib() { Material::MaterialSingleton::getInstance()->loadFromMaterialLib(_mainWindow); // updateMaterialTree(); } void PhysicsWidget::slot_remove_from_material_lib() { Material::MaterialSingleton::getInstance()->removeFromMAterialLib(_mainWindow); } void PhysicsWidget::slot_create_material() { CreateMaterialDialog dlg(_mainWindow); dlg.exec(); /* if (QDialog::Accepted == dlg.exec()) { updateMaterialTree(); }*/ } void PhysicsWidget::slot_delete_material() { if (_curretnItem->type() != TreeItemType::MaterialChild) return; const int id = _curretnItem->data(0, Qt::UserRole).toInt(); _curretnItem->takeChildren(); _physicsModelRoot->removeChild(_curretnItem); Material::MaterialSingleton *s = Material::MaterialSingleton::getInstance(); QString maname = s->getMaterialByID(id)->getName(); // qDebug() << maname; // s->removeMaterialByID(id); QString code = QString("ControlPanel.DeleteMaterial(%1,'%2')").arg(id).arg(maname); Py::PythonAgent::getInstance()->submit(code); /* emit updateActionStates(); updateMaterialTree(); emit disPlayProp(nullptr);*/ } void PhysicsWidget::slot_add_to_material_lib() { if (_curretnItem == nullptr) return; if (_curretnItem->type() != TreeItemType::MaterialChild) return; const int id = _curretnItem->data(0, Qt::UserRole).toInt(); Material::MaterialSingleton *s = Material::MaterialSingleton::getInstance(); QString maname = s->getMaterialByID(id)->getName(); // qDebug() << maname; // s->removeMaterialByID(id); QString code = QString("ControlPanel.AddMaterialToLib(%1,'%2')").arg(id).arg(maname); Py::PythonAgent::getInstance()->submit(code); // s->appendToMaterialLib(id); } void PhysicsWidget::caseRename(int pid, QString newname) { ModelData::ModelDataBase *model = ModelData::ModelDataSingleton::getinstance()->getModelByID(pid); if (nullptr == model) return; model->setName(newname); } void PhysicsWidget::closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint) { if (_curretnItem->type() != TreeItemType::ProjectRoot) return; const int pid = _curretnItem->data(0, Qt::UserRole).toInt(); if (pid < 1 || pid > ModelData::ModelDataBase::getMaxID()) return; ModelData::ModelDataBase *model = ModelData::ModelDataSingleton::getinstance()->getModelByID(pid); const QString oldname = model->getName(); const QString newname = _curretnItem->text(0).simplified(); bool exist = false; bool legal = true; if (newname.isEmpty() || (oldname == newname)) { _curretnItem->setText(0, oldname); } else { ModelData::ModelDataSingleton *models = ModelData::ModelDataSingleton::getinstance(); const int n = models->getModelCount(); for (int i = 0; i < n; ++i) { ModelData::ModelDataBase *dataBase = models->getModelAt(i); QString name = dataBase->getName(); if (name == newname) { exist = true; break; } } QRegExp rx("[//\\*:<>?\"\\|]"); int pos = rx.indexIn(newname); if (pos > -1 || newname.contains("\\")) { QString info = tr("Name can not contains fellowing char: \\/:*?\"<>|!"); QMessageBox::warning(this, tr("Warning"), info); legal = false; } else if (newname.toLocal8Bit().length() > 20) { QString info = tr("Name contains too many characters !"); QMessageBox::warning(this, tr("Warning"), info); legal = false; } if ((!exist) && legal) { _curretnItem->setText(0, newname); QString code = QString("ControlPanel.caseRename(%1,\"%2\")").arg(pid).arg(newname); qDebug() << code; Py::PythonAgent::getInstance()->submit(code); } else { _curretnItem->setText(0, oldname); } this->releaseKeyboard(); emit endaleGraphWinKey(true); } _curretnItem->setSelected(true); emit disPlayProp(model); QTreeWidget::closeEditor(editor, hint); if (exist) { QMessageBox::warning(this, tr("Warning"), tr("Case \"%1\" has already exist!").arg(newname)); } } void PhysicsWidget::reTranslate() { _materialRoot->setText(0, tr("Materials")); _physicsModelRoot->setText(0, tr("Case")); QList ids = _idTreeHash.keys(); for (int i = 0; i < ids.size(); ++i) { ProjectTree::ProjectTreeBase *t = _idTreeHash.value(ids.at(i)); if (t == nullptr) continue; t->reTranslate(); } } ProjectTree::ProjectTreeBase *PhysicsWidget::getProjectByID(int id) { return _idTreeHash.value(id); } void PhysicsWidget::openProjectPath() { if (_curretnItem->type() != TreeItemType::ProjectRoot) return; const int id = _curretnItem->data(0, Qt::UserRole).toInt(); ModelData::ModelDataSingleton *s = ModelData::ModelDataSingleton::getinstance(); ModelData::ModelDataBase *m = s->getModelByID(id); QString path = m->getPath(); QDir dir(path); if (!dir.exists()) dir.mkpath(path); QDesktopServices::openUrl(QUrl::fromLocalFile(path)); } void PhysicsWidget::updateMaterialStatus() { auto glo = ConfigOption::ConfigOption::getInstance()->getGlobalConfig(); bool ok = glo->isMaterialEnabled(); _materialRoot->setHidden(!ok); } }