|
@@ -1,54 +1,28 @@ |
|
|
#include "hmieditorwidget.h" |
|
|
#include "hmieditorwidget.h" |
|
|
#include "hmiwidgetfactory.h" |
|
|
|
|
|
#include <QHBoxLayout> |
|
|
|
|
|
|
|
|
#include "hmibutton.h" |
|
|
|
|
|
#include "hmiled.h" |
|
|
|
|
|
#include "hmicontrolitem.h" |
|
|
|
|
|
|
|
|
#include <QVBoxLayout> |
|
|
#include <QVBoxLayout> |
|
|
#include <QGraphicsScene> |
|
|
|
|
|
#include <QGraphicsView> |
|
|
|
|
|
#include <QDebug> |
|
|
|
|
|
#include <QKeyEvent> |
|
|
|
|
|
#include <QMouseEvent> |
|
|
|
|
|
|
|
|
#include <QContextMenuEvent> |
|
|
#include <QMenu> |
|
|
#include <QMenu> |
|
|
#include <QTimer> |
|
|
|
|
|
#include <QCoreApplication> |
|
|
|
|
|
#include <QMetaObject> |
|
|
#include <QMetaObject> |
|
|
#include "hmicontrolitem.h" |
|
|
|
|
|
|
|
|
#include <QGraphicsView> |
|
|
|
|
|
#include <QApplication> |
|
|
|
|
|
#include <QClipboard> |
|
|
|
|
|
|
|
|
HmiEditorWidget::HmiEditorWidget(QWidget* parent) |
|
|
HmiEditorWidget::HmiEditorWidget(QWidget* parent) |
|
|
: QWidget(parent) |
|
|
|
|
|
|
|
|
: EditorWidget(parent) |
|
|
{ |
|
|
{ |
|
|
QHBoxLayout* mainLayout = new QHBoxLayout(this); |
|
|
|
|
|
mainLayout->setContentsMargins(10, 10, 10, 10); |
|
|
|
|
|
mainLayout->setSpacing(10); |
|
|
|
|
|
|
|
|
|
|
|
QVBoxLayout* leftLayout = new QVBoxLayout(); |
|
|
|
|
|
leftLayout->setSpacing(5); |
|
|
|
|
|
|
|
|
|
|
|
hmiToolbar = new QListWidget(this); |
|
|
|
|
|
hmiToolbar->setViewMode(QListWidget::IconMode); |
|
|
|
|
|
hmiToolbar->setIconSize(QSize(48, 48)); |
|
|
|
|
|
hmiToolbar->setFixedWidth(100); |
|
|
|
|
|
hmiToolbar->setSpacing(10); |
|
|
|
|
|
hmiToolbar->setDragEnabled(false); |
|
|
|
|
|
|
|
|
|
|
|
QListWidgetItem* buttonItem = new QListWidgetItem(); |
|
|
|
|
|
buttonItem->setIcon(QIcon(":resource/image/button.png")); |
|
|
|
|
|
buttonItem->setData(Qt::UserRole, QString("按钮")); |
|
|
|
|
|
buttonItem->setToolTip("按钮"); |
|
|
|
|
|
hmiToolbar->addItem(buttonItem); |
|
|
|
|
|
|
|
|
|
|
|
QListWidgetItem* ledItem = new QListWidgetItem(); |
|
|
|
|
|
ledItem->setIcon(QIcon(":resource/image/light.png")); |
|
|
|
|
|
ledItem->setData(Qt::UserRole, QString("指示灯")); |
|
|
|
|
|
ledItem->setToolTip("指示灯"); |
|
|
|
|
|
hmiToolbar->addItem(ledItem); |
|
|
|
|
|
|
|
|
|
|
|
leftLayout->addWidget(hmiToolbar); |
|
|
|
|
|
|
|
|
// 左侧:在父类 EditorWidget 的左侧工具栏区域追加页面按钮与标签 |
|
|
|
|
|
QLayoutItem* item = layout()->itemAt(0)->widget()->layout()->itemAt(0); |
|
|
|
|
|
auto* leftLayout = dynamic_cast<QVBoxLayout*>(item->layout()); |
|
|
|
|
|
|
|
|
m_newPageButton = new QPushButton("新建页面", this); |
|
|
|
|
|
|
|
|
m_newPageButton = new QPushButton("新建页面", this); |
|
|
m_deletePageButton = new QPushButton("删除页面", this); |
|
|
m_deletePageButton = new QPushButton("删除页面", this); |
|
|
m_prevPageButton = new QPushButton("上一页", this); |
|
|
|
|
|
m_nextPageButton = new QPushButton("下一页", this); |
|
|
|
|
|
m_pageLabel = new QLabel("无页面", this); |
|
|
|
|
|
|
|
|
m_prevPageButton = new QPushButton("上一页", this); |
|
|
|
|
|
m_nextPageButton = new QPushButton("下一页", this); |
|
|
|
|
|
m_pageLabel = new QLabel("无页面", this); |
|
|
|
|
|
|
|
|
leftLayout->addWidget(m_newPageButton); |
|
|
leftLayout->addWidget(m_newPageButton); |
|
|
leftLayout->addWidget(m_deletePageButton); |
|
|
leftLayout->addWidget(m_deletePageButton); |
|
@@ -57,100 +31,128 @@ HmiEditorWidget::HmiEditorWidget(QWidget* parent) |
|
|
leftLayout->addWidget(m_pageLabel); |
|
|
leftLayout->addWidget(m_pageLabel); |
|
|
leftLayout->addStretch(); |
|
|
leftLayout->addStretch(); |
|
|
|
|
|
|
|
|
mainLayout->addLayout(leftLayout); |
|
|
|
|
|
|
|
|
|
|
|
hmiEditArea = new QGraphicsView(this); |
|
|
|
|
|
hmiEditArea->setRenderHint(QPainter::Antialiasing); |
|
|
|
|
|
hmiEditArea->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); |
|
|
|
|
|
hmiEditArea->setOptimizationFlags(QGraphicsView::DontSavePainterState | QGraphicsView::DontAdjustForAntialiasing); |
|
|
|
|
|
hmiEditArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); |
|
|
|
|
|
hmiEditArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); |
|
|
|
|
|
mainLayout->addWidget(hmiEditArea, 1); |
|
|
|
|
|
|
|
|
|
|
|
hmiEditArea->installEventFilter(this); |
|
|
|
|
|
|
|
|
|
|
|
connect(hmiToolbar, &QListWidget::itemClicked, this, &HmiEditorWidget::onToolbarItemClicked); |
|
|
|
|
|
connect(m_newPageButton, &QPushButton::clicked, this, &HmiEditorWidget::onNewPageClicked); |
|
|
|
|
|
|
|
|
connect(m_newPageButton, &QPushButton::clicked, this, &HmiEditorWidget::onNewPageClicked); |
|
|
connect(m_deletePageButton, &QPushButton::clicked, this, &HmiEditorWidget::onDeletePageClicked); |
|
|
connect(m_deletePageButton, &QPushButton::clicked, this, &HmiEditorWidget::onDeletePageClicked); |
|
|
connect(m_prevPageButton, &QPushButton::clicked, this, &HmiEditorWidget::onPreviousPageClicked); |
|
|
|
|
|
connect(m_nextPageButton, &QPushButton::clicked, this, &HmiEditorWidget::onNextPageClicked); |
|
|
|
|
|
|
|
|
connect(m_prevPageButton, &QPushButton::clicked, this, &HmiEditorWidget::onPreviousPageClicked); |
|
|
|
|
|
connect(m_nextPageButton, &QPushButton::clicked, this, &HmiEditorWidget::onNextPageClicked); |
|
|
|
|
|
|
|
|
|
|
|
// 工具栏项 |
|
|
|
|
|
initToolbar(); |
|
|
|
|
|
|
|
|
|
|
|
// 确保视图已创建(父类提供) |
|
|
ensureViewReady(); |
|
|
ensureViewReady(); |
|
|
|
|
|
|
|
|
|
|
|
// 捕获编辑区鼠标:既监听 QGraphicsView 自身,也监听其 viewport |
|
|
|
|
|
if (editArea) { |
|
|
|
|
|
editArea->installEventFilter(this); |
|
|
|
|
|
if (editArea->viewport()) |
|
|
|
|
|
editArea->viewport()->installEventFilter(this); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
HmiEditorWidget::~HmiEditorWidget() |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
HmiEditorWidget::~HmiEditorWidget() { |
|
|
clearPages(); |
|
|
clearPages(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void HmiEditorWidget::ensureViewReady() |
|
|
|
|
|
|
|
|
void HmiEditorWidget::refreshView() |
|
|
{ |
|
|
{ |
|
|
QCoreApplication::processEvents(); |
|
|
|
|
|
hmiEditArea->resetTransform(); |
|
|
|
|
|
hmiEditArea->viewport()->update(); |
|
|
|
|
|
|
|
|
|
|
|
if (hmiEditArea->viewport()->rect().isEmpty()) { |
|
|
|
|
|
hmiEditArea->setFixedSize(600, 400); |
|
|
|
|
|
QCoreApplication::processEvents(); |
|
|
|
|
|
|
|
|
if (m_currentPageIndex >= 0 && !m_pages.isEmpty()) { |
|
|
|
|
|
editArea->setScene(nullptr); |
|
|
|
|
|
editArea->setScene(m_pages[m_currentPageIndex]); |
|
|
|
|
|
initViewScale(); |
|
|
|
|
|
editArea->viewport()->update(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void HmiEditorWidget::showEvent(QShowEvent* event) |
|
|
|
|
|
{ |
|
|
|
|
|
QWidget::showEvent(event); |
|
|
|
|
|
if (m_firstShow && m_pages.isEmpty()) { |
|
|
|
|
|
m_firstShow = false; |
|
|
|
|
|
createNewPage(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void HmiEditorWidget::initToolbar() { |
|
|
|
|
|
// “按钮” |
|
|
|
|
|
auto* buttonItem = new QListWidgetItem(); |
|
|
|
|
|
buttonItem->setIcon(QIcon(":resource/image/button.png")); |
|
|
|
|
|
buttonItem->setData(Qt::UserRole, QString("按钮")); |
|
|
|
|
|
buttonItem->setToolTip("按钮"); |
|
|
|
|
|
toolbar->addItem(buttonItem); |
|
|
|
|
|
|
|
|
|
|
|
// “指示灯” |
|
|
|
|
|
auto* ledItem = new QListWidgetItem(); |
|
|
|
|
|
ledItem->setIcon(QIcon(":resource/image/light.png")); |
|
|
|
|
|
ledItem->setData(Qt::UserRole, QString("指示灯")); |
|
|
|
|
|
ledItem->setToolTip("指示灯"); |
|
|
|
|
|
toolbar->addItem(ledItem); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void HmiEditorWidget::onToolbarItemClicked(QListWidgetItem* item) { |
|
|
|
|
|
if (!item) return; |
|
|
|
|
|
|
|
|
|
|
|
// —— 关键改动 ——: |
|
|
|
|
|
// 不再“立即创建到场景中心”,而是进入“放置模式” |
|
|
|
|
|
m_pendingType = item->data(Qt::UserRole).toString(); |
|
|
|
|
|
setPlacingCursor(true); |
|
|
|
|
|
|
|
|
|
|
|
appendOutput(QString("已选择控件:%1。请在编辑区点击以放置。").arg(m_pendingType)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
QGraphicsScene* HmiEditorWidget::getCurrentScene() const { |
|
|
|
|
|
if (m_currentPageIndex >= 0 && m_currentPageIndex < m_pages.size()) |
|
|
|
|
|
return m_pages[m_currentPageIndex]; |
|
|
|
|
|
return nullptr; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void HmiEditorWidget::clearPages() { |
|
|
|
|
|
for (QGraphicsScene* scene : m_pages) delete scene; |
|
|
|
|
|
m_pages.clear(); |
|
|
|
|
|
m_currentPageIndex = -1; |
|
|
|
|
|
if (editArea) editArea->setScene(nullptr); |
|
|
|
|
|
updatePageLabel(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void HmiEditorWidget::createNewPage() |
|
|
void HmiEditorWidget::createNewPage() |
|
|
{ |
|
|
{ |
|
|
QGraphicsScene* newScene = new QGraphicsScene(this); |
|
|
|
|
|
QRect viewRect = hmiEditArea->viewport()->rect(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto* newScene = new QGraphicsScene(this); |
|
|
|
|
|
QRect viewRect = editArea->viewport()->rect(); |
|
|
if (viewRect.isEmpty()) { |
|
|
if (viewRect.isEmpty()) { |
|
|
viewRect = QRect(0, 0, 800, 600); |
|
|
|
|
|
hmiEditArea->setSceneRect(viewRect); |
|
|
|
|
|
|
|
|
viewRect = QRect(0,0,800,600); |
|
|
|
|
|
editArea->setSceneRect(viewRect); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
newScene->setSceneRect(viewRect); |
|
|
newScene->setSceneRect(viewRect); |
|
|
m_pages.append(newScene); |
|
|
m_pages.append(newScene); |
|
|
m_currentPageIndex = m_pages.size() - 1; |
|
|
m_currentPageIndex = m_pages.size() - 1; |
|
|
|
|
|
|
|
|
QMetaObject::invokeMethod(this, [this, newScene]() { |
|
|
|
|
|
hmiEditArea->setScene(newScene); |
|
|
|
|
|
|
|
|
QMetaObject::invokeMethod(this, [this, newScene](){ |
|
|
|
|
|
editArea->setScene(newScene); |
|
|
initViewScale(); |
|
|
initViewScale(); |
|
|
updatePageLabel(); |
|
|
updatePageLabel(); |
|
|
hmiEditArea->viewport()->update(); |
|
|
|
|
|
|
|
|
editArea->viewport()->update(); |
|
|
}, Qt::QueuedConnection); |
|
|
}, Qt::QueuedConnection); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void HmiEditorWidget::refreshView() |
|
|
|
|
|
{ |
|
|
|
|
|
if (m_currentPageIndex >= 0 && !m_pages.isEmpty()) { |
|
|
|
|
|
hmiEditArea->setScene(nullptr); |
|
|
|
|
|
hmiEditArea->setScene(m_pages[m_currentPageIndex]); |
|
|
|
|
|
initViewScale(); |
|
|
|
|
|
hmiEditArea->viewport()->update(); |
|
|
|
|
|
|
|
|
void HmiEditorWidget::switchToPage(int index) { |
|
|
|
|
|
if (index >= 0 && index < m_pages.size()) { |
|
|
|
|
|
m_currentPageIndex = index; |
|
|
|
|
|
editArea->resetTransform(); |
|
|
|
|
|
editArea->setScene(m_pages[index]); |
|
|
|
|
|
updatePageLabel(); |
|
|
|
|
|
QMetaObject::invokeMethod(this, [this](){ |
|
|
|
|
|
initViewScale(); |
|
|
|
|
|
editArea->viewport()->update(); |
|
|
|
|
|
}, Qt::QueuedConnection); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void HmiEditorWidget::initViewScale() |
|
|
void HmiEditorWidget::initViewScale() |
|
|
{ |
|
|
{ |
|
|
if (!hmiEditArea || m_currentPageIndex < 0 || m_pages.isEmpty()) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (!editArea || m_currentPageIndex < 0 || m_pages.isEmpty()) return; |
|
|
|
|
|
|
|
|
QRect viewRect = hmiEditArea->viewport()->rect(); |
|
|
|
|
|
if (viewRect.isEmpty()) { |
|
|
|
|
|
viewRect = QRect(0, 0, 800, 600); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
QRect viewRect = editArea->viewport()->rect(); |
|
|
|
|
|
if (viewRect.isEmpty()) viewRect = QRect(0,0,800,600); |
|
|
|
|
|
|
|
|
QGraphicsScene* currentScene = m_pages[m_currentPageIndex]; |
|
|
|
|
|
currentScene->setSceneRect(viewRect); |
|
|
|
|
|
hmiEditArea->fitInView(viewRect, Qt::KeepAspectRatio); |
|
|
|
|
|
hmiEditArea->viewport()->update(); |
|
|
|
|
|
|
|
|
auto* currentScene = m_pages[m_currentPageIndex]; |
|
|
|
|
|
QRectF currentRect = currentScene->sceneRect(); |
|
|
|
|
|
const qreal newW = qMax(currentRect.width(), qreal(viewRect.width())); |
|
|
|
|
|
const qreal newH = qMax(currentRect.height(), qreal(viewRect.height())); |
|
|
|
|
|
currentScene->setSceneRect(0,0,newW,newH); |
|
|
|
|
|
|
|
|
|
|
|
editArea->viewport()->update(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void HmiEditorWidget::updatePageLabel() |
|
|
void HmiEditorWidget::updatePageLabel() |
|
@@ -161,51 +163,36 @@ void HmiEditorWidget::updatePageLabel() |
|
|
m_prevPageButton->setEnabled(false); |
|
|
m_prevPageButton->setEnabled(false); |
|
|
m_nextPageButton->setEnabled(false); |
|
|
m_nextPageButton->setEnabled(false); |
|
|
} else { |
|
|
} else { |
|
|
m_pageLabel->setText(QString("第 %1/%2 页").arg(m_currentPageIndex + 1).arg(m_pages.size())); |
|
|
|
|
|
m_deletePageButton->setEnabled(m_pages.size() > 1); |
|
|
|
|
|
m_prevPageButton->setEnabled(m_currentPageIndex > 0); |
|
|
|
|
|
m_nextPageButton->setEnabled(m_currentPageIndex < m_pages.size() - 1); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void HmiEditorWidget::switchToPage(int index) |
|
|
|
|
|
{ |
|
|
|
|
|
if (index >= 0 && index < m_pages.size()) { |
|
|
|
|
|
m_currentPageIndex = index; |
|
|
|
|
|
hmiEditArea->resetTransform(); |
|
|
|
|
|
hmiEditArea->setScene(m_pages[index]); |
|
|
|
|
|
|
|
|
|
|
|
QRectF sceneRect = m_pages[index]->sceneRect(); |
|
|
|
|
|
if (!sceneRect.isEmpty()) { |
|
|
|
|
|
hmiEditArea->fitInView(sceneRect, Qt::KeepAspectRatio); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
updatePageLabel(); |
|
|
|
|
|
QMetaObject::invokeMethod(this, [this]() { |
|
|
|
|
|
hmiEditArea->viewport()->update(); |
|
|
|
|
|
}, Qt::QueuedConnection); |
|
|
|
|
|
|
|
|
m_pageLabel->setText(QString("第 %1/%2 页").arg(m_currentPageIndex+1).arg(m_pages.size())); |
|
|
|
|
|
m_deletePageButton->setEnabled(m_pages.size()>1); |
|
|
|
|
|
m_prevPageButton->setEnabled(m_currentPageIndex>0); |
|
|
|
|
|
m_nextPageButton->setEnabled(m_currentPageIndex<m_pages.size()-1); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool HmiEditorWidget::eventFilter(QObject* obj, QEvent* event) |
|
|
bool HmiEditorWidget::eventFilter(QObject* obj, QEvent* event) |
|
|
{ |
|
|
{ |
|
|
if (obj == hmiEditArea && event->type() == QEvent::ContextMenu) { |
|
|
|
|
|
QContextMenuEvent* contextEvent = static_cast<QContextMenuEvent*>(event); |
|
|
|
|
|
|
|
|
// —— 右键空白处:弹出“粘贴”菜单(保留原逻辑) —— // |
|
|
|
|
|
if (obj == editArea && event->type() == QEvent::ContextMenu) { |
|
|
|
|
|
auto* contextEvent = static_cast<QContextMenuEvent*>(event); |
|
|
if (m_currentPageIndex >= 0 && m_pages[m_currentPageIndex]) { |
|
|
if (m_currentPageIndex >= 0 && m_pages[m_currentPageIndex]) { |
|
|
QGraphicsItem* item = hmiEditArea->itemAt(contextEvent->pos()); |
|
|
|
|
|
if (!item) { |
|
|
|
|
|
|
|
|
QGraphicsItem* hit = editArea->itemAt(contextEvent->pos()); |
|
|
|
|
|
if (!hit) { |
|
|
QMenu menu; |
|
|
QMenu menu; |
|
|
QAction* pasteAction = new QAction("粘贴", &menu); |
|
|
QAction* pasteAction = new QAction("粘贴", &menu); |
|
|
pasteAction->setEnabled(HmiControlItem::hasClipboardData()); |
|
|
pasteAction->setEnabled(HmiControlItem::hasClipboardData()); |
|
|
QObject::connect(pasteAction, &QAction::triggered, [this, contextEvent]() { |
|
|
|
|
|
if (m_currentPageIndex >= 0 && m_pages[m_currentPageIndex] && HmiControlItem::hasClipboardData()) { |
|
|
|
|
|
QPointF scenePos = hmiEditArea->mapToScene(contextEvent->pos()); |
|
|
|
|
|
HmiControlItem* newItem = HmiControlItem::createFromClipboard(HmiControlItem::getClipboardData(), scenePos); |
|
|
|
|
|
|
|
|
connect(pasteAction, &QAction::triggered, [this, contextEvent](){ |
|
|
|
|
|
if (m_currentPageIndex >= 0 && m_pages[m_currentPageIndex] && |
|
|
|
|
|
HmiControlItem::hasClipboardData()) { |
|
|
|
|
|
|
|
|
|
|
|
const QPointF scenePos = editArea->mapToScene(contextEvent->pos()); |
|
|
|
|
|
HmiControlItem* newItem = |
|
|
|
|
|
HmiControlItem::createFromClipboard(HmiControlItem::getClipboardData(), scenePos); |
|
|
if (newItem) { |
|
|
if (newItem) { |
|
|
m_pages[m_currentPageIndex]->addItem(newItem); |
|
|
m_pages[m_currentPageIndex]->addItem(newItem); |
|
|
m_pages[m_currentPageIndex]->clearSelection(); |
|
|
m_pages[m_currentPageIndex]->clearSelection(); |
|
|
newItem->setSelected(true); |
|
|
newItem->setSelected(true); |
|
|
hmiEditArea->viewport()->update(); |
|
|
|
|
|
|
|
|
editArea->viewport()->update(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
@@ -215,116 +202,167 @@ bool HmiEditorWidget::eventFilter(QObject* obj, QEvent* event) |
|
|
} |
|
|
} |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
return QWidget::eventFilter(obj, event); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void HmiEditorWidget::resizeEvent(QResizeEvent* event) |
|
|
|
|
|
{ |
|
|
|
|
|
QWidget::resizeEvent(event); |
|
|
|
|
|
if (m_currentPageIndex >= 0 && !m_pages.isEmpty()) { |
|
|
|
|
|
initViewScale(); |
|
|
|
|
|
|
|
|
// —— 关键改动:放置模式下,点击编辑区创建 —— // |
|
|
|
|
|
// 捕获 QGraphicsView 的 viewport 左键按下 |
|
|
|
|
|
if (obj == (editArea ? editArea->viewport() : nullptr) |
|
|
|
|
|
&& event->type() == QEvent::MouseButtonPress && !m_pendingType.isEmpty()) { |
|
|
|
|
|
|
|
|
|
|
|
auto* me = static_cast<QMouseEvent*>(event); |
|
|
|
|
|
if (me->button() == Qt::LeftButton |
|
|
|
|
|
&& m_currentPageIndex >= 0 |
|
|
|
|
|
&& m_pages[m_currentPageIndex]) { |
|
|
|
|
|
|
|
|
|
|
|
const QPointF scenePos = editArea->mapToScene(me->pos()); |
|
|
|
|
|
HmiControlItem* item = createItemByType(m_pendingType, scenePos); |
|
|
|
|
|
if (item) { |
|
|
|
|
|
m_pages[m_currentPageIndex]->addItem(item); |
|
|
|
|
|
m_pages[m_currentPageIndex]->clearSelection(); |
|
|
|
|
|
item->setSelected(true); |
|
|
|
|
|
editArea->viewport()->update(); |
|
|
|
|
|
} |
|
|
|
|
|
// 一次放一个:退出放置模式(如需连续放置,注释掉两行) |
|
|
|
|
|
m_pendingType.clear(); |
|
|
|
|
|
setPlacingCursor(false); |
|
|
|
|
|
|
|
|
|
|
|
return true; // 已处理 |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return EditorWidget::eventFilter(obj, event); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void HmiEditorWidget::resizeEvent(QResizeEvent* e) { |
|
|
|
|
|
EditorWidget::resizeEvent(e); |
|
|
|
|
|
if (m_currentPageIndex >= 0 && !m_pages.isEmpty()) initViewScale(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void HmiEditorWidget::showEvent(QShowEvent* e) { |
|
|
|
|
|
EditorWidget::showEvent(e); |
|
|
|
|
|
if (m_pages.isEmpty()) createNewPage(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void HmiEditorWidget::keyPressEvent(QKeyEvent* event) |
|
|
void HmiEditorWidget::keyPressEvent(QKeyEvent* event) |
|
|
{ |
|
|
{ |
|
|
|
|
|
// Ctrl+C:复制(保留原逻辑——复制首个选中项至静态剪贴板) |
|
|
if (event->matches(QKeySequence::Copy)) { |
|
|
if (event->matches(QKeySequence::Copy)) { |
|
|
if (m_currentPageIndex >= 0 && m_pages[m_currentPageIndex]) { |
|
|
if (m_currentPageIndex >= 0 && m_pages[m_currentPageIndex]) { |
|
|
auto selectedItems = m_pages[m_currentPageIndex]->selectedItems(); |
|
|
auto selectedItems = m_pages[m_currentPageIndex]->selectedItems(); |
|
|
if (!selectedItems.isEmpty()) { |
|
|
if (!selectedItems.isEmpty()) { |
|
|
HmiControlItem* item = dynamic_cast<HmiControlItem*>(selectedItems.first()); |
|
|
|
|
|
if (item) { |
|
|
|
|
|
|
|
|
if (auto* item = dynamic_cast<HmiControlItem*>(selectedItems.first())) { |
|
|
HmiControlItem::copyToClipboard(item->saveToClipboard()); |
|
|
HmiControlItem::copyToClipboard(item->saveToClipboard()); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
return; |
|
|
} |
|
|
} |
|
|
else if (event->matches(QKeySequence::Paste)) { |
|
|
|
|
|
if (m_currentPageIndex >= 0 && m_pages[m_currentPageIndex] && HmiControlItem::hasClipboardData()) { |
|
|
|
|
|
QRectF sceneRect = m_pages[m_currentPageIndex]->sceneRect(); |
|
|
|
|
|
QPointF centerPos(sceneRect.width() / 2, sceneRect.height() / 2); |
|
|
|
|
|
HmiControlItem* newItem = HmiControlItem::createFromClipboard(HmiControlItem::getClipboardData(), centerPos); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Ctrl+V:粘贴(关键改动:若有选中源控件 → 旁边粘贴;否则 → 场景中心) |
|
|
|
|
|
if (event->matches(QKeySequence::Paste)) { |
|
|
|
|
|
if (m_currentPageIndex >= 0 && |
|
|
|
|
|
m_pages[m_currentPageIndex] && |
|
|
|
|
|
HmiControlItem::hasClipboardData()) { |
|
|
|
|
|
|
|
|
|
|
|
QPointF pastePos; |
|
|
|
|
|
auto selectedItems = m_pages[m_currentPageIndex]->selectedItems(); |
|
|
|
|
|
static int s_pasteIndex = 0; // 连续多次粘贴时,用来轻微错行 |
|
|
|
|
|
|
|
|
|
|
|
if (!selectedItems.isEmpty()) { |
|
|
|
|
|
if (auto* src = dynamic_cast<HmiControlItem*>(selectedItems.first())) { |
|
|
|
|
|
pastePos = calcPasteBesidePos(src, s_pasteIndex++); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
// 无选中项:仍按原逻辑 → 场景中心 |
|
|
|
|
|
QRectF rect = m_pages[m_currentPageIndex]->sceneRect(); |
|
|
|
|
|
pastePos = QPointF(rect.width()/2, rect.height()/2); |
|
|
|
|
|
s_pasteIndex = 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
HmiControlItem* newItem = |
|
|
|
|
|
HmiControlItem::createFromClipboard(HmiControlItem::getClipboardData(), pastePos); |
|
|
if (newItem) { |
|
|
if (newItem) { |
|
|
m_pages[m_currentPageIndex]->addItem(newItem); |
|
|
m_pages[m_currentPageIndex]->addItem(newItem); |
|
|
m_pages[m_currentPageIndex]->clearSelection(); |
|
|
m_pages[m_currentPageIndex]->clearSelection(); |
|
|
newItem->setSelected(true); |
|
|
newItem->setSelected(true); |
|
|
hmiEditArea->viewport()->update(); |
|
|
|
|
|
|
|
|
editArea->viewport()->update(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
return; |
|
|
} |
|
|
} |
|
|
else if (event->matches(QKeySequence::Delete)) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Delete:删除(保留原逻辑) |
|
|
|
|
|
if (event->matches(QKeySequence::Delete)) { |
|
|
if (m_currentPageIndex >= 0 && m_pages[m_currentPageIndex]) { |
|
|
if (m_currentPageIndex >= 0 && m_pages[m_currentPageIndex]) { |
|
|
auto selectedItems = m_pages[m_currentPageIndex]->selectedItems(); |
|
|
auto selectedItems = m_pages[m_currentPageIndex]->selectedItems(); |
|
|
for (QGraphicsItem* item : selectedItems) { |
|
|
|
|
|
HmiControlItem* controlItem = dynamic_cast<HmiControlItem*>(item); |
|
|
|
|
|
if (controlItem) { |
|
|
|
|
|
controlItem->deleteItem(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
for (QGraphicsItem* gi : selectedItems) { |
|
|
|
|
|
if (auto* ci = dynamic_cast<HmiControlItem*>(gi)) ci->deleteItem(); |
|
|
} |
|
|
} |
|
|
hmiEditArea->viewport()->update(); |
|
|
|
|
|
|
|
|
editArea->viewport()->update(); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
QWidget::keyPressEvent(event); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void HmiEditorWidget::onToolbarItemClicked(QListWidgetItem* item) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!item || m_currentPageIndex < 0 || !m_pages[m_currentPageIndex]) return; |
|
|
|
|
|
|
|
|
|
|
|
QString type = item->data(Qt::UserRole).toString(); |
|
|
|
|
|
HmiControlItem* newItem = nullptr; |
|
|
|
|
|
if (type == "按钮") { |
|
|
|
|
|
newItem = new HmiButton(); |
|
|
|
|
|
} else if (type == "指示灯") { |
|
|
|
|
|
newItem = new HmiLed(); |
|
|
|
|
|
|
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (newItem) { |
|
|
|
|
|
QRectF sceneRect = m_pages[m_currentPageIndex]->sceneRect(); |
|
|
|
|
|
newItem->setPos(sceneRect.width() / 2, sceneRect.height() / 2); |
|
|
|
|
|
m_pages[m_currentPageIndex]->addItem(newItem); |
|
|
|
|
|
m_pages[m_currentPageIndex]->clearSelection(); |
|
|
|
|
|
newItem->setSelected(true); |
|
|
|
|
|
hmiEditArea->viewport()->update(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
EditorWidget::keyPressEvent(event); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void HmiEditorWidget::onNewPageClicked() |
|
|
|
|
|
{ |
|
|
|
|
|
createNewPage(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void HmiEditorWidget::onNewPageClicked() { createNewPage(); } |
|
|
|
|
|
|
|
|
void HmiEditorWidget::onDeletePageClicked() |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
void HmiEditorWidget::onDeletePageClicked() { |
|
|
if (m_currentPageIndex >= 0 && m_pages.size() > 1) { |
|
|
if (m_currentPageIndex >= 0 && m_pages.size() > 1) { |
|
|
QGraphicsScene* scene = m_pages[m_currentPageIndex]; |
|
|
QGraphicsScene* scene = m_pages[m_currentPageIndex]; |
|
|
m_pages.removeAt(m_currentPageIndex); |
|
|
m_pages.removeAt(m_currentPageIndex); |
|
|
delete scene; |
|
|
delete scene; |
|
|
m_currentPageIndex = qMin(m_currentPageIndex, m_pages.size() - 1); |
|
|
|
|
|
hmiEditArea->setScene(m_pages[m_currentPageIndex]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_currentPageIndex = qMin(m_currentPageIndex, m_pages.size()-1); |
|
|
|
|
|
editArea->setScene(m_pages[m_currentPageIndex]); |
|
|
initViewScale(); |
|
|
initViewScale(); |
|
|
updatePageLabel(); |
|
|
updatePageLabel(); |
|
|
hmiEditArea->viewport()->update(); |
|
|
|
|
|
|
|
|
editArea->viewport()->update(); |
|
|
|
|
|
appendOutput(QString("删除页面,剩余页面数: %1").arg(m_pages.size())); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void HmiEditorWidget::onPreviousPageClicked() |
|
|
|
|
|
|
|
|
void HmiEditorWidget::onPreviousPageClicked() { switchToPage(m_currentPageIndex - 1); } |
|
|
|
|
|
void HmiEditorWidget::onNextPageClicked() { switchToPage(m_currentPageIndex + 1); } |
|
|
|
|
|
|
|
|
|
|
|
// —— 私有辅助 —— // |
|
|
|
|
|
|
|
|
|
|
|
HmiControlItem* HmiEditorWidget::createItemByType(const QString& type, const QPointF& scenePos) |
|
|
{ |
|
|
{ |
|
|
switchToPage(m_currentPageIndex - 1); |
|
|
|
|
|
|
|
|
HmiControlItem* item = nullptr; |
|
|
|
|
|
if (type == "按钮") { |
|
|
|
|
|
item = new HmiButton(); |
|
|
|
|
|
appendOutput("添加按钮控件"); |
|
|
|
|
|
} else if (type == "指示灯") { |
|
|
|
|
|
item = new HmiLed(); |
|
|
|
|
|
appendOutput("添加指示灯控件"); |
|
|
|
|
|
} |
|
|
|
|
|
if (item) item->setPos(scenePos); |
|
|
|
|
|
return item; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void HmiEditorWidget::onNextPageClicked() |
|
|
|
|
|
|
|
|
void HmiEditorWidget::setPlacingCursor(bool on) |
|
|
{ |
|
|
{ |
|
|
switchToPage(m_currentPageIndex + 1); |
|
|
|
|
|
|
|
|
if (!editArea) return; |
|
|
|
|
|
if (on) { |
|
|
|
|
|
editArea->setCursor(Qt::CrossCursor); |
|
|
|
|
|
if (editArea->viewport()) editArea->viewport()->setCursor(Qt::CrossCursor); |
|
|
|
|
|
} else { |
|
|
|
|
|
editArea->unsetCursor(); |
|
|
|
|
|
if (editArea->viewport()) editArea->viewport()->unsetCursor(); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void HmiEditorWidget::clearPages() |
|
|
|
|
|
|
|
|
QPointF HmiEditorWidget::calcPasteBesidePos(HmiControlItem* src, int pasteIndex) const |
|
|
{ |
|
|
{ |
|
|
for (QGraphicsScene* scene : m_pages) { |
|
|
|
|
|
delete scene; |
|
|
|
|
|
} |
|
|
|
|
|
m_pages.clear(); |
|
|
|
|
|
m_currentPageIndex = -1; |
|
|
|
|
|
hmiEditArea->setScene(nullptr); |
|
|
|
|
|
updatePageLabel(); |
|
|
|
|
|
|
|
|
if (!src) return QPointF(); |
|
|
|
|
|
|
|
|
|
|
|
// 使用“映射到场景后的边界框”来获取可视宽度,避免缩放带来的误差 |
|
|
|
|
|
QRectF sceneRect = src->mapToScene(src->boundingRect()).boundingRect(); |
|
|
|
|
|
const qreal w = qMax<qreal>(sceneRect.width(), 24.0); // 保底宽度 |
|
|
|
|
|
const qreal gap = 12.0; // 与原件的水平间隔 |
|
|
|
|
|
const qreal stepY = 8.0; // 连续粘贴时的竖向微调 |
|
|
|
|
|
|
|
|
|
|
|
QPointF base = src->pos(); |
|
|
|
|
|
return QPointF(base.x() + w + gap, base.y() + pasteIndex * stepY); |
|
|
} |
|
|
} |