452 lines
11 KiB
C++
452 lines
11 KiB
C++
// pluginItemWrapper.cpp
|
|
#include "graphicsItem/pluginItemWrapper.h"
|
|
#include "pluginManager/include/pluginManager.h"
|
|
#include <QDebug>
|
|
#include <QPainter>
|
|
#include <QStyleOptionGraphicsItem>
|
|
|
|
PluginItemWrapper::PluginItemWrapper(ICanvasItem *pluginItem, QGraphicsItem *parent)
|
|
: GraphicsFunctionModelItem(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();
|
|
}
|
|
|
|
PluginItemWrapper::~PluginItemWrapper()
|
|
{
|
|
// 删除插件项
|
|
if (m_pluginItem) {
|
|
m_pluginItem->deleteLater();
|
|
}
|
|
}
|
|
|
|
GraphicsFunctionModelItem* PluginItemWrapper::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();
|
|
|
|
// 保存当前状态
|
|
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;
|
|
}
|
|
|
|
// 创建新的包装器
|
|
PluginItemWrapper *clone = new PluginItemWrapper(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 PluginItemWrapper::paint(QPainter *painter,
|
|
const QStyleOptionGraphicsItem *option,
|
|
QWidget *widget)
|
|
{
|
|
if (!painter || !m_pluginItem) {
|
|
return;
|
|
}
|
|
|
|
painter->save();
|
|
|
|
// 设置抗锯齿
|
|
painter->setRenderHint(QPainter::Antialiasing, true);
|
|
|
|
// 让插件绘制
|
|
m_pluginItem->draw(painter, m_cachedBounds);
|
|
|
|
// 如果选中,绘制控制框
|
|
if (option && (option->state & QStyle::State_Selected)) {
|
|
painter->setPen(QPen(QColor(0, 120, 215), 1, Qt::DashLine));
|
|
painter->setBrush(Qt::NoBrush);
|
|
|
|
// 绘制选中框
|
|
QRectF selectRect = m_cachedBounds.adjusted(-2, -2, 2, 2);
|
|
painter->drawRect(selectRect);
|
|
|
|
// 绘制控制点
|
|
const qreal handleSize = 6.0;
|
|
QRectF handleRect(-handleSize/2, -handleSize/2, handleSize, handleSize);
|
|
|
|
QBrush handleBrush(QColor(0, 120, 215));
|
|
QPen handlePen(Qt::white, 1);
|
|
|
|
// 绘制8个控制点
|
|
QPointF corners[] = {
|
|
m_cachedBounds.topLeft(),
|
|
m_cachedBounds.topRight(),
|
|
m_cachedBounds.bottomRight(),
|
|
m_cachedBounds.bottomLeft(),
|
|
QPointF(m_cachedBounds.center().x(), m_cachedBounds.top()),
|
|
QPointF(m_cachedBounds.right(), m_cachedBounds.center().y()),
|
|
QPointF(m_cachedBounds.center().x(), m_cachedBounds.bottom()),
|
|
QPointF(m_cachedBounds.left(), m_cachedBounds.center().y())
|
|
};
|
|
|
|
for (const QPointF &corner : corners) {
|
|
painter->save();
|
|
painter->translate(corner);
|
|
painter->setPen(handlePen);
|
|
painter->setBrush(handleBrush);
|
|
painter->drawEllipse(handleRect);
|
|
painter->restore();
|
|
}
|
|
}
|
|
|
|
painter->restore();
|
|
}
|
|
|
|
QRectF PluginItemWrapper::boundingRect() const
|
|
{
|
|
qreal margin = 4.0; // 为控制点留出空间
|
|
return m_cachedBounds.adjusted(-margin, -margin, margin, margin);
|
|
}
|
|
|
|
QPainterPath PluginItemWrapper::shape() const
|
|
{
|
|
QPainterPath path;
|
|
|
|
if (!m_pluginItem) {
|
|
return path;
|
|
}
|
|
|
|
// 创建简单的矩形路径
|
|
// 插件可以提供更精确的形状,这里简化处理
|
|
path.addRect(m_cachedBounds);
|
|
|
|
return path;
|
|
}
|
|
|
|
void PluginItemWrapper::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 PluginItemWrapper::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 PluginItemWrapper::move(const QPointF &delta)
|
|
{
|
|
if (!m_pluginItem || delta.isNull()) {
|
|
return;
|
|
}
|
|
|
|
QRectF bounds = m_pluginItem->bounds();
|
|
bounds.translate(delta);
|
|
m_pluginItem->setBounds(bounds);
|
|
}
|
|
|
|
ICanvasItem* PluginItemWrapper::pluginItem() const
|
|
{
|
|
return m_pluginItem;
|
|
}
|
|
|
|
QVariant PluginItemWrapper::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 PluginItemWrapper::updateCache()
|
|
{
|
|
if (m_pluginItem) {
|
|
m_cachedBounds = m_pluginItem->bounds();
|
|
}
|
|
}
|
|
|
|
void PluginItemWrapper::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 PluginItemWrapper::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->property(key);
|
|
if (value.isValid()) {
|
|
state[key] = value;
|
|
}
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
bool PluginItemWrapper::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 PluginItemWrapper::copyPropertiesFrom(const PluginItemWrapper *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 PluginItemWrapper::onPluginBoundsChanged(const QRectF &newBounds)
|
|
{
|
|
m_cachedBounds = newBounds;
|
|
|
|
// 更新坐标
|
|
updateCoordinate();
|
|
|
|
// 通知变化
|
|
emit itemChanged();
|
|
}
|
|
|
|
void PluginItemWrapper::onPluginPropertyChanged(const QString &key, const QVariant &value)
|
|
{
|
|
Q_UNUSED(key);
|
|
Q_UNUSED(value);
|
|
|
|
// 属性变化,需要重绘
|
|
update();
|
|
|
|
// 通知变化
|
|
emit itemChanged();
|
|
}
|