| @@ -23,6 +23,7 @@ SOURCES += \ | |||
| src/ui/plc_connection_dialog.cpp \ | |||
| src/ui/free_monitor_widget.cpp \ | |||
| src/ui/runtime_monitor_widget.cpp \ | |||
| src/ui/toolbar_icon_factory.cpp \ | |||
| src/ui/project_workspace_controller.cpp \ | |||
| src/ui/property_panel_controller.cpp \ | |||
| src/ui/runtime_panel_controller.cpp \ | |||
| @@ -63,6 +64,7 @@ HEADERS += \ | |||
| src/ui/plc_connection_dialog.h \ | |||
| src/ui/free_monitor_widget.h \ | |||
| src/ui/runtime_monitor_widget.h \ | |||
| src/ui/toolbar_icon_factory.h \ | |||
| src/ui/project_workspace_controller.h \ | |||
| src/ui/property_panel_controller.h \ | |||
| src/ui/runtime_panel_controller.h \ | |||
| @@ -1,11 +1,11 @@ | |||
| #include "free_monitor_widget.h" | |||
| #include "services/register_monitor_service.h" | |||
| #include "toolbar_icon_factory.h" | |||
| #include "ui_free_monitor_widget.h" | |||
| #include <QHeaderView> | |||
| #include <QMessageBox> | |||
| #include <QStyle> | |||
| #include <QTableWidgetItem> | |||
| #include <set> | |||
| @@ -32,8 +32,8 @@ FreeMonitorWidget::FreeMonitorWidget( | |||
| service_(service) | |||
| { | |||
| ui_->setupUi(this); | |||
| ui_->removeButton->setIcon(style()->standardIcon(QStyle::SP_TrashIcon)); | |||
| ui_->clearButton->setIcon(style()->standardIcon(QStyle::SP_DialogResetButton)); | |||
| ui_->removeButton->setIcon(makeUiIcon(UiIcon::Delete)); | |||
| ui_->clearButton->setIcon(makeUiIcon(UiIcon::ClearList)); | |||
| ui_->monitorTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents); | |||
| ui_->monitorTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents); | |||
| ui_->monitorTable->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch); | |||
| @@ -7,6 +7,7 @@ | |||
| #include "logic_instruction_dialog.h" | |||
| #include "plc_connection_dialog.h" | |||
| #include "runtime_monitor_widget.h" | |||
| #include "toolbar_icon_factory.h" | |||
| #include "project_workspace_controller.h" | |||
| #include "property_panel_controller.h" | |||
| #include "runtime_panel_controller.h" | |||
| @@ -26,12 +27,13 @@ | |||
| #include <QApplication> | |||
| #include <QFileDialog> | |||
| #include <QInputDialog> | |||
| #include <QIcon> | |||
| #include <QLabel> | |||
| #include <QMessageBox> | |||
| #include <QMenu> | |||
| #include <QStatusBar> | |||
| #include <QStyle> | |||
| #include <QTabWidget> | |||
| #include <QToolBar> | |||
| #include <QToolButton> | |||
| namespace { | |||
| @@ -135,6 +137,27 @@ QString plcStatusText(const RuntimeModeService &service) | |||
| } | |||
| } | |||
| QToolButton *addToolbarMenu( | |||
| QToolBar *toolbar, | |||
| const QString &text, | |||
| const QString &object_name, | |||
| const QIcon &icon, | |||
| const QList<QAction *> &actions) | |||
| { | |||
| auto *button = new QToolButton(toolbar); | |||
| button->setObjectName(object_name); | |||
| button->setText(text); | |||
| button->setIcon(icon); | |||
| button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); | |||
| button->setPopupMode(QToolButton::InstantPopup); | |||
| auto *menu = new QMenu(button); | |||
| menu->addActions(actions); | |||
| button->setMenu(menu); | |||
| toolbar->addWidget(button); | |||
| return button; | |||
| } | |||
| } // namespace | |||
| MainWindow::MainWindow( | |||
| @@ -289,6 +312,16 @@ void MainWindow::configureActions() | |||
| [this] { addHmiControl(HmiControlType::AlarmList); }); | |||
| connect(ui_->deleteControlAction, &QAction::triggered, | |||
| this, &MainWindow::deleteSelectedControl); | |||
| addToolbarMenu( | |||
| ui_->hmiToolBar, | |||
| tr("更多控件"), | |||
| QStringLiteral("hmiMoreControlsButton"), | |||
| makeUiIcon(UiIcon::More), | |||
| QList<QAction *>{ | |||
| ui_->addProgressBarAction, | |||
| ui_->addPageJumpAction, | |||
| ui_->addAlarmListAction, | |||
| ui_->configureAlarmsAction}); | |||
| connect(ui_->addRungAction, &QAction::triggered, | |||
| this, &MainWindow::addLogicRung); | |||
| @@ -525,6 +558,38 @@ void MainWindow::configureActions() | |||
| this, &MainWindow::deleteSelectedLogicObject); | |||
| connect(ui_->editRungCommentAction, &QAction::triggered, | |||
| this, &MainWindow::editSelectedRungComment); | |||
| addToolbarMenu( | |||
| ui_->logicToolBar, | |||
| tr("更多触点"), | |||
| QStringLiteral("logicContactMenuButton"), | |||
| makeUiIcon(UiIcon::NormallyOpenContact), | |||
| QList<QAction *>{ | |||
| ui_->addRisingEdgeAction, | |||
| ui_->addFallingEdgeAction, | |||
| ui_->addTimerContactAction, | |||
| ui_->addCounterContactAction}); | |||
| addToolbarMenu( | |||
| ui_->logicToolBar, | |||
| tr("更多输出"), | |||
| QStringLiteral("logicOutputMenuButton"), | |||
| makeUiIcon(UiIcon::Coil), | |||
| QList<QAction *>{ui_->addSetCoilAction, ui_->addResetCoilAction}); | |||
| addToolbarMenu( | |||
| ui_->logicToolBar, | |||
| tr("定时/计数"), | |||
| QStringLiteral("logicTimerCounterMenuButton"), | |||
| makeUiIcon(UiIcon::Ton), | |||
| QList<QAction *>{ui_->addTonAction, ui_->addCtuAction, ui_->addCtdAction}); | |||
| addToolbarMenu( | |||
| ui_->logicToolBar, | |||
| tr("数据运算"), | |||
| QStringLiteral("logicDataMenuButton"), | |||
| makeUiIcon(UiIcon::Move), | |||
| QList<QAction *>{ | |||
| ui_->addMoveAction, | |||
| ui_->addAddAction, | |||
| ui_->addSubAction, | |||
| ui_->addCompareAction}); | |||
| connect(ui_->editorTabWidget, &QTabWidget::currentChanged, | |||
| this, | |||
| @@ -564,54 +629,51 @@ void MainWindow::configureAppearance() | |||
| setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); | |||
| setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); | |||
| ui_->editingModeAction->setIcon(style()->standardIcon(QStyle::SP_FileDialogDetailedView)); | |||
| ui_->offlineModeAction->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); | |||
| ui_->onlineModeAction->setIcon(style()->standardIcon(QStyle::SP_DriveNetIcon)); | |||
| ui_->newProjectAction->setIcon(style()->standardIcon(QStyle::SP_FileIcon)); | |||
| ui_->saveProjectAction->setIcon(style()->standardIcon(QStyle::SP_DialogSaveButton)); | |||
| ui_->loadProjectAction->setIcon(style()->standardIcon(QStyle::SP_DialogOpenButton)); | |||
| ui_->configurePlcAction->setIcon(style()->standardIcon(QStyle::SP_ComputerIcon)); | |||
| ui_->disconnectPlcAction->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton)); | |||
| ui_->addButtonAction->setIcon(style()->standardIcon(QStyle::SP_DialogApplyButton)); | |||
| ui_->addIndicatorAction->setIcon(style()->standardIcon(QStyle::SP_DialogYesButton)); | |||
| ui_->addNumericDisplayAction->setIcon( | |||
| style()->standardIcon(QStyle::SP_FileDialogInfoView)); | |||
| ui_->addNumericInputAction->setIcon( | |||
| style()->standardIcon(QStyle::SP_FileDialogContentsView)); | |||
| ui_->addProgressBarAction->setIcon( | |||
| style()->standardIcon(QStyle::SP_MediaSeekForward)); | |||
| ui_->addLabelAction->setIcon( | |||
| style()->standardIcon(QStyle::SP_FileDialogInfoView)); | |||
| ui_->addPageJumpAction->setIcon( | |||
| style()->standardIcon(QStyle::SP_ArrowForward)); | |||
| ui_->addAlarmListAction->setIcon( | |||
| style()->standardIcon(QStyle::SP_MessageBoxWarning)); | |||
| ui_->configureAlarmsAction->setIcon( | |||
| style()->standardIcon(QStyle::SP_FileDialogDetailedView)); | |||
| ui_->deleteControlAction->setIcon(style()->standardIcon(QStyle::SP_TrashIcon)); | |||
| ui_->addRungAction->setIcon(style()->standardIcon(QStyle::SP_FileIcon)); | |||
| ui_->parallelInsertAction->setIcon(style()->standardIcon(QStyle::SP_ArrowDown)); | |||
| ui_->addNormallyOpenAction->setIcon(style()->standardIcon(QStyle::SP_ArrowRight)); | |||
| ui_->addNormallyClosedAction->setIcon(style()->standardIcon(QStyle::SP_ArrowRight)); | |||
| ui_->addRisingEdgeAction->setIcon(style()->standardIcon(QStyle::SP_ArrowRight)); | |||
| ui_->addFallingEdgeAction->setIcon(style()->standardIcon(QStyle::SP_ArrowRight)); | |||
| ui_->addTimerContactAction->setIcon(style()->standardIcon(QStyle::SP_ArrowRight)); | |||
| ui_->addCounterContactAction->setIcon(style()->standardIcon(QStyle::SP_ArrowRight)); | |||
| ui_->addNormalCoilAction->setIcon(style()->standardIcon(QStyle::SP_DialogApplyButton)); | |||
| ui_->addSetCoilAction->setIcon(style()->standardIcon(QStyle::SP_DialogYesButton)); | |||
| ui_->addResetCoilAction->setIcon(style()->standardIcon(QStyle::SP_DialogNoButton)); | |||
| ui_->addTonAction->setIcon(style()->standardIcon(QStyle::SP_BrowserReload)); | |||
| ui_->addCtuAction->setIcon(style()->standardIcon(QStyle::SP_ArrowUp)); | |||
| ui_->addCtdAction->setIcon(style()->standardIcon(QStyle::SP_ArrowDown)); | |||
| ui_->addMoveAction->setIcon(style()->standardIcon(QStyle::SP_ArrowForward)); | |||
| ui_->addAddAction->setIcon(style()->standardIcon(QStyle::SP_DialogApplyButton)); | |||
| ui_->addSubAction->setIcon(style()->standardIcon(QStyle::SP_DialogResetButton)); | |||
| ui_->addCompareAction->setIcon(style()->standardIcon(QStyle::SP_FileDialogInfoView)); | |||
| ui_->editRungCommentAction->setIcon(style()->standardIcon(QStyle::SP_FileDialogDetailedView)); | |||
| ui_->deleteLogicAction->setIcon(style()->standardIcon(QStyle::SP_TrashIcon)); | |||
| ui_->editorTabWidget->setTabIcon(0, style()->standardIcon(QStyle::SP_DesktopIcon)); | |||
| ui_->editorTabWidget->setTabIcon(1, style()->standardIcon(QStyle::SP_FileDialogListView)); | |||
| ui_->editorTabWidget->setTabIcon(2, style()->standardIcon(QStyle::SP_ComputerIcon)); | |||
| ui_->editingModeAction->setIcon(makeUiIcon(UiIcon::Edit)); | |||
| ui_->offlineModeAction->setIcon(makeUiIcon(UiIcon::RunOffline)); | |||
| ui_->onlineModeAction->setIcon(makeUiIcon(UiIcon::RunOnline)); | |||
| ui_->newProjectAction->setIcon(makeUiIcon(UiIcon::NewDocument)); | |||
| ui_->saveProjectAction->setIcon(makeUiIcon(UiIcon::Save)); | |||
| ui_->saveAsProjectAction->setIcon(makeUiIcon(UiIcon::SaveAs)); | |||
| ui_->loadProjectAction->setIcon(makeUiIcon(UiIcon::Open)); | |||
| ui_->exitAction->setIcon(makeUiIcon(UiIcon::Exit)); | |||
| ui_->configurePlcAction->setIcon(makeUiIcon(UiIcon::PlcSettings)); | |||
| ui_->disconnectPlcAction->setIcon(makeUiIcon(UiIcon::Disconnect)); | |||
| ui_->configureRegisterCommentsAction->setIcon( | |||
| makeUiIcon(UiIcon::RegisterComments)); | |||
| ui_->addButtonAction->setIcon(makeUiIcon(UiIcon::HmiButton)); | |||
| ui_->addIndicatorAction->setIcon(makeUiIcon(UiIcon::Indicator)); | |||
| ui_->addNumericDisplayAction->setIcon(makeUiIcon(UiIcon::NumericDisplay)); | |||
| ui_->addNumericInputAction->setIcon(makeUiIcon(UiIcon::NumericInput)); | |||
| ui_->addProgressBarAction->setIcon(makeUiIcon(UiIcon::ProgressBar)); | |||
| ui_->addLabelAction->setIcon(makeUiIcon(UiIcon::Text)); | |||
| ui_->addPageJumpAction->setIcon(makeUiIcon(UiIcon::PageJump)); | |||
| ui_->addAlarmListAction->setIcon(makeUiIcon(UiIcon::AlarmList)); | |||
| ui_->configureAlarmsAction->setIcon(makeUiIcon(UiIcon::AlarmSettings)); | |||
| ui_->deleteControlAction->setIcon(makeUiIcon(UiIcon::Delete)); | |||
| ui_->addRungAction->setIcon(makeUiIcon(UiIcon::AddRung)); | |||
| ui_->parallelInsertAction->setIcon(makeUiIcon(UiIcon::ParallelBranch)); | |||
| ui_->addNormallyOpenAction->setIcon(makeUiIcon(UiIcon::NormallyOpenContact)); | |||
| ui_->addNormallyClosedAction->setIcon(makeUiIcon(UiIcon::NormallyClosedContact)); | |||
| ui_->addRisingEdgeAction->setIcon(makeUiIcon(UiIcon::RisingEdgeContact)); | |||
| ui_->addFallingEdgeAction->setIcon(makeUiIcon(UiIcon::FallingEdgeContact)); | |||
| ui_->addTimerContactAction->setIcon(makeUiIcon(UiIcon::TimerContact)); | |||
| ui_->addCounterContactAction->setIcon(makeUiIcon(UiIcon::CounterContact)); | |||
| ui_->addNormalCoilAction->setIcon(makeUiIcon(UiIcon::Coil)); | |||
| ui_->addSetCoilAction->setIcon(makeUiIcon(UiIcon::SetCoil)); | |||
| ui_->addResetCoilAction->setIcon(makeUiIcon(UiIcon::ResetCoil)); | |||
| ui_->addTonAction->setIcon(makeUiIcon(UiIcon::Ton)); | |||
| ui_->addCtuAction->setIcon(makeUiIcon(UiIcon::Ctu)); | |||
| ui_->addCtdAction->setIcon(makeUiIcon(UiIcon::Ctd)); | |||
| ui_->addMoveAction->setIcon(makeUiIcon(UiIcon::Move)); | |||
| ui_->addAddAction->setIcon(makeUiIcon(UiIcon::Add)); | |||
| ui_->addSubAction->setIcon(makeUiIcon(UiIcon::Subtract)); | |||
| ui_->addCompareAction->setIcon(makeUiIcon(UiIcon::Compare)); | |||
| ui_->editRungCommentAction->setIcon(makeUiIcon(UiIcon::Comment)); | |||
| ui_->deleteLogicAction->setIcon(makeUiIcon(UiIcon::Delete)); | |||
| ui_->editorTabWidget->setTabIcon(0, makeUiIcon(UiIcon::HmiPage)); | |||
| ui_->editorTabWidget->setTabIcon(1, makeUiIcon(UiIcon::Logic)); | |||
| ui_->editorTabWidget->setTabIcon(2, makeUiIcon(UiIcon::Runtime)); | |||
| ui_->outputDock->setMaximumHeight(220); | |||
| mode_status_label_ = new QLabel(this); | |||
| @@ -303,11 +303,7 @@ | |||
| <addaction name="addIndicatorAction"/> | |||
| <addaction name="addNumericDisplayAction"/> | |||
| <addaction name="addNumericInputAction"/> | |||
| <addaction name="addProgressBarAction"/> | |||
| <addaction name="addLabelAction"/> | |||
| <addaction name="addPageJumpAction"/> | |||
| <addaction name="addAlarmListAction"/> | |||
| <addaction name="configureAlarmsAction"/> | |||
| <addaction name="deleteControlAction"/> | |||
| </widget> | |||
| <widget class="QToolBar" name="logicToolBar"> | |||
| @@ -329,20 +325,7 @@ | |||
| <addaction name="separator"/> | |||
| <addaction name="addNormallyOpenAction"/> | |||
| <addaction name="addNormallyClosedAction"/> | |||
| <addaction name="addRisingEdgeAction"/> | |||
| <addaction name="addFallingEdgeAction"/> | |||
| <addaction name="addTimerContactAction"/> | |||
| <addaction name="addCounterContactAction"/> | |||
| <addaction name="addNormalCoilAction"/> | |||
| <addaction name="addSetCoilAction"/> | |||
| <addaction name="addResetCoilAction"/> | |||
| <addaction name="addTonAction"/> | |||
| <addaction name="addCtuAction"/> | |||
| <addaction name="addCtdAction"/> | |||
| <addaction name="addMoveAction"/> | |||
| <addaction name="addAddAction"/> | |||
| <addaction name="addSubAction"/> | |||
| <addaction name="addCompareAction"/> | |||
| <addaction name="editRungCommentAction"/> | |||
| </widget> | |||
| <widget class="QDockWidget" name="projectDock"> | |||
| @@ -0,0 +1,508 @@ | |||
| #include "toolbar_icon_factory.h" | |||
| #include <QFont> | |||
| #include <QPainter> | |||
| #include <QPainterPath> | |||
| #include <QPixmap> | |||
| #include <array> | |||
| namespace { | |||
| const QColor kInk(QStringLiteral("#263842")); | |||
| const QColor kAccent(QStringLiteral("#2f7d4a")); | |||
| const QColor kAccentFill(QStringLiteral("#dcece3")); | |||
| const QColor kWarning(QStringLiteral("#b87808")); | |||
| const QColor kDanger(QStringLiteral("#a84545")); | |||
| const QColor kPaper(QStringLiteral("#ffffff")); | |||
| QPen iconPen(const QColor &color = kInk, qreal width = 1.7) | |||
| { | |||
| QPen pen(color, width); | |||
| pen.setCapStyle(Qt::RoundCap); | |||
| pen.setJoinStyle(Qt::RoundJoin); | |||
| return pen; | |||
| } | |||
| void drawCenteredText( | |||
| QPainter &painter, | |||
| const QRectF &bounds, | |||
| const QString &text, | |||
| qreal point_size, | |||
| const QColor &color = kInk) | |||
| { | |||
| QFont font = painter.font(); | |||
| font.setFamily(QStringLiteral("Arial")); | |||
| font.setPointSizeF(point_size); | |||
| font.setBold(true); | |||
| painter.setFont(font); | |||
| painter.setPen(color); | |||
| painter.drawText(bounds, Qt::AlignCenter, text); | |||
| } | |||
| void drawPlc(QPainter &painter) | |||
| { | |||
| painter.setPen(iconPen()); | |||
| painter.setBrush(kPaper); | |||
| painter.drawRoundedRect(QRectF(3, 4, 18, 16), 1.5, 1.5); | |||
| painter.drawLine(QPointF(8, 4), QPointF(8, 20)); | |||
| painter.setBrush(kAccent); | |||
| painter.setPen(Qt::NoPen); | |||
| painter.drawEllipse(QPointF(5.5, 8), 1.1, 1.1); | |||
| painter.drawEllipse(QPointF(5.5, 12), 1.1, 1.1); | |||
| painter.setPen(iconPen()); | |||
| painter.drawLine(QPointF(11, 8), QPointF(18, 8)); | |||
| painter.drawLine(QPointF(11, 12), QPointF(18, 12)); | |||
| painter.drawLine(QPointF(11, 16), QPointF(16, 16)); | |||
| } | |||
| void drawSave(QPainter &painter) | |||
| { | |||
| painter.setPen(iconPen()); | |||
| painter.setBrush(kPaper); | |||
| painter.drawRoundedRect(QRectF(4, 3, 16, 18), 1.2, 1.2); | |||
| painter.drawRect(QRectF(7, 3, 9, 6)); | |||
| painter.drawRect(QRectF(7, 13, 10, 8)); | |||
| } | |||
| void drawContact(QPainter &painter, const QString &label, bool closed) | |||
| { | |||
| painter.setPen(iconPen()); | |||
| painter.drawLine(QPointF(2, 12), QPointF(7, 12)); | |||
| painter.drawLine(QPointF(17, 12), QPointF(22, 12)); | |||
| painter.drawLine(QPointF(8, 7), QPointF(8, 17)); | |||
| painter.drawLine(QPointF(16, 7), QPointF(16, 17)); | |||
| if (closed) | |||
| { | |||
| painter.drawLine(QPointF(7, 17), QPointF(17, 7)); | |||
| } | |||
| if (!label.isEmpty()) | |||
| { | |||
| drawCenteredText(painter, QRectF(8, 7, 8, 10), label, 5.5); | |||
| } | |||
| } | |||
| void drawCoil(QPainter &painter, const QString &label) | |||
| { | |||
| painter.setPen(iconPen()); | |||
| painter.drawLine(QPointF(2, 12), QPointF(6, 12)); | |||
| painter.drawLine(QPointF(18, 12), QPointF(22, 12)); | |||
| QPainterPath left; | |||
| left.moveTo(11, 5); | |||
| left.cubicTo(5, 6, 5, 18, 11, 19); | |||
| painter.drawPath(left); | |||
| QPainterPath right; | |||
| right.moveTo(13, 5); | |||
| right.cubicTo(19, 6, 19, 18, 13, 19); | |||
| painter.drawPath(right); | |||
| if (!label.isEmpty()) | |||
| { | |||
| drawCenteredText(painter, QRectF(8, 7, 8, 10), label, 6.0); | |||
| } | |||
| } | |||
| void drawInstructionBlock(QPainter &painter, const QString &label) | |||
| { | |||
| painter.setPen(iconPen()); | |||
| painter.setBrush(kPaper); | |||
| painter.drawRoundedRect(QRectF(2.5, 5, 19, 14), 1.5, 1.5); | |||
| drawCenteredText(painter, QRectF(3, 5.5, 18, 13), label, 5.5); | |||
| } | |||
| QPixmap renderIcon(UiIcon icon, int size) | |||
| { | |||
| QPixmap pixmap(size, size); | |||
| pixmap.fill(Qt::transparent); | |||
| QPainter painter(&pixmap); | |||
| painter.setRenderHint(QPainter::Antialiasing, true); | |||
| painter.scale(static_cast<qreal>(size) / 24.0, static_cast<qreal>(size) / 24.0); | |||
| painter.setPen(iconPen()); | |||
| painter.setBrush(Qt::NoBrush); | |||
| switch (icon) | |||
| { | |||
| case UiIcon::Edit: | |||
| { | |||
| painter.drawLine(QPointF(5, 19), QPointF(16.5, 7.5)); | |||
| painter.drawLine(QPointF(8, 20), QPointF(19.5, 8.5)); | |||
| painter.drawLine(QPointF(16.5, 7.5), QPointF(19.5, 8.5)); | |||
| painter.drawLine(QPointF(5, 19), QPointF(4, 21)); | |||
| break; | |||
| } | |||
| case UiIcon::RunOffline: | |||
| { | |||
| QPainterPath path; | |||
| path.moveTo(7, 4); | |||
| path.lineTo(20, 12); | |||
| path.lineTo(7, 20); | |||
| path.closeSubpath(); | |||
| painter.setPen(iconPen(kAccent)); | |||
| painter.setBrush(kAccentFill); | |||
| painter.drawPath(path); | |||
| break; | |||
| } | |||
| case UiIcon::RunOnline: | |||
| { | |||
| drawPlc(painter); | |||
| painter.setPen(Qt::NoPen); | |||
| painter.setBrush(kAccent); | |||
| QPainterPath path; | |||
| path.moveTo(14, 10); | |||
| path.lineTo(19, 13); | |||
| path.lineTo(14, 16); | |||
| path.closeSubpath(); | |||
| painter.drawPath(path); | |||
| break; | |||
| } | |||
| case UiIcon::NewDocument: | |||
| { | |||
| QPainterPath page; | |||
| page.moveTo(5, 2); | |||
| page.lineTo(15, 2); | |||
| page.lineTo(20, 7); | |||
| page.lineTo(20, 22); | |||
| page.lineTo(5, 22); | |||
| page.closeSubpath(); | |||
| painter.setBrush(kPaper); | |||
| painter.drawPath(page); | |||
| painter.drawLine(QPointF(15, 2), QPointF(15, 7)); | |||
| painter.drawLine(QPointF(15, 7), QPointF(20, 7)); | |||
| painter.drawLine(QPointF(8, 15), QPointF(16, 15)); | |||
| painter.drawLine(QPointF(12, 11), QPointF(12, 19)); | |||
| break; | |||
| } | |||
| case UiIcon::Save: | |||
| { | |||
| drawSave(painter); | |||
| break; | |||
| } | |||
| case UiIcon::SaveAs: | |||
| { | |||
| drawSave(painter); | |||
| painter.setPen(iconPen(kAccent, 2.0)); | |||
| painter.drawLine(QPointF(13, 19), QPointF(21, 11)); | |||
| break; | |||
| } | |||
| case UiIcon::Open: | |||
| { | |||
| painter.setBrush(kPaper); | |||
| QPainterPath folder; | |||
| folder.moveTo(2, 7); | |||
| folder.lineTo(9, 7); | |||
| folder.lineTo(11, 10); | |||
| folder.lineTo(22, 10); | |||
| folder.lineTo(19, 20); | |||
| folder.lineTo(3, 20); | |||
| folder.closeSubpath(); | |||
| painter.setBrush(kAccentFill); | |||
| painter.drawPath(folder); | |||
| break; | |||
| } | |||
| case UiIcon::Exit: | |||
| { | |||
| painter.drawRect(QRectF(4, 3, 10, 18)); | |||
| painter.drawLine(QPointF(10, 12), QPointF(22, 12)); | |||
| painter.drawLine(QPointF(18, 8), QPointF(22, 12)); | |||
| painter.drawLine(QPointF(18, 16), QPointF(22, 12)); | |||
| break; | |||
| } | |||
| case UiIcon::PlcSettings: | |||
| { | |||
| drawPlc(painter); | |||
| painter.setPen(iconPen(kAccent)); | |||
| painter.drawEllipse(QPointF(17.5, 16.5), 3.0, 3.0); | |||
| painter.drawLine(QPointF(17.5, 12), QPointF(17.5, 14)); | |||
| painter.drawLine(QPointF(17.5, 19), QPointF(17.5, 21)); | |||
| break; | |||
| } | |||
| case UiIcon::Disconnect: | |||
| { | |||
| painter.drawLine(QPointF(3, 12), QPointF(8, 12)); | |||
| painter.drawRect(QRectF(8, 8, 4, 8)); | |||
| painter.drawLine(QPointF(12, 10), QPointF(15, 10)); | |||
| painter.drawLine(QPointF(12, 14), QPointF(15, 14)); | |||
| painter.drawRect(QRectF(16, 8, 4, 8)); | |||
| painter.drawLine(QPointF(20, 12), QPointF(23, 12)); | |||
| painter.setPen(iconPen(kDanger, 2.0)); | |||
| painter.drawLine(QPointF(6, 20), QPointF(19, 4)); | |||
| break; | |||
| } | |||
| case UiIcon::RegisterComments: | |||
| { | |||
| painter.drawRoundedRect(QRectF(3, 3, 18, 18), 1.5, 1.5); | |||
| drawCenteredText(painter, QRectF(4, 4, 8, 7), QStringLiteral("M"), 5.0); | |||
| drawCenteredText(painter, QRectF(4, 12, 8, 7), QStringLiteral("D"), 5.0); | |||
| painter.drawLine(QPointF(13, 8), QPointF(19, 8)); | |||
| painter.drawLine(QPointF(13, 16), QPointF(19, 16)); | |||
| break; | |||
| } | |||
| case UiIcon::HmiButton: | |||
| { | |||
| painter.setBrush(kAccentFill); | |||
| painter.drawRoundedRect(QRectF(3, 5, 18, 14), 3, 3); | |||
| painter.setBrush(kPaper); | |||
| painter.drawEllipse(QPointF(12, 12), 4, 4); | |||
| break; | |||
| } | |||
| case UiIcon::Indicator: | |||
| { | |||
| painter.setBrush(kAccentFill); | |||
| painter.drawEllipse(QPointF(12, 12), 8.5, 8.5); | |||
| painter.setBrush(kAccent); | |||
| painter.setPen(Qt::NoPen); | |||
| painter.drawEllipse(QPointF(12, 12), 4.5, 4.5); | |||
| break; | |||
| } | |||
| case UiIcon::NumericDisplay: | |||
| { | |||
| painter.drawRoundedRect(QRectF(2, 5, 20, 14), 2, 2); | |||
| drawCenteredText(painter, QRectF(3, 6, 18, 12), QStringLiteral("123"), 6.0); | |||
| break; | |||
| } | |||
| case UiIcon::NumericInput: | |||
| { | |||
| painter.drawRoundedRect(QRectF(2, 5, 20, 14), 2, 2); | |||
| drawCenteredText(painter, QRectF(3, 6, 13, 12), QStringLiteral("12"), 6.0); | |||
| painter.drawLine(QPointF(18, 7), QPointF(18, 17)); | |||
| break; | |||
| } | |||
| case UiIcon::ProgressBar: | |||
| { | |||
| painter.drawRoundedRect(QRectF(2, 8, 20, 8), 2, 2); | |||
| painter.setPen(Qt::NoPen); | |||
| painter.setBrush(kAccent); | |||
| painter.drawRoundedRect(QRectF(4, 10, 11, 4), 1, 1); | |||
| break; | |||
| } | |||
| case UiIcon::Text: | |||
| { | |||
| painter.drawLine(QPointF(5, 5), QPointF(19, 5)); | |||
| painter.drawLine(QPointF(12, 5), QPointF(12, 20)); | |||
| drawCenteredText(painter, QRectF(7, 6, 10, 14), QStringLiteral("T"), 9.0); | |||
| break; | |||
| } | |||
| case UiIcon::PageJump: | |||
| { | |||
| painter.drawRect(QRectF(3, 3, 14, 18)); | |||
| painter.drawLine(QPointF(9, 12), QPointF(22, 12)); | |||
| painter.drawLine(QPointF(18, 8), QPointF(22, 12)); | |||
| painter.drawLine(QPointF(18, 16), QPointF(22, 12)); | |||
| break; | |||
| } | |||
| case UiIcon::AlarmList: | |||
| { | |||
| QPainterPath triangle; | |||
| triangle.moveTo(12, 3); | |||
| triangle.lineTo(22, 21); | |||
| triangle.lineTo(2, 21); | |||
| triangle.closeSubpath(); | |||
| painter.setPen(iconPen(kWarning)); | |||
| painter.setBrush(QColor(QStringLiteral("#fff0d2"))); | |||
| painter.drawPath(triangle); | |||
| painter.drawLine(QPointF(12, 8), QPointF(12, 14)); | |||
| painter.drawPoint(QPointF(12, 17)); | |||
| break; | |||
| } | |||
| case UiIcon::AlarmSettings: | |||
| { | |||
| painter.setPen(iconPen(kWarning)); | |||
| painter.drawArc(QRectF(4, 4, 12, 13), 0, 180 * 16); | |||
| painter.drawLine(QPointF(4, 10), QPointF(4, 17)); | |||
| painter.drawLine(QPointF(16, 10), QPointF(16, 17)); | |||
| painter.drawLine(QPointF(3, 17), QPointF(17, 17)); | |||
| painter.drawEllipse(QPointF(18, 17), 3.0, 3.0); | |||
| painter.drawLine(QPointF(18, 12), QPointF(18, 14)); | |||
| break; | |||
| } | |||
| case UiIcon::Delete: | |||
| { | |||
| painter.setPen(iconPen(kDanger)); | |||
| painter.drawLine(QPointF(5, 7), QPointF(19, 7)); | |||
| painter.drawLine(QPointF(9, 4), QPointF(15, 4)); | |||
| painter.drawRoundedRect(QRectF(7, 7, 10, 14), 1, 1); | |||
| painter.drawLine(QPointF(10, 10), QPointF(10, 18)); | |||
| painter.drawLine(QPointF(14, 10), QPointF(14, 18)); | |||
| break; | |||
| } | |||
| case UiIcon::AddRung: | |||
| { | |||
| painter.drawLine(QPointF(4, 3), QPointF(4, 21)); | |||
| painter.drawLine(QPointF(20, 3), QPointF(20, 21)); | |||
| painter.drawLine(QPointF(4, 12), QPointF(20, 12)); | |||
| painter.setPen(iconPen(kAccent, 2.0)); | |||
| painter.drawLine(QPointF(12, 7), QPointF(12, 17)); | |||
| painter.drawLine(QPointF(7, 12), QPointF(17, 12)); | |||
| break; | |||
| } | |||
| case UiIcon::ParallelBranch: | |||
| { | |||
| painter.drawLine(QPointF(2, 12), QPointF(6, 12)); | |||
| painter.drawLine(QPointF(18, 12), QPointF(22, 12)); | |||
| painter.drawLine(QPointF(6, 7), QPointF(6, 17)); | |||
| painter.drawLine(QPointF(18, 7), QPointF(18, 17)); | |||
| painter.drawLine(QPointF(6, 7), QPointF(18, 7)); | |||
| painter.drawLine(QPointF(6, 17), QPointF(18, 17)); | |||
| painter.setPen(iconPen(kAccent)); | |||
| painter.drawLine(QPointF(12, 9), QPointF(12, 15)); | |||
| painter.drawLine(QPointF(9, 12), QPointF(15, 12)); | |||
| break; | |||
| } | |||
| case UiIcon::NormallyOpenContact: | |||
| { | |||
| drawContact(painter, {}, false); | |||
| break; | |||
| } | |||
| case UiIcon::NormallyClosedContact: | |||
| { | |||
| drawContact(painter, {}, true); | |||
| break; | |||
| } | |||
| case UiIcon::RisingEdgeContact: | |||
| { | |||
| drawContact(painter, QStringLiteral("P"), false); | |||
| break; | |||
| } | |||
| case UiIcon::FallingEdgeContact: | |||
| { | |||
| drawContact(painter, QStringLiteral("N"), false); | |||
| break; | |||
| } | |||
| case UiIcon::TimerContact: | |||
| { | |||
| drawContact(painter, QStringLiteral("T"), false); | |||
| break; | |||
| } | |||
| case UiIcon::CounterContact: | |||
| { | |||
| drawContact(painter, QStringLiteral("C"), false); | |||
| break; | |||
| } | |||
| case UiIcon::Coil: | |||
| { | |||
| drawCoil(painter, {}); | |||
| break; | |||
| } | |||
| case UiIcon::SetCoil: | |||
| { | |||
| drawCoil(painter, QStringLiteral("S")); | |||
| break; | |||
| } | |||
| case UiIcon::ResetCoil: | |||
| { | |||
| drawCoil(painter, QStringLiteral("R")); | |||
| break; | |||
| } | |||
| case UiIcon::Ton: | |||
| { | |||
| drawInstructionBlock(painter, QStringLiteral("TON")); | |||
| break; | |||
| } | |||
| case UiIcon::Ctu: | |||
| { | |||
| drawInstructionBlock(painter, QStringLiteral("CTU")); | |||
| break; | |||
| } | |||
| case UiIcon::Ctd: | |||
| { | |||
| drawInstructionBlock(painter, QStringLiteral("CTD")); | |||
| break; | |||
| } | |||
| case UiIcon::Move: | |||
| { | |||
| painter.drawRect(QRectF(2, 6, 6, 12)); | |||
| painter.drawRect(QRectF(16, 6, 6, 12)); | |||
| painter.drawLine(QPointF(8, 12), QPointF(16, 12)); | |||
| painter.drawLine(QPointF(13, 9), QPointF(16, 12)); | |||
| painter.drawLine(QPointF(13, 15), QPointF(16, 12)); | |||
| break; | |||
| } | |||
| case UiIcon::Add: | |||
| { | |||
| drawInstructionBlock(painter, QStringLiteral("+")); | |||
| break; | |||
| } | |||
| case UiIcon::Subtract: | |||
| { | |||
| drawInstructionBlock(painter, QStringLiteral("-")); | |||
| break; | |||
| } | |||
| case UiIcon::Compare: | |||
| { | |||
| drawInstructionBlock(painter, QStringLiteral("<>")); | |||
| break; | |||
| } | |||
| case UiIcon::Comment: | |||
| { | |||
| painter.drawRoundedRect(QRectF(3, 3, 18, 18), 1.5, 1.5); | |||
| painter.drawLine(QPointF(7, 8), QPointF(17, 8)); | |||
| painter.drawLine(QPointF(7, 12), QPointF(17, 12)); | |||
| painter.drawLine(QPointF(7, 16), QPointF(13, 16)); | |||
| painter.setPen(iconPen(kAccent, 2.0)); | |||
| painter.drawLine(QPointF(14, 19), QPointF(21, 12)); | |||
| break; | |||
| } | |||
| case UiIcon::More: | |||
| { | |||
| painter.setPen(Qt::NoPen); | |||
| painter.setBrush(kInk); | |||
| painter.drawEllipse(QPointF(6, 12), 1.7, 1.7); | |||
| painter.drawEllipse(QPointF(12, 12), 1.7, 1.7); | |||
| painter.drawEllipse(QPointF(18, 12), 1.7, 1.7); | |||
| break; | |||
| } | |||
| case UiIcon::HmiPage: | |||
| { | |||
| painter.drawRoundedRect(QRectF(2, 4, 20, 14), 1.5, 1.5); | |||
| painter.drawLine(QPointF(8, 21), QPointF(16, 21)); | |||
| painter.drawLine(QPointF(12, 18), QPointF(12, 21)); | |||
| painter.setBrush(kAccentFill); | |||
| painter.drawRoundedRect(QRectF(6, 8, 12, 6), 1, 1); | |||
| break; | |||
| } | |||
| case UiIcon::Logic: | |||
| { | |||
| painter.drawLine(QPointF(3, 3), QPointF(3, 21)); | |||
| painter.drawLine(QPointF(21, 3), QPointF(21, 21)); | |||
| drawContact(painter, {}, false); | |||
| break; | |||
| } | |||
| case UiIcon::Runtime: | |||
| { | |||
| painter.drawRoundedRect(QRectF(2, 4, 20, 16), 1.5, 1.5); | |||
| QPainterPath pulse; | |||
| pulse.moveTo(4, 13); | |||
| pulse.lineTo(8, 13); | |||
| pulse.lineTo(10, 8); | |||
| pulse.lineTo(13, 17); | |||
| pulse.lineTo(16, 11); | |||
| pulse.lineTo(20, 11); | |||
| painter.setPen(iconPen(kAccent)); | |||
| painter.drawPath(pulse); | |||
| break; | |||
| } | |||
| case UiIcon::ClearList: | |||
| { | |||
| painter.drawLine(QPointF(4, 6), QPointF(16, 6)); | |||
| painter.drawLine(QPointF(4, 11), QPointF(13, 11)); | |||
| painter.drawLine(QPointF(4, 16), QPointF(10, 16)); | |||
| painter.setPen(iconPen(kDanger)); | |||
| painter.drawLine(QPointF(14, 13), QPointF(21, 20)); | |||
| painter.drawLine(QPointF(21, 13), QPointF(14, 20)); | |||
| break; | |||
| } | |||
| } | |||
| return pixmap; | |||
| } | |||
| } // namespace | |||
| QIcon makeUiIcon(UiIcon icon) | |||
| { | |||
| QIcon result; | |||
| constexpr std::array<int, 3> sizes{16, 24, 32}; | |||
| for (int size : sizes) | |||
| { | |||
| result.addPixmap(renderIcon(icon, size)); | |||
| } | |||
| return result; | |||
| } | |||
| @@ -0,0 +1,54 @@ | |||
| #pragma once | |||
| #include <QIcon> | |||
| enum class UiIcon | |||
| { | |||
| Edit, | |||
| RunOffline, | |||
| RunOnline, | |||
| NewDocument, | |||
| Save, | |||
| SaveAs, | |||
| Open, | |||
| Exit, | |||
| PlcSettings, | |||
| Disconnect, | |||
| RegisterComments, | |||
| HmiButton, | |||
| Indicator, | |||
| NumericDisplay, | |||
| NumericInput, | |||
| ProgressBar, | |||
| Text, | |||
| PageJump, | |||
| AlarmList, | |||
| AlarmSettings, | |||
| Delete, | |||
| AddRung, | |||
| ParallelBranch, | |||
| NormallyOpenContact, | |||
| NormallyClosedContact, | |||
| RisingEdgeContact, | |||
| FallingEdgeContact, | |||
| TimerContact, | |||
| CounterContact, | |||
| Coil, | |||
| SetCoil, | |||
| ResetCoil, | |||
| Ton, | |||
| Ctu, | |||
| Ctd, | |||
| Move, | |||
| Add, | |||
| Subtract, | |||
| Compare, | |||
| Comment, | |||
| More, | |||
| HmiPage, | |||
| Logic, | |||
| Runtime, | |||
| ClearList | |||
| }; | |||
| QIcon makeUiIcon(UiIcon icon); | |||
| @@ -37,8 +37,10 @@ | |||
| #include <QPushButton> | |||
| #include <QStringList> | |||
| #include <QTableWidget> | |||
| #include <QTabWidget> | |||
| #include <QTimer> | |||
| #include <QTest> | |||
| #include <QToolButton> | |||
| #include <QTreeWidget> | |||
| #include <iostream> | |||
| @@ -601,6 +603,16 @@ void testModeActionsControlEditingAvailability() | |||
| QAction *add_progress_bar_action = requiredChild<QAction>( | |||
| window, "addProgressBarAction"); | |||
| QAction *delete_control_action = requiredChild<QAction>(window, "deleteControlAction"); | |||
| QToolButton *hmi_more_controls = requiredChild<QToolButton>( | |||
| window, "hmiMoreControlsButton"); | |||
| QToolButton *logic_contact_menu = requiredChild<QToolButton>( | |||
| window, "logicContactMenuButton"); | |||
| QToolButton *logic_output_menu = requiredChild<QToolButton>( | |||
| window, "logicOutputMenuButton"); | |||
| QToolButton *logic_timer_counter_menu = requiredChild<QToolButton>( | |||
| window, "logicTimerCounterMenuButton"); | |||
| QToolButton *logic_data_menu = requiredChild<QToolButton>( | |||
| window, "logicDataMenuButton"); | |||
| QAction *add_normally_open_action = requiredChild<QAction>( | |||
| window, "addNormallyOpenAction"); | |||
| QAction *add_normal_coil_action = requiredChild<QAction>( | |||
| @@ -632,8 +644,93 @@ void testModeActionsControlEditingAvailability() | |||
| QWidget *runtime_hmi = requiredChild<QWidget>(window, "runtimeHmiView"); | |||
| QWidget *runtime_logic = requiredChild<QWidget>(window, "runtimeLogicView"); | |||
| QWidget *free_monitor = requiredChild<QWidget>(window, "freeMonitorWidget"); | |||
| QTabWidget *editor_tabs = requiredChild<QTabWidget>(window, "editorTabWidget"); | |||
| require(!runtime_tab->isVisible(), | |||
| "runtime monitor workspace must be hidden while editing"); | |||
| for (const char *action_name : { | |||
| "exitAction", | |||
| "newProjectAction", | |||
| "saveProjectAction", | |||
| "saveAsProjectAction", | |||
| "loadProjectAction", | |||
| "configurePlcAction", | |||
| "configureRegisterCommentsAction", | |||
| "disconnectPlcAction", | |||
| "addButtonAction", | |||
| "addIndicatorAction", | |||
| "addNumericDisplayAction", | |||
| "addNumericInputAction", | |||
| "addProgressBarAction", | |||
| "addLabelAction", | |||
| "addPageJumpAction", | |||
| "addAlarmListAction", | |||
| "configureAlarmsAction", | |||
| "deleteControlAction", | |||
| "addRungAction", | |||
| "parallelInsertAction", | |||
| "addNormallyOpenAction", | |||
| "addNormallyClosedAction", | |||
| "addRisingEdgeAction", | |||
| "addFallingEdgeAction", | |||
| "addTimerContactAction", | |||
| "addCounterContactAction", | |||
| "addNormalCoilAction", | |||
| "addSetCoilAction", | |||
| "addResetCoilAction", | |||
| "addTonAction", | |||
| "addCtuAction", | |||
| "addCtdAction", | |||
| "addMoveAction", | |||
| "addAddAction", | |||
| "addSubAction", | |||
| "addCompareAction", | |||
| "editRungCommentAction", | |||
| "deleteLogicAction", | |||
| "editingModeAction", | |||
| "offlineModeAction", | |||
| "onlineModeAction"}) | |||
| { | |||
| require(!requiredChild<QAction>(window, action_name)->icon().isNull(), | |||
| std::string("UI action must have a semantic icon: ") + action_name); | |||
| } | |||
| require(!hmi_more_controls->icon().isNull() | |||
| && !logic_contact_menu->icon().isNull() | |||
| && !logic_output_menu->icon().isNull() | |||
| && !logic_timer_counter_menu->icon().isNull() | |||
| && !logic_data_menu->icon().isNull(), | |||
| "every grouped toolbar menu must have an icon"); | |||
| require(editor_tabs->count() == 3 | |||
| && !editor_tabs->tabIcon(0).isNull() | |||
| && !editor_tabs->tabIcon(1).isNull() | |||
| && !editor_tabs->tabIcon(2).isNull(), | |||
| "every editor workspace tab must have an icon"); | |||
| QToolButton *monitor_remove = free_monitor->findChild<QToolButton *>( | |||
| QStringLiteral("removeButton")); | |||
| QToolButton *monitor_clear = free_monitor->findChild<QToolButton *>( | |||
| QStringLiteral("clearButton")); | |||
| require(monitor_remove != nullptr && monitor_clear != nullptr | |||
| && !monitor_remove->icon().isNull() | |||
| && !monitor_clear->icon().isNull(), | |||
| "free-monitor delete and clear commands must have icons"); | |||
| require(hmi_more_controls->menu() != nullptr | |||
| && hmi_more_controls->menu()->actions().contains(add_progress_bar_action), | |||
| "advanced HMI controls must remain reachable from the more-controls menu"); | |||
| require(logic_contact_menu->menu() != nullptr | |||
| && logic_contact_menu->menu()->actions().contains( | |||
| requiredChild<QAction>(window, "addRisingEdgeAction")), | |||
| "edge and resource contacts must remain reachable from the contact menu"); | |||
| require(logic_output_menu->menu() != nullptr | |||
| && logic_output_menu->menu()->actions().contains( | |||
| requiredChild<QAction>(window, "addResetCoilAction")), | |||
| "set/reset coils must remain reachable from the output menu"); | |||
| require(logic_timer_counter_menu->menu() != nullptr | |||
| && logic_timer_counter_menu->menu()->actions().contains( | |||
| requiredChild<QAction>(window, "addCtdAction")), | |||
| "timer and counter instructions must remain reachable from their menu"); | |||
| require(logic_data_menu->menu() != nullptr | |||
| && logic_data_menu->menu()->actions().contains( | |||
| requiredChild<QAction>(window, "addSubAction")), | |||
| "data instructions must remain reachable from the data menu"); | |||
| const qreal compact_scale = hmi_editor->transform().m11(); | |||
| window.resize(1600, 900); | |||
| @@ -16,6 +16,7 @@ SOURCES += \ | |||
| ../src/ui/plc_connection_dialog.cpp \ | |||
| ../src/ui/free_monitor_widget.cpp \ | |||
| ../src/ui/runtime_monitor_widget.cpp \ | |||
| ../src/ui/toolbar_icon_factory.cpp \ | |||
| ../src/ui/project_workspace_controller.cpp \ | |||
| ../src/ui/property_panel_controller.cpp \ | |||
| ../src/ui/runtime_panel_controller.cpp \ | |||
| @@ -52,6 +53,7 @@ HEADERS += \ | |||
| ../src/ui/plc_connection_dialog.h \ | |||
| ../src/ui/free_monitor_widget.h \ | |||
| ../src/ui/runtime_monitor_widget.h \ | |||
| ../src/ui/toolbar_icon_factory.h \ | |||
| ../src/ui/project_workspace_controller.h \ | |||
| ../src/ui/property_panel_controller.h \ | |||
| ../src/ui/runtime_panel_controller.h \ | |||