您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

331 行
11 KiB

  1. #include "hmieditorwidget.h"
  2. #include "hmiwidgetfactory.h"
  3. #include <QHBoxLayout>
  4. #include <QVBoxLayout>
  5. #include <QGraphicsScene>
  6. #include <QGraphicsView>
  7. #include <QDebug>
  8. #include <QKeyEvent>
  9. #include <QMouseEvent>
  10. #include <QMenu>
  11. #include <QTimer>
  12. #include <QCoreApplication>
  13. #include <QMetaObject>
  14. #include "hmicontrolitem.h"
  15. HmiEditorWidget::HmiEditorWidget(QWidget* parent)
  16. : QWidget(parent)
  17. {
  18. QHBoxLayout* mainLayout = new QHBoxLayout(this);
  19. mainLayout->setContentsMargins(10, 10, 10, 10);
  20. mainLayout->setSpacing(10);
  21. QVBoxLayout* leftLayout = new QVBoxLayout();
  22. leftLayout->setSpacing(5);
  23. hmiToolbar = new QListWidget(this);
  24. hmiToolbar->setViewMode(QListWidget::IconMode);
  25. hmiToolbar->setIconSize(QSize(48, 48));
  26. hmiToolbar->setFixedWidth(100);
  27. hmiToolbar->setSpacing(10);
  28. hmiToolbar->setDragEnabled(false);
  29. QListWidgetItem* buttonItem = new QListWidgetItem();
  30. buttonItem->setIcon(QIcon(":resource/image/button.png"));
  31. buttonItem->setData(Qt::UserRole, QString("按钮"));
  32. buttonItem->setToolTip("按钮");
  33. hmiToolbar->addItem(buttonItem);
  34. QListWidgetItem* ledItem = new QListWidgetItem();
  35. ledItem->setIcon(QIcon(":resource/image/light.png"));
  36. ledItem->setData(Qt::UserRole, QString("指示灯"));
  37. ledItem->setToolTip("指示灯");
  38. hmiToolbar->addItem(ledItem);
  39. leftLayout->addWidget(hmiToolbar);
  40. m_newPageButton = new QPushButton("新建页面", this);
  41. m_deletePageButton = new QPushButton("删除页面", this);
  42. m_prevPageButton = new QPushButton("上一页", this);
  43. m_nextPageButton = new QPushButton("下一页", this);
  44. m_pageLabel = new QLabel("无页面", this);
  45. leftLayout->addWidget(m_newPageButton);
  46. leftLayout->addWidget(m_deletePageButton);
  47. leftLayout->addWidget(m_prevPageButton);
  48. leftLayout->addWidget(m_nextPageButton);
  49. leftLayout->addWidget(m_pageLabel);
  50. leftLayout->addStretch();
  51. mainLayout->addLayout(leftLayout);
  52. hmiEditArea = new QGraphicsView(this);
  53. hmiEditArea->setRenderHint(QPainter::Antialiasing);
  54. hmiEditArea->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
  55. hmiEditArea->setOptimizationFlags(QGraphicsView::DontSavePainterState | QGraphicsView::DontAdjustForAntialiasing);
  56. hmiEditArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  57. hmiEditArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  58. mainLayout->addWidget(hmiEditArea, 1);
  59. hmiEditArea->installEventFilter(this);
  60. connect(hmiToolbar, &QListWidget::itemClicked, this, &HmiEditorWidget::onToolbarItemClicked);
  61. connect(m_newPageButton, &QPushButton::clicked, this, &HmiEditorWidget::onNewPageClicked);
  62. connect(m_deletePageButton, &QPushButton::clicked, this, &HmiEditorWidget::onDeletePageClicked);
  63. connect(m_prevPageButton, &QPushButton::clicked, this, &HmiEditorWidget::onPreviousPageClicked);
  64. connect(m_nextPageButton, &QPushButton::clicked, this, &HmiEditorWidget::onNextPageClicked);
  65. ensureViewReady();
  66. }
  67. HmiEditorWidget::~HmiEditorWidget()
  68. {
  69. clearPages();
  70. }
  71. void HmiEditorWidget::ensureViewReady()
  72. {
  73. QCoreApplication::processEvents();
  74. hmiEditArea->resetTransform();
  75. hmiEditArea->viewport()->update();
  76. if (hmiEditArea->viewport()->rect().isEmpty()) {
  77. hmiEditArea->setFixedSize(600, 400);
  78. QCoreApplication::processEvents();
  79. }
  80. }
  81. void HmiEditorWidget::showEvent(QShowEvent* event)
  82. {
  83. QWidget::showEvent(event);
  84. if (m_firstShow && m_pages.isEmpty()) {
  85. m_firstShow = false;
  86. createNewPage();
  87. }
  88. }
  89. void HmiEditorWidget::createNewPage()
  90. {
  91. QGraphicsScene* newScene = new QGraphicsScene(this);
  92. QRect viewRect = hmiEditArea->viewport()->rect();
  93. if (viewRect.isEmpty()) {
  94. viewRect = QRect(0, 0, 800, 600);
  95. hmiEditArea->setSceneRect(viewRect);
  96. }
  97. newScene->setSceneRect(viewRect);
  98. m_pages.append(newScene);
  99. m_currentPageIndex = m_pages.size() - 1;
  100. QMetaObject::invokeMethod(this, [this, newScene]() {
  101. hmiEditArea->setScene(newScene);
  102. initViewScale();
  103. updatePageLabel();
  104. hmiEditArea->viewport()->update();
  105. }, Qt::QueuedConnection);
  106. }
  107. void HmiEditorWidget::refreshView()
  108. {
  109. if (m_currentPageIndex >= 0 && !m_pages.isEmpty()) {
  110. hmiEditArea->setScene(nullptr);
  111. hmiEditArea->setScene(m_pages[m_currentPageIndex]);
  112. initViewScale();
  113. hmiEditArea->viewport()->update();
  114. }
  115. }
  116. void HmiEditorWidget::initViewScale()
  117. {
  118. if (!hmiEditArea || m_currentPageIndex < 0 || m_pages.isEmpty()) {
  119. return;
  120. }
  121. QRect viewRect = hmiEditArea->viewport()->rect();
  122. if (viewRect.isEmpty()) {
  123. viewRect = QRect(0, 0, 800, 600);
  124. }
  125. QGraphicsScene* currentScene = m_pages[m_currentPageIndex];
  126. currentScene->setSceneRect(viewRect);
  127. hmiEditArea->fitInView(viewRect, Qt::KeepAspectRatio);
  128. hmiEditArea->viewport()->update();
  129. }
  130. void HmiEditorWidget::updatePageLabel()
  131. {
  132. if (m_pages.isEmpty()) {
  133. m_pageLabel->setText("无页面");
  134. m_deletePageButton->setEnabled(false);
  135. m_prevPageButton->setEnabled(false);
  136. m_nextPageButton->setEnabled(false);
  137. } else {
  138. m_pageLabel->setText(QString("第 %1/%2 页").arg(m_currentPageIndex + 1).arg(m_pages.size()));
  139. m_deletePageButton->setEnabled(m_pages.size() > 1);
  140. m_prevPageButton->setEnabled(m_currentPageIndex > 0);
  141. m_nextPageButton->setEnabled(m_currentPageIndex < m_pages.size() - 1);
  142. }
  143. }
  144. void HmiEditorWidget::switchToPage(int index)
  145. {
  146. if (index >= 0 && index < m_pages.size()) {
  147. m_currentPageIndex = index;
  148. hmiEditArea->resetTransform();
  149. hmiEditArea->setScene(m_pages[index]);
  150. QRectF sceneRect = m_pages[index]->sceneRect();
  151. if (!sceneRect.isEmpty()) {
  152. hmiEditArea->fitInView(sceneRect, Qt::KeepAspectRatio);
  153. }
  154. updatePageLabel();
  155. QMetaObject::invokeMethod(this, [this]() {
  156. hmiEditArea->viewport()->update();
  157. }, Qt::QueuedConnection);
  158. }
  159. }
  160. bool HmiEditorWidget::eventFilter(QObject* obj, QEvent* event)
  161. {
  162. if (obj == hmiEditArea && event->type() == QEvent::ContextMenu) {
  163. QContextMenuEvent* contextEvent = static_cast<QContextMenuEvent*>(event);
  164. if (m_currentPageIndex >= 0 && m_pages[m_currentPageIndex]) {
  165. QGraphicsItem* item = hmiEditArea->itemAt(contextEvent->pos());
  166. if (!item) {
  167. QMenu menu;
  168. QAction* pasteAction = new QAction("粘贴", &menu);
  169. pasteAction->setEnabled(HmiControlItem::hasClipboardData());
  170. QObject::connect(pasteAction, &QAction::triggered, [this, contextEvent]() {
  171. if (m_currentPageIndex >= 0 && m_pages[m_currentPageIndex] && HmiControlItem::hasClipboardData()) {
  172. QPointF scenePos = hmiEditArea->mapToScene(contextEvent->pos());
  173. HmiControlItem* newItem = HmiControlItem::createFromClipboard(HmiControlItem::getClipboardData(), scenePos);
  174. if (newItem) {
  175. m_pages[m_currentPageIndex]->addItem(newItem);
  176. m_pages[m_currentPageIndex]->clearSelection();
  177. newItem->setSelected(true);
  178. hmiEditArea->viewport()->update();
  179. }
  180. }
  181. });
  182. menu.addAction(pasteAction);
  183. menu.exec(contextEvent->globalPos());
  184. }
  185. }
  186. return true;
  187. }
  188. return QWidget::eventFilter(obj, event);
  189. }
  190. void HmiEditorWidget::resizeEvent(QResizeEvent* event)
  191. {
  192. QWidget::resizeEvent(event);
  193. if (m_currentPageIndex >= 0 && !m_pages.isEmpty()) {
  194. initViewScale();
  195. }
  196. }
  197. void HmiEditorWidget::keyPressEvent(QKeyEvent* event)
  198. {
  199. if (event->matches(QKeySequence::Copy)) {
  200. if (m_currentPageIndex >= 0 && m_pages[m_currentPageIndex]) {
  201. auto selectedItems = m_pages[m_currentPageIndex]->selectedItems();
  202. if (!selectedItems.isEmpty()) {
  203. HmiControlItem* item = dynamic_cast<HmiControlItem*>(selectedItems.first());
  204. if (item) {
  205. HmiControlItem::copyToClipboard(item->saveToClipboard());
  206. }
  207. }
  208. }
  209. }
  210. else if (event->matches(QKeySequence::Paste)) {
  211. if (m_currentPageIndex >= 0 && m_pages[m_currentPageIndex] && HmiControlItem::hasClipboardData()) {
  212. QRectF sceneRect = m_pages[m_currentPageIndex]->sceneRect();
  213. QPointF centerPos(sceneRect.width() / 2, sceneRect.height() / 2);
  214. HmiControlItem* newItem = HmiControlItem::createFromClipboard(HmiControlItem::getClipboardData(), centerPos);
  215. if (newItem) {
  216. m_pages[m_currentPageIndex]->addItem(newItem);
  217. m_pages[m_currentPageIndex]->clearSelection();
  218. newItem->setSelected(true);
  219. hmiEditArea->viewport()->update();
  220. }
  221. }
  222. }
  223. else if (event->matches(QKeySequence::Delete)) {
  224. if (m_currentPageIndex >= 0 && m_pages[m_currentPageIndex]) {
  225. auto selectedItems = m_pages[m_currentPageIndex]->selectedItems();
  226. for (QGraphicsItem* item : selectedItems) {
  227. HmiControlItem* controlItem = dynamic_cast<HmiControlItem*>(item);
  228. if (controlItem) {
  229. controlItem->deleteItem();
  230. }
  231. }
  232. hmiEditArea->viewport()->update();
  233. }
  234. }
  235. QWidget::keyPressEvent(event);
  236. }
  237. void HmiEditorWidget::onToolbarItemClicked(QListWidgetItem* item)
  238. {
  239. if (!item || m_currentPageIndex < 0 || !m_pages[m_currentPageIndex]) return;
  240. QString type = item->data(Qt::UserRole).toString();
  241. HmiControlItem* newItem = nullptr;
  242. if (type == "按钮") {
  243. newItem = new HmiButton();
  244. } else if (type == "指示灯") {
  245. newItem = new HmiLed();
  246. }
  247. if (newItem) {
  248. QRectF sceneRect = m_pages[m_currentPageIndex]->sceneRect();
  249. newItem->setPos(sceneRect.width() / 2, sceneRect.height() / 2);
  250. m_pages[m_currentPageIndex]->addItem(newItem);
  251. m_pages[m_currentPageIndex]->clearSelection();
  252. newItem->setSelected(true);
  253. hmiEditArea->viewport()->update();
  254. }
  255. }
  256. void HmiEditorWidget::onNewPageClicked()
  257. {
  258. createNewPage();
  259. }
  260. void HmiEditorWidget::onDeletePageClicked()
  261. {
  262. if (m_currentPageIndex >= 0 && m_pages.size() > 1) {
  263. QGraphicsScene* scene = m_pages[m_currentPageIndex];
  264. m_pages.removeAt(m_currentPageIndex);
  265. delete scene;
  266. m_currentPageIndex = qMin(m_currentPageIndex, m_pages.size() - 1);
  267. hmiEditArea->setScene(m_pages[m_currentPageIndex]);
  268. initViewScale();
  269. updatePageLabel();
  270. hmiEditArea->viewport()->update();
  271. }
  272. }
  273. void HmiEditorWidget::onPreviousPageClicked()
  274. {
  275. switchToPage(m_currentPageIndex - 1);
  276. }
  277. void HmiEditorWidget::onNextPageClicked()
  278. {
  279. switchToPage(m_currentPageIndex + 1);
  280. }
  281. void HmiEditorWidget::clearPages()
  282. {
  283. for (QGraphicsScene* scene : m_pages) {
  284. delete scene;
  285. }
  286. m_pages.clear();
  287. m_currentPageIndex = -1;
  288. hmiEditArea->setScene(nullptr);
  289. updatePageLabel();
  290. }