|
- #include "document.h"
- #include "graphicsitems.h"
- #include <QGraphicsItem>
- #include <QGraphicsSceneHoverEvent>
- #include <QMouseEvent>
- #include <QMenu>
- #include <QAction>
- #include <QDataStream>
- #include <QColorDialog>
- #include <QDialog>
- #include <QFormLayout>
- #include <QLineEdit>
- #include <QPushButton>
- #include <QDialogButtonBox>
- #include <QMimeData>
- #include <QDragEnterEvent>
- #include <QDropEvent>
- #include <QDebug>
-
- HMIDocument::HMIDocument(QWidget *parent)
- : BaseDocument(HMI, parent),
- m_title("未命名HMI"),
- m_canDrawEllipse(false),
- m_canDrawRectangle(false),
- m_lastPastePos(0, 0)
- {
- // 创建绘图场景
- m_scene = new QGraphicsScene(this);
- m_scene->setSceneRect(0, 0, 800, 600);
- m_scene->setBackgroundBrush(QBrush(Qt::lightGray));
-
- // 创建视图
- m_view = new QGraphicsView(m_scene, this);
- m_view->setRenderHint(QPainter::Antialiasing);
- m_view->setDragMode(QGraphicsView::RubberBandDrag);
- m_view->setAcceptDrops(true);
- m_view->viewport()->installEventFilter(this);
-
- // 布局(让视图占满文档区域)
- auto layout = new QVBoxLayout(this);
- layout->setContentsMargins(0, 0, 0, 0);
- layout->addWidget(m_view);
- setLayout(layout);
- }
-
- HMIDocument::~HMIDocument()
- {
- }
-
- // 事件过滤器(处理绘图、拖拽等事件)
- bool HMIDocument::eventFilter(QObject *obj, QEvent *event)
- {
- if (obj != m_view->viewport()) {
- return QWidget::eventFilter(obj, event);
- }
-
- // 鼠标按下事件(绘制图形)
- if (event->type() == QEvent::MouseButtonPress)
- {
- QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
-
- if (mouseEvent->button() == Qt::RightButton)
- {
- // 右键菜单
- showContextMenu(mouseEvent->globalPos());
- return true;
- }
- if (mouseEvent->button() == Qt::LeftButton)
- {
- QPointF scenePos = m_view->mapToScene(mouseEvent->pos());
- QGraphicsItem *item = m_scene->itemAt(scenePos, m_view->transform());
-
- // 如果点击空白区域且有绘制标志,创建图形
- if (!item) {
- if (m_canDrawEllipse) {
- createEllipse(scenePos);
- resetDrawFlags();
- } else if (m_canDrawRectangle) {
- createRectangle(scenePos);
- resetDrawFlags();
- }
- m_scene->clearSelection(); // 清除选择
- return true;
- }
- }
- }
-
- // 拖拽事件(从工具栏拖拽绘制)
- if (event->type() == QEvent::DragEnter) {
- QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent*>(event);
- dragEvent->acceptProposedAction();
- return true;
- }
- if (event->type() == QEvent::DragMove) {
- static_cast<QDragMoveEvent*>(event)->acceptProposedAction();
- return true;
- }
- if (event->type() == QEvent::Drop) {
- QDropEvent *dropEvent = static_cast<QDropEvent*>(event);
- const QMimeData *mimeData = dropEvent->mimeData(); // 显式获取mimeData
- QPointF scenePos = m_view->mapToScene(dropEvent->pos());
-
- // 使用QMimeData
- if (mimeData && mimeData->hasText()) {
- QString type = mimeData->text();
- if (type == "指示灯") {
- createEllipse(scenePos);
- } else if (type == "按钮") {
- createRectangle(scenePos);
- }
- }
- dropEvent->acceptProposedAction();
- return true;
- }
-
- return QWidget::eventFilter(obj, event);
- }
-
- // 创建椭圆(指示灯)
- void HMIDocument::createEllipse(const QPointF &pos)
- {
- ResizableEllipse *ellipse = new ResizableEllipse(pos.x(), pos.y(), 50, 50);
- ellipse->setBrush(QBrush(Qt::red));
- ellipse->setPen(QPen(Qt::black, 1));
- m_scene->addItem(ellipse);
- ellipse->setSelected(true);
- }
-
- // 创建矩形(按钮)
- void HMIDocument::createRectangle(const QPointF &pos)
- {
- ResizableRectangle *rect = new ResizableRectangle(pos.x(), pos.y(), 100, 50);
- rect->setBrush(QBrush(Qt::yellow));
- rect->setPen(QPen(Qt::black, 1));
- m_scene->addItem(rect);
- rect->setSelected(true);
- }
-
- // 重置绘制标志
- void HMIDocument::resetDrawFlags()
- {
- m_canDrawEllipse = false;
- m_canDrawRectangle = false;
- }
-
- // 右键菜单
- void HMIDocument::showContextMenu(QPoint globalPos)
- {
- QPoint viewportPos = m_view->mapFromGlobal(globalPos);
- QPointF scenePos = m_view->mapToScene(viewportPos);
- QGraphicsItem *clickedItem = m_scene->itemAt(scenePos, m_view->transform());
-
- QMenu menu(this);
-
- if (!clickedItem) {
- // 空白区域:仅显示粘贴
- QAction *pasteAction = menu.addAction("粘贴");
- pasteAction->setEnabled(!m_copiedItemsData.isEmpty());
- connect(pasteAction, &QAction::triggered, this, &HMIDocument::pasteItems);
- } else {
- // 选中图形:显示完整菜单
- QAction *propAction = menu.addAction("属性");
- QAction *copyAction = menu.addAction("复制");
- QAction *pasteAction = menu.addAction("粘贴");
- QAction *deleteAction = menu.addAction("删除");
- QAction *onAction = menu.addAction("置为ON");
- QAction *offAction = menu.addAction("置为OFF");
-
- pasteAction->setEnabled(!m_copiedItemsData.isEmpty());
-
- connect(propAction, &QAction::triggered, this, &HMIDocument::showItemProperties);
- connect(copyAction, &QAction::triggered, this, &HMIDocument::copySelectedItems);
- connect(pasteAction, &QAction::triggered, this, &HMIDocument::pasteItems);
- connect(deleteAction, &QAction::triggered, this, &HMIDocument::deleteSelectedItems);
-
- // ON/OFF动作(针对指示灯和按钮)
- connect(onAction, &QAction::triggered, [=]() {
- if (auto ellipse = dynamic_cast<ResizableEllipse*>(clickedItem)) {
- ellipse->setBrush(ellipse->onColor());
- } else if (auto rect = dynamic_cast<ResizableRectangle*>(clickedItem)) {
- rect->setBrush(rect->pressedColor());
- }
- });
- connect(offAction, &QAction::triggered, [=]() {
- if (auto ellipse = dynamic_cast<ResizableEllipse*>(clickedItem)) {
- ellipse->setBrush(ellipse->offColor());
- } else if (auto rect = dynamic_cast<ResizableRectangle*>(clickedItem)) {
- rect->setBrush(rect->releasedColor());
- }
- });
- }
-
- menu.exec(globalPos + QPoint(10, 10));
- }
-
- // 复制选中项
- void HMIDocument::copySelectedItems()
- {
- m_copiedItemsData.clear();
- QList<QGraphicsItem*> selectedItems = m_scene->selectedItems();
- if (selectedItems.isEmpty()) return;
-
- foreach (QGraphicsItem *item, selectedItems) {
- m_copiedItemsData.append(serializeItem(item));
- }
- m_lastPastePos = selectedItems.first()->pos();
- }
-
- // 粘贴项
- void HMIDocument::pasteItems()
- {
- if (m_copiedItemsData.isEmpty()) return;
-
- QPointF offset(20, 20);
- m_lastPastePos += offset;
- m_scene->clearSelection();
-
- foreach (const QByteArray &itemData, m_copiedItemsData) {
- QGraphicsItem *newItem = deserializeItem(itemData);
- if (newItem) {
- m_scene->addItem(newItem);
- newItem->setPos(m_lastPastePos);
- newItem->setSelected(true);
- }
- }
- }
-
- // 删除选中项
- void HMIDocument::deleteSelectedItems()
- {
- QList<QGraphicsItem*> selectedItems = m_scene->selectedItems();
- foreach (QGraphicsItem *item, selectedItems) {
- m_scene->removeItem(item);
- delete item;
- }
- }
-
- // 显示属性对话框
- void HMIDocument::showItemProperties()
- {
- QList<QGraphicsItem*> selectedItems = m_scene->selectedItems();
- if (selectedItems.isEmpty()) return;
- QGraphicsItem *item = selectedItems.first();
-
- // 将QGraphicsItem转换为NamedItem
- NamedItem *namedItem = dynamic_cast<NamedItem*>(item);
- if (!namedItem) return;
-
- QDialog dialog(this);
- dialog.setWindowTitle("属性设置");
- QFormLayout *form = new QFormLayout(&dialog);
-
- // 名称输入 - 使用NamedItem接口
- QLineEdit *nameEdit = new QLineEdit(namedItem->name());
-
- // 颜色选择(根据图形类型)
- QColor tempColor1, tempColor2;
- QPushButton *colorBtn1 = new QPushButton;
- QPushButton *colorBtn2 = new QPushButton;
-
- if (auto ellipse = dynamic_cast<ResizableEllipse*>(item)) {
- tempColor1 = ellipse->onColor();
- tempColor2 = ellipse->offColor();
- form->addRow("ON颜色:", colorBtn1);
- form->addRow("OFF颜色:", colorBtn2);
- } else if (auto rect = dynamic_cast<ResizableRectangle*>(item)) {
- tempColor1 = rect->pressedColor();
- tempColor2 = rect->releasedColor();
- form->addRow("按下颜色:", colorBtn1);
- form->addRow("释放颜色:", colorBtn2);
- }
-
- // 初始化颜色按钮
- colorBtn1->setStyleSheet("background-color:" + tempColor1.name());
- colorBtn2->setStyleSheet("background-color:" + tempColor2.name());
-
- // 颜色选择对话框
- connect(colorBtn1, &QPushButton::clicked, [&]() {
- QColor c = QColorDialog::getColor(tempColor1, &dialog);
- if (c.isValid()) {
- tempColor1 = c;
- colorBtn1->setStyleSheet("background-color:" + c.name());
- }
- });
- connect(colorBtn2, &QPushButton::clicked, [&]() {
- QColor c = QColorDialog::getColor(tempColor2, &dialog);
- if (c.isValid()) {
- tempColor2 = c;
- colorBtn2->setStyleSheet("background-color:" + c.name());
- }
- });
-
- // 布局组装
- form->addRow("名称:", nameEdit);
- QDialogButtonBox *btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
- form->addRow(btnBox);
- connect(btnBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
- connect(btnBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
-
- // 应用属性
- if (dialog.exec() == QDialog::Accepted) {
- // 使用NamedItem接口设置名称
- namedItem->setName(nameEdit->text());
-
- if (auto ellipse = dynamic_cast<ResizableEllipse*>(item)) {
- ellipse->setOnColor(tempColor1);
- ellipse->setOffColor(tempColor2);
- } else if (auto rect = dynamic_cast<ResizableRectangle*>(item)) {
- rect->setPressedColor(tempColor1);
- rect->setReleasedColor(tempColor2);
- }
- item->update();
- }
- }
-
- // 序列化图形项(用于复制粘贴)
- QByteArray HMIDocument::serializeItem(QGraphicsItem *item)
- {
- QByteArray data;
- QDataStream stream(&data, QIODevice::WriteOnly);
-
- // 基础信息
- stream << item->type();
- stream << item->pos();
- stream << item->flags();
- stream << item->transform();
- stream << item->isVisible();
-
- // 形状信息
- if (auto shape = dynamic_cast<QAbstractGraphicsShapeItem*>(item)) {
- stream << shape->pen();
- stream << shape->brush();
- stream << shape->boundingRect();
- }
-
- // 具体图形信息
- if (auto rect = dynamic_cast<ResizableRectangle*>(item)) {
- stream << rect->rect();
- stream << rect->pressedColor();
- stream << rect->releasedColor();
- stream << rect->name();
- } else if (auto ellipse = dynamic_cast<ResizableEllipse*>(item)) {
- stream << ellipse->rect();
- stream << ellipse->onColor();
- stream << ellipse->offColor();
- stream << ellipse->name();
- }
-
- return data;
- }
-
- // 反序列化图形项(用于粘贴)
- QGraphicsItem *HMIDocument::deserializeItem(const QByteArray &data)
- {
- QDataStream stream(data);
- int type;
- QPointF pos;
- QGraphicsItem::GraphicsItemFlags flags;
- QTransform transform;
- bool visible;
-
- stream >> type >> pos >> flags >> transform >> visible;
-
- QGraphicsItem *item = nullptr;
- if (type == QGraphicsRectItem::Type) {
- QPen pen;
- QBrush brush;
- QRectF boundRect;
- QRectF rect;
- QColor pressedColor, releasedColor;
- QString name;
-
- stream >> pen >> brush >> boundRect >> rect >> pressedColor >> releasedColor >> name;
-
- ResizableRectangle *rectItem = new ResizableRectangle(0, 0, rect.width(), rect.height());
- rectItem->setPen(pen);
- rectItem->setBrush(brush);
- rectItem->setPressedColor(pressedColor);
- rectItem->setReleasedColor(releasedColor);
- rectItem->setName(name);
- item = rectItem;
- } else if (type == QGraphicsEllipseItem::Type) {
- QPen pen;
- QBrush brush;
- QRectF boundRect;
- QRectF rect;
- QColor onColor, offColor;
- QString name;
-
- stream >> pen >> brush >> boundRect >> rect >> onColor >> offColor >> name;
-
- ResizableEllipse *ellipseItem = new ResizableEllipse(0, 0, rect.width(), rect.height());
- ellipseItem->setPen(pen);
- ellipseItem->setBrush(brush);
- ellipseItem->setOnColor(onColor);
- ellipseItem->setOffColor(offColor);
- ellipseItem->setName(name);
- item = ellipseItem;
- }
-
- if (item) {
- item->setFlags(flags);
- item->setTransform(transform);
- item->setVisible(visible);
- }
-
- return item;
- }
|