450 lines
11 KiB
C++
450 lines
11 KiB
C++
// pluginItemWrapper.cpp
|
|
#include "graphicsItem/pluginSvgItemWrapper.h"
|
|
#include "pluginManager/include/pluginManager.h"
|
|
#include "baseProperty.h"
|
|
#include "graphicsDataModel/fixedPortsModel.h"
|
|
#include <QDebug>
|
|
#include <QPainter>
|
|
#include <QStyleOptionGraphicsItem>
|
|
|
|
PluginSvgItemWrapper::PluginSvgItemWrapper(ICanvasItem *pluginItem, QGraphicsItem *parent)
|
|
: ElectricFunctionModelSvgItem(pluginItem->bounds().toRect(),parent)
|
|
, m_pluginItem(pluginItem)
|
|
{
|
|
if (!m_pluginItem) {
|
|
qWarning() << "PluginItemWrapper: pluginItem is null!";
|
|
return;
|
|
}
|
|
|
|
// 设置类型
|
|
m_Itemtype = GIT_PluginItem;
|
|
|
|
// 设置初始名称
|
|
setName(m_pluginItem->displayName());
|
|
|
|
// 连接信号
|
|
connectSignals();
|
|
|
|
// 初始化缓存
|
|
updateCache();
|
|
|
|
// 更新坐标
|
|
updateCoordinate();
|
|
|
|
qDebug() << "PluginItemWrapper created for:" << m_pluginItem->typeId();
|
|
}
|
|
|
|
PluginSvgItemWrapper::~PluginSvgItemWrapper()
|
|
{
|
|
// 删除插件项
|
|
if (m_pluginItem) {
|
|
m_pluginItem->deleteLater();
|
|
}
|
|
}
|
|
|
|
void PluginSvgItemWrapper::setImage_1(QFileInfo info)
|
|
{
|
|
QByteArray svgData;
|
|
QFile svgFile(info.absoluteFilePath());
|
|
|
|
if (svgFile.open(QIODevice::ReadOnly)) {
|
|
svgData = svgFile.readAll();
|
|
svgFile.close();
|
|
} else {
|
|
qDebug() << "can't open imgfile" << svgFile.errorString();
|
|
}
|
|
|
|
QMap<QString,QByteArray> mapData;
|
|
if(!svgData.isEmpty()){
|
|
mapData["custom"] = svgData;
|
|
updateMapSvg(mapData,"custom");
|
|
loadSvg(svgData);
|
|
updateItem();
|
|
}
|
|
|
|
QString sMeta;
|
|
QString sModel;
|
|
int nType = -1;
|
|
if(_property){
|
|
sMeta = _property->metaModelName();
|
|
sModel = _property->modelName();
|
|
nType = _property->type();
|
|
}
|
|
|
|
if(_pHandle && !sMeta.isEmpty() && !sModel.isEmpty())
|
|
_pHandle->updateItemIcon(sMeta,sModel,mapData,"custom",nType,0);
|
|
|
|
ElectricFunctionModelSvgItem::setImage_1(info);
|
|
}
|
|
|
|
ElectricFunctionModelSvgItem* PluginSvgItemWrapper::clone() const
|
|
{
|
|
if (!m_pluginItem) {
|
|
return nullptr;
|
|
}
|
|
|
|
// 获取场景中的PluginManager
|
|
PluginManager *manager = PluginManager::instance();
|
|
if (!manager) {
|
|
qWarning() << "PluginManager not available for cloning";
|
|
return nullptr;
|
|
}
|
|
|
|
// 获取插件类型
|
|
QString pluginType = m_pluginItem->typeId();
|
|
int nBaseType = m_pluginItem->baseType();
|
|
|
|
// 保存当前状态
|
|
QVariantMap state = saveState();
|
|
|
|
// 创建新的插件项
|
|
ICanvasItem *newPluginItem = manager->createItem(pluginType);
|
|
if (!newPluginItem) {
|
|
qWarning() << "Failed to create plugin item for cloning:" << pluginType;
|
|
return nullptr;
|
|
}
|
|
|
|
// 恢复状态
|
|
if (!loadStateIntoPluginItem(newPluginItem, state)) {
|
|
qWarning() << "Failed to restore state for cloned item";
|
|
delete newPluginItem;
|
|
return nullptr;
|
|
}
|
|
|
|
// 创建新的包装器
|
|
PluginSvgItemWrapper *clone = new PluginSvgItemWrapper(newPluginItem, parentItem());
|
|
|
|
// 复制变换属性
|
|
clone->setPos(pos());
|
|
clone->setRotation(rotation());
|
|
clone->setScale(scale());
|
|
clone->setZValue(zValue());
|
|
|
|
// 复制其他属性
|
|
clone->copyPropertiesFrom(this);
|
|
|
|
qDebug() << "Cloned plugin item:" << pluginType;
|
|
return clone;
|
|
}
|
|
|
|
void PluginSvgItemWrapper::paint(QPainter *painter,
|
|
const QStyleOptionGraphicsItem *option,
|
|
QWidget *widget)
|
|
{
|
|
if (!painter || !m_pluginItem) {
|
|
return;
|
|
}
|
|
|
|
painter->save();
|
|
// 让插件绘制
|
|
m_pluginItem->draw(painter, m_cachedBounds);
|
|
|
|
ElectricFunctionModelSvgItem::paint(painter,option,widget); //调用默认绘制
|
|
|
|
painter->restore();
|
|
}
|
|
|
|
QRectF PluginSvgItemWrapper::boundingRect() const
|
|
{
|
|
qreal margin = 4.0; // 为控制点留出空间
|
|
return m_cachedBounds.adjusted(-margin, -margin, margin, margin);
|
|
}
|
|
|
|
QPainterPath PluginSvgItemWrapper::shape() const
|
|
{
|
|
QPainterPath path;
|
|
|
|
if (!m_pluginItem) {
|
|
return path;
|
|
}
|
|
|
|
// 创建简单的矩形路径
|
|
// 插件可以提供更精确的形状,这里简化处理
|
|
path.addRect(m_cachedBounds);
|
|
|
|
return path;
|
|
}
|
|
|
|
void PluginSvgItemWrapper::updateCoordinate()
|
|
{
|
|
if (!m_pluginItem) {
|
|
return;
|
|
}
|
|
|
|
// 更新基类属性
|
|
QRectF bounds = m_pluginItem->bounds();
|
|
m_dWidth = bounds.width();
|
|
m_dHeight = bounds.height();
|
|
|
|
// 更新包围框
|
|
m_boundingRect = bounds;
|
|
|
|
// 更新变换
|
|
setTransformOriginPoint(bounds.center());
|
|
|
|
// 调用基类更新
|
|
GraphicsFunctionModelItem::updateCoordinate();
|
|
|
|
// 更新句柄位置
|
|
updateHandles();
|
|
}
|
|
|
|
void PluginSvgItemWrapper::resize(int handle, double dx, double dy, const QPointF &pos)
|
|
{
|
|
if (!m_pluginItem) {
|
|
return;
|
|
}
|
|
|
|
QRectF bounds = m_pluginItem->bounds();
|
|
QRectF newBounds = bounds;
|
|
|
|
// 根据控制点调整大小
|
|
switch (handle) {
|
|
case H_leftTop:
|
|
newBounds.setTopLeft(newBounds.topLeft() + QPointF(dx, dy));
|
|
break;
|
|
case H_top:
|
|
newBounds.setTop(newBounds.top() + dy);
|
|
break;
|
|
case H_rightTop:
|
|
newBounds.setTopRight(newBounds.topRight() + QPointF(dx, dy));
|
|
break;
|
|
case H_right:
|
|
newBounds.setRight(newBounds.right() + dx);
|
|
break;
|
|
case H_rightBottom:
|
|
newBounds.setBottomRight(newBounds.bottomRight() + QPointF(dx, dy));
|
|
break;
|
|
case H_bottom:
|
|
newBounds.setBottom(newBounds.bottom() + dy);
|
|
break;
|
|
case H_leftBottom:
|
|
newBounds.setBottomLeft(newBounds.bottomLeft() + QPointF(dx, dy));
|
|
break;
|
|
case H_left:
|
|
newBounds.setLeft(newBounds.left() + dx);
|
|
break;
|
|
default:
|
|
// 不是控制点,直接移动
|
|
move(QPointF(dx, dy));
|
|
return;
|
|
}
|
|
|
|
// 确保大小有效
|
|
if (newBounds.width() < 10) {
|
|
newBounds.setWidth(10);
|
|
}
|
|
if (newBounds.height() < 10) {
|
|
newBounds.setHeight(10);
|
|
}
|
|
|
|
if (newBounds.isValid() && newBounds != bounds) {
|
|
m_pluginItem->setBounds(newBounds);
|
|
}
|
|
}
|
|
|
|
void PluginSvgItemWrapper::move(const QPointF &delta)
|
|
{
|
|
if (!m_pluginItem || delta.isNull()) {
|
|
return;
|
|
}
|
|
|
|
QRectF bounds = m_pluginItem->bounds();
|
|
bounds.translate(delta);
|
|
m_pluginItem->setBounds(bounds);
|
|
}
|
|
|
|
ICanvasItem* PluginSvgItemWrapper::pluginItem() const
|
|
{
|
|
return m_pluginItem;
|
|
}
|
|
|
|
QVariant PluginSvgItemWrapper::itemChange(GraphicsItemChange change, const QVariant &value)
|
|
{
|
|
if (!m_pluginItem) {
|
|
return GraphicsFunctionModelItem::itemChange(change, value);
|
|
}
|
|
|
|
switch (change) {
|
|
case ItemSelectedChange:
|
|
// 选中状态变化
|
|
if (value.toBool()) {
|
|
// 选中时的处理
|
|
setHandleVisible(true);
|
|
} else {
|
|
// 取消选中的处理
|
|
setHandleVisible(false);
|
|
}
|
|
break;
|
|
|
|
case ItemPositionChange: {
|
|
// 位置变化
|
|
QPointF newPos = value.toPointF();
|
|
QPointF delta = newPos - pos();
|
|
|
|
// 更新插件项的位置
|
|
QRectF bounds = m_pluginItem->bounds();
|
|
bounds.translate(delta);
|
|
m_pluginItem->setBounds(bounds);
|
|
|
|
return newPos;
|
|
}
|
|
|
|
case ItemRotationChange:
|
|
// 旋转变化
|
|
// 插件项可能需要处理旋转
|
|
break;
|
|
|
|
case ItemScaleChange:
|
|
// 缩放变化
|
|
// 插件项可能需要处理缩放
|
|
break;
|
|
|
|
case ItemZValueChange:
|
|
// Z值变化
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return GraphicsFunctionModelItem::itemChange(change, value);
|
|
}
|
|
|
|
void PluginSvgItemWrapper::updateCache()
|
|
{
|
|
if (m_pluginItem) {
|
|
m_cachedBounds = m_pluginItem->bounds();
|
|
}
|
|
}
|
|
|
|
void PluginSvgItemWrapper::connectSignals()
|
|
{
|
|
if (!m_pluginItem) {
|
|
return;
|
|
}
|
|
|
|
// 使用旧式语法连接
|
|
connect(m_pluginItem, SIGNAL(boundsChanged(QRectF)),
|
|
this, SLOT(onPluginBoundsChanged(QRectF)));
|
|
|
|
connect(m_pluginItem, SIGNAL(propertyChanged(QString, QVariant)),
|
|
this, SLOT(onPluginPropertyChanged(QString, QVariant)));
|
|
}
|
|
|
|
QVariantMap PluginSvgItemWrapper::saveState() const
|
|
{
|
|
QVariantMap state;
|
|
|
|
if (!m_pluginItem) {
|
|
return state;
|
|
}
|
|
|
|
// 保存基本属性
|
|
state["type"] = m_pluginItem->typeId();
|
|
state["displayName"] = m_pluginItem->displayName();
|
|
|
|
// 保存几何信息
|
|
QRectF bounds = m_pluginItem->bounds();
|
|
state["x"] = bounds.x();
|
|
state["y"] = bounds.y();
|
|
state["width"] = bounds.width();
|
|
state["height"] = bounds.height();
|
|
|
|
// 保存插件特定属性
|
|
// 这里可以保存插件的关键属性
|
|
QStringList propertyKeys = {"fillColor", "borderColor", "borderWidth", "cornerRadius"};
|
|
for (const QString &key : propertyKeys) {
|
|
QVariant value = m_pluginItem->getProperty(key);
|
|
if (value.isValid()) {
|
|
state[key] = value;
|
|
}
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
bool PluginSvgItemWrapper::loadStateIntoPluginItem(ICanvasItem *pluginItem, const QVariantMap &state) const
|
|
{
|
|
if (!pluginItem) {
|
|
return false;
|
|
}
|
|
|
|
// 设置几何信息
|
|
if (state.contains("x") && state.contains("y") &&
|
|
state.contains("width") && state.contains("height")) {
|
|
QRectF bounds(
|
|
state["x"].toReal(),
|
|
state["y"].toReal(),
|
|
state["width"].toReal(),
|
|
state["height"].toReal()
|
|
);
|
|
|
|
if (bounds.isValid()) {
|
|
pluginItem->setBounds(bounds);
|
|
}
|
|
}
|
|
|
|
// 设置插件属性
|
|
QStringList propertyKeys = {"fillColor", "borderColor", "borderWidth", "cornerRadius"};
|
|
for (const QString &key : propertyKeys) {
|
|
if (state.contains(key)) {
|
|
pluginItem->setProperty(key, state[key]);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void PluginSvgItemWrapper::copyPropertiesFrom(const PluginSvgItemWrapper *source)
|
|
{
|
|
if (!source) {
|
|
return;
|
|
}
|
|
|
|
// 复制基类属性
|
|
m_type = source->m_type;
|
|
m_pen = source->m_pen;
|
|
m_brush = source->m_brush;
|
|
m_dWidth = source->m_dWidth;
|
|
m_dHeight = source->m_dHeight;
|
|
m_boundingRect = source->m_boundingRect;
|
|
m_Itemtype = source->m_Itemtype;
|
|
|
|
// 复制可见性和使能状态
|
|
setVisible(source->isVisible());
|
|
setEnabled(source->isEnabled());
|
|
|
|
// 复制工具提示
|
|
setToolTip(source->toolTip());
|
|
|
|
// 复制自定义数据
|
|
setData(0, source->data(0));
|
|
|
|
// 生成新的ID
|
|
setItemId(QUuid::createUuid());
|
|
}
|
|
|
|
void PluginSvgItemWrapper::onPluginBoundsChanged(const QRectF &newBounds)
|
|
{
|
|
m_cachedBounds = newBounds;
|
|
|
|
// 更新坐标
|
|
updateCoordinate();
|
|
|
|
// 通知变化
|
|
emit itemChanged();
|
|
}
|
|
|
|
void PluginSvgItemWrapper::onPluginPropertyChanged(const QString &key, const QVariant &value)
|
|
{
|
|
Q_UNUSED(key);
|
|
Q_UNUSED(value);
|
|
|
|
// 属性变化,需要重绘
|
|
update();
|
|
|
|
// 通知变化
|
|
emit itemChanged();
|
|
}
|