LAMPCAE/src/MainWidgets/PhysicsWidget.cpp

648 lines
20 KiB
C++
Raw Normal View History

2023-05-08 06:32:41 +00:00
#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 <QMenu>
#include <QAction>
#include <assert.h>
#include <QDebug>
#include <QContextMenuEvent>
#include <QMessageBox>
#include <QDesktopServices>
#include <QUrl>
#include <QDir>
#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 <QTextCodec>
#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); // 材料
2023-05-08 06:32:41 +00:00
_materialRoot->setText(0, tr("Materials"));
_materialRoot->setIcon(0, QIcon(":/QUI/icon/material.png"));
_physicsModelRoot = new QTreeWidgetItem(this, TreeItemType::PhyaicsModelRoot); // 算例处理节点
2023-05-08 06:32:41 +00:00
_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<ProjectTree::ProjectTreeBase *> 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: // 工程节点
2023-05-08 06:32:41 +00:00
{
emit disPlayProp(ModelData::ModelDataSingleton::getinstance()->getModelByID(proID));
e = true;
break;
}
case TreeItemType::MaterialChild: // 材料子节点
2023-05-08 06:32:41 +00:00
{
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<ProjectTree::ProjectTreeBase *> 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<int, ProjectTree::ProjectTreeBase *>::iterator it;
for (it = _idTreeHash.begin(); it != _idTreeHash.end(); ++it)
{
auto tree = dynamic_cast<ProjectTree::ProjectTreeWithBasicNode *>(it.value());
if (!tree->getComponentIDList().contains(cpID))
continue;
tree->removeCaseComponentByID(cpID);
}
}
void PhysicsWidget::renameCaseComponentSlot(int cpID)
{
QHash<int, ProjectTree::ProjectTreeBase *>::iterator it;
for (it = _idTreeHash.begin(); it != _idTreeHash.end(); ++it)
{
auto tree = dynamic_cast<ProjectTree::ProjectTreeWithBasicNode *>(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<int> 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);
}
}