#include "WindowAppUiFrame.h"
#include "selectwidget.h"
#include "UiManager.h"
#include "WindowMain.h"
#include "DialogUiOption.h"
#include "WindowAppUiScene.h"
#include "VPCommand.h"
#include "Preferences.h"
#include "VControlObject.h"
WindowAppUiFrame::WindowAppUiFrame(const QString& strTitle, QWidget *parent)
: QMainWindow(parent)
, m_nUiViewHeight(DEFAULT_UIVIEW_HEIGHT)
, m_nUiViewWidth(DEFAULT_UIVIEW_WIDTH)
, actionUndo(nullptr)
, actionRedo(nullptr)
{
ui.setupUi(this);
m_nScrollValueH = 0;
m_nScrollValueV = 0;
// UI元素初始化
this->initUI();
// 初始化布局工具栏
this->initLayoutToolbar();
//// 初始化控件工具栏
//this->initControlToolbar();
this->addToolBar(m_layoutToolbar);
m_layoutToolbar->setMovable(false);
//this->addToolBarBreak();
//this->addToolBar(m_controlToolbar);
//m_controlToolbar->setMovable(false);
// 初始化UiView
ui.widgetUiView->init(strTitle, ui.uiNavView, this, ui.objectController);
// 绑定鸟瞰图缩放时的同步刷新动作
connect(ui.widgetUiView, &WindowAppUiView::navigatorViewRequired, this, [=](bool required, const QTransform& tf)
{
Q_UNUSED(required);
Q_UNUSED(tf);
//ui.uiNavView->setTransform(WindowAppPouView::resetScale(tf));
ui.uiNavView->fitInView(ui.uiNavView->sceneRect(), Qt::KeepAspectRatio);
ui.uiNavView->setVisible(required);
ui.uiNavView->updateMainViewportRegion();
}
);
//// 矩形区域变动时的响应动作
//connect(ui.widgetUiView, &WindowAppUiView::viewportRectChanged, ui.uiNavView, &WindowAppUiNavView::updateMainViewportRegion);
// 统一转换为初始化函数
//ui.widgetUiView->uiScene()->m_pPropertyController = ui.objectController;
//ui.widgetUiView->m_strPageName = strTitle;
// g_pUiManager->registerNewUi(ui.widgetUiView);
//// 将当前Scene绑定到鸟瞰图中进行同步
//ui.uiNavView->setScene((QGraphicsScene*)ui.widgetUiView->scene());
//// 绑定同步的鸟瞰图
//ui.uiNavView->setMainView(ui.widgetUiView);
//// 调整View
//ui.uiNavView->fitInView(ui.uiNavView->sceneRect(), Qt::KeepAspectRatio);
WindowAppUiScene* pScene = ui.widgetUiView->uiScene();
WindowAppUiView* pView = ui.widgetUiView;
WindowAppUiFrame* pFrame = this;
vDebug() << pScene << " " << pView << " " << pFrame;
}
WindowAppUiFrame::~WindowAppUiFrame()
{
}
///
/// 获取本Frame下的View指针
///
///
WindowAppUiView* WindowAppUiFrame::getUiView()
{
return ui.widgetUiView;
}
///
/// UI元素初始化
///
void WindowAppUiFrame::initUI()
{
//QWidget* mainWidget = new QWidget();
//QVBoxLayout* mainLayout = new QVBoxLayout();
//mainLayout->addWidget(ui.toolbarLayoutFrame, 0, Qt::AlignTop);
//mainLayout->addWidget(ui.toolbarControlFrame, 1, Qt::AlignTop);
//mainLayout->addWidget(ui.widgetUiView);
//mainLayout->setContentsMargins(0, 0, 0, 0);
//mainLayout->setSpacing(0);
//mainWidget->setLayout(mainLayout);
//this->setCentralWidget(mainWidget);
// 2021-8-30 在QMainWindow作为QMdiSubView时,需要将QMainWindow设置为 Widget风格,否则窗体不显示
this->setWindowFlags(Qt::Widget);
ui.widgetUiView->uiScene()->m_pUiFrame = this;
QScrollArea* ScrollArea = new QScrollArea(ui.widget_1);
ScrollArea->setWidget(ui.widgetUiView);//设置滚动条
ui.gridLayout->addWidget(ScrollArea);
connect(ScrollArea->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(horizontalValueChanged(int)));
connect(ScrollArea->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(verticalValueChanged(int)));
//connect(ScrollArea->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(valueChanged(int)));
ui.widgetUiView->resize(this->m_nUiViewWidth, this->m_nUiViewHeight);
// 初始化界面分隔区域
//for (int i = 0; i < thePrefs.listUiStretchFactors.size(); i++)
//{
// ui.splitter->setStretchFactor(i, 4);
//}
//// 更新界面分隔区域
//this->updateSplitterFromPref();
// 先按照默认尺寸进行拆分
ui.splitter->setStretchFactor(0, 4);
ui.splitter->setStretchFactor(1, 2);
//QList list = ui.splitter->sizes();
}
///
/// 初始化布局工具栏
///
void WindowAppUiFrame::initLayoutToolbar()
{
m_layoutToolbar = new QToolBar();
m_layoutToolbar->setToolButtonStyle(Qt::ToolButtonIconOnly);
QAction* actionZorderTop = new QAction(QIcon(":/image/ZorderTop.png"), ("ZorderTop"));
QAction* actionZorderBottom = new QAction(QIcon(":/image/ZorderBottom.png"), ("ZorderBottom"));
QAction* actionZorderUp = new QAction(QIcon(":/image/ZorderUp.png"), ("ZorderUp"));
QAction* actionZorderDown = new QAction(QIcon(":/image/ZorderDown.png"), ("ZorderDown"));
// QAction* actionAlignLeft = new QAction(QIcon(":/image/AlignLeft.png"), ("Align Left"));
// QAction* actionAlignTop = new QAction(QIcon(":/image/AlignTop.png"), ("Align Top"));
// QAction* actionAlignRight = new QAction(QIcon(":/image/AlignRight.png"), ("Align Right"));
// QAction* actionAlignBottom = new QAction(QIcon(":/image/AlignBottom.png"), ("Align Bottom"));
// QAction* actionSamesize = new QAction(QIcon("./image/Samesize.png"), ("Make same size"));
// QAction* actionZoomIn = new QAction(QIcon(":/image/ZoomOut.png"), ("Zoom In"));
// QAction* actionZoomOut = new QAction(QIcon(":/image/ZoomIn.png"), ("Zoom Out"));
// QAction* actionZoomZero = new QAction(QIcon(":/image/Zoom.png"), ("Zoom Zero"));
QAction* actionOption = new QAction(QIcon(":/image/Option.png"), ("Options"));
// QAction* actionSnap = new QAction(QIcon(":/image/Snap.png"), ("Snap to Grid"));
// 2022-9-29,增加了Undo和Redo操作
actionUndo = new QAction(QIcon(":/image/Undo.png"), ("Undo"));
actionRedo = new QAction(QIcon(":/image/Redo.png"), ("Redo"));
// QAction* actionUpdate = new QAction(QIcon(":/image/Update.png"), ("Update ro Runtime"));
QAction* actionDelete = new QAction(QIcon(":/image/Delete.png"), ("Delete"));
QAction* actionPublish = new QAction(QIcon(":/image/ui_run.png"), ("Publish UI in Runtime"));
m_layoutToolbar->addAction(actionZorderTop);
m_layoutToolbar->addAction(actionZorderBottom);
m_layoutToolbar->addAction(actionZorderUp);
m_layoutToolbar->addAction(actionZorderDown);
m_layoutToolbar->addSeparator();
// m_layoutToolbar->addAction(actionAlignLeft);
// m_layoutToolbar->addAction(actionAlignTop);
// m_layoutToolbar->addAction(actionAlignRight);
// m_layoutToolbar->addAction(actionAlignBottom);
// m_layoutToolbar->addAction(actionSamesize);
// m_layoutToolbar->addSeparator();
// m_layoutToolbar->addAction(actionZoomIn);
// m_layoutToolbar->addAction(actionZoomOut);
// m_layoutToolbar->addAction(actionZoomZero);
m_layoutToolbar->addAction(actionOption);
// m_layoutToolbar->addAction(actionSnap);
m_layoutToolbar->addSeparator();
m_layoutToolbar->addAction(actionUndo);
m_layoutToolbar->addAction(actionRedo);
m_layoutToolbar->addSeparator();
// m_layoutToolbar->addAction(actionUpdate);
m_layoutToolbar->addAction(actionDelete);
m_layoutToolbar->addSeparator();
m_layoutToolbar->addAction(actionPublish);
m_layoutToolbar->setIconSize(QSize(14, 14));
// 工具栏Signal
connect(actionZorderTop, &QAction::triggered, this, &WindowAppUiFrame::onToolZorderTop);
connect(actionZorderBottom, &QAction::triggered, this, &WindowAppUiFrame::onToolZorderBottom);
connect(actionZorderUp, &QAction::triggered, this, &WindowAppUiFrame::onToolZorderUp);
connect(actionZorderDown, &QAction::triggered, this, &WindowAppUiFrame::onToolZorderDown);
connect(actionUndo, &QAction::triggered, this, &WindowAppUiFrame::onToolUndo);
connect(actionRedo, &QAction::triggered, this, &WindowAppUiFrame::onToolRedo);
connect(actionPublish, &QAction::triggered, this, &WindowAppUiFrame::onToolPublish);
connect(actionDelete, &QAction::triggered, this, &WindowAppUiFrame::onToolDelete);
connect(actionOption, &QAction::triggered, this, &WindowAppUiFrame::onToolOption);
// 拆分栏Signal
connect(ui.splitter, SIGNAL(splitterMoved(int, int)), this, SLOT(slotSplitterMoved(int, int)));
}
///
/// 拆分条移动时(暂未使用)
///
///
///
void WindowAppUiFrame::slotSplitterMoved(int pos, int index)
{
Q_UNUSED(pos);
Q_UNUSED(index);
QList list = ui.splitter->sizes();
// qDebug() << list;
}
//========================================================================
//
// 刻度尺绘制相关
//
//========================================================================
///
/// 绘制水平刻度尺
///
///
///
void WindowAppUiFrame::DrawHorizontalScale(QPainter* painter, QPen* pen)
{
int Y = 51;
int X = 4;
//绘制一条水平坐标线
QPoint ptBegin(X, Y);
QPoint ptEnd(this->rect().width(), Y);
painter->drawLine(ptBegin, ptEnd);
float m_fInterval = 4;
float fDrawLeft = 10;
int nIndex = 0;
int nScaleHeight = 8; //刻度线高度
while (fDrawLeft < this->rect().width())
{
if ((nIndex % 2 == 0) && (nIndex % 5 == 0))
{
nScaleHeight = 8;
QString sText = QString::number(nIndex / 10);
painter->drawText(QPoint(fDrawLeft + X + 2, Y - nScaleHeight + 2), sText);
}
else
{
pen->setWidth(1);
painter->setPen(*pen);
//当是中间节点时,长度要比一般的长
nScaleHeight = (nIndex % 4) == 0 ? 4 : 2;
}
//绘制刻度值
painter->drawRect(QRectF((double)fDrawLeft + (double)X, (double)Y - (double)nScaleHeight, 0.1, (double)nScaleHeight));
fDrawLeft += m_fInterval;
nIndex = nIndex + 1;
}
}
///
/// 绘制垂直刻度尺
///
///
///
void WindowAppUiFrame::DrawVerticalScale(QPainter* painter, QPen* pen)
{
//绘制一条垂直坐标线
int X = 15 - 1;
int Y = 51;
QPoint ptBegin(X, Y);
QPoint ptEnd(X, ui.widgetUiView->rect().height() - Y);
painter->drawLine(ptBegin, ptEnd);
float m_fInterval = 4;
float fDrawTop = 0;
int nIndex = 0;
int nScaleWidth = 20; //刻度线宽度
while (fDrawTop < this->rect().height())
{
if ((nIndex % 2 == 0) && (nIndex % 5 == 0))
{
nScaleWidth = 8;
QString sText = QString::number(nIndex / 10);
int fontWidth = fontMetrics().width(sText);
int nleft = (((X - nScaleWidth) - fontWidth) / 2) + 4;
painter->drawText(QPoint(nleft, fDrawTop + Y + 10), sText);
}
else
{
pen->setWidth(1);
painter->setPen(*pen);
//当是中间节点时,长度要比一般的长
nScaleWidth = (nIndex % 4) == 0 ? 4 : 2;
}
//绘制刻度值
painter->drawRect(QRectF((double)X - (double)nScaleWidth, (double)fDrawTop + (double)Y, nScaleWidth, 0.1));
fDrawTop += m_fInterval;
nIndex++;
}
}
///
/// 绘制界面
///
///
void WindowAppUiFrame::paintEvent(QPaintEvent*)
{
QPainter painter(this);
//设置画刷
QPen pen(Qt::black, 1);
pen.setWidth(1);
painter.setPen(pen);
painter.translate(0, 0);
//抗锯齿绘制
painter.setRenderHint(QPainter::Antialiasing);
//绘制水平刻度尺
this->DrawHorizontalScale(&painter, &pen);
//绘制垂直刻度尺
this->DrawVerticalScale(&painter, &pen);
// 刷新Undo菜单启用禁用
this->refreshUndoMenu();
}
///
/// 水平滚动条数值改变时,保存数值
///
///
void WindowAppUiFrame::horizontalValueChanged(int value)
{
m_nScrollValueH = value;
}
///
/// 垂直滚动条数值改变时,保存数值
///
///
void WindowAppUiFrame::verticalValueChanged(int value)
{
m_nScrollValueV = value;
}
void WindowAppUiFrame::onToolZorderTop()
{
ui.widgetUiView->uiScene()->zorderTopCurrentControl();
}
void WindowAppUiFrame::onToolZorderBottom()
{
ui.widgetUiView->uiScene()->zorderBottomCurrentControl();
}
void WindowAppUiFrame::onToolZorderUp()
{
ui.widgetUiView->uiScene()->zorderUpCurrentControl();
}
void WindowAppUiFrame::onToolZorderDown()
{
ui.widgetUiView->uiScene()->zorderDownCurrentControl();
}
///
/// Undo
///
void WindowAppUiFrame::onToolUndo()
{
// vDebug() << "WindowAppUiFrame::onToolUndo()";
ui.widgetUiView->uiScene()->m_CommandManager.undo();
}
///
/// Redo
///
void WindowAppUiFrame::onToolRedo()
{
// vDebug() << "WindowAppUiFrame::onToolRedo()";
ui.widgetUiView->uiScene()->m_CommandManager.redo();
}
//========================================================================
//
// Toolbar 消息处理
//
//========================================================================
///
/// UI界面设置
///
void WindowAppUiFrame::onToolOption()
{
DialogUiOption dialogUiOption(
this->m_nUiViewWidth,
this->m_nUiViewHeight,
this
);
// 进行UI界面设置
if (dialogUiOption.exec() == QDialog::Accepted)
{
// 保存用户设置的UI宽度和高度
this->m_nUiViewWidth = dialogUiOption.m_nWidth;
this->m_nUiViewHeight = dialogUiOption.m_nHeight;
// 同步修改UiView和UiScene的界面尺寸
ui.widgetUiView->resize(this->m_nUiViewWidth, this->m_nUiViewHeight);
// 调整鸟瞰图View
ui.uiNavView->fitInView(ui.uiNavView->sceneRect(), Qt::KeepAspectRatio);
}
}
///
/// Ui控件删除
///
void WindowAppUiFrame::onToolDelete()
{
// ui.widgetUiView->uiScene()->deleteCurrentControl();
// 2022-10-19,统一替换成了Undo框架进行删除,但是步骤要复杂一些
WindowAppUiScene* uiScene = ui.widgetUiView->uiScene();
// 获取当前删除的控件
VControlObject* pDelControl = uiScene->getCurrentControl();
if (pDelControl == nullptr)
{
vDebug() << "Ignore, current control is nullptr.";
return;
}
// 求出控件的中心点坐标
// 由于控件并非是QGraphicObject,所以位置需要换算一下
QPoint ptControlPos = pDelControl->m_pWidget->pos();
ptControlPos.setX(ptControlPos.x() + pDelControl->m_pWidget->geometry().width() / 2);
ptControlPos.setY(ptControlPos.y() + pDelControl->m_pWidget->geometry().height() / 2);
//QPoint ptPos = pDelControl->m_pProxyWidget->scenePos().toPoint();
// QPoint ptPos2 = pDelControl->m_pWidget->pos();
// 生成删除指令,调用Undo体系进行删除
UiControlDelCommand* controlDelCommand = new UiControlDelCommand(
uiScene,
pDelControl->m_Type,
pDelControl->m_strID,
ptControlPos,
pDelControl->m_pWidget->size()
);
uiScene->m_CommandManager.executeCommand(controlDelCommand);
}
///
/// UI界面发布至Runtime
///
void WindowAppUiFrame::onToolPublish()
{
qDebug() << "WindowAppUiFrame::onActionRun.";
// 通过Manager发布所有UI
bool bRet = g_pUiManager->publishAll();
if (bRet)
{
INFORMATION_MESSAGE("Publish to runtime success!");
// 成功发布后,通知主框架把页面切换到Runtime页面
g_pMainWindow->onViewRunTime();
}
else
{
// CRITICAL_MESSAGE("Publish to runtime failed!");
}
}
///
/// 序列化支持
///
///
///
///
bool WindowAppUiFrame::serialized(QDataStream& ar, bool in /*= true*/)
{
int paranum;//参数数量
// 保存
if (!in)
{
paranum = 3;
ar << paranum;//先保存参数数量
// 宽和高
ar << (int)1 << m_nUiViewWidth;
ar << (int)2 << m_nUiViewHeight;
ar << (int)3 << ui.splitter->sizes();
}
// 读取
else
{
QList splitters;
int para;
ar >> paranum;//读取参数数量
for (int i = 0; i < paranum; i++)
{
ar >> para;
switch (para)
{
case 1: ar >> m_nUiViewWidth; break;
case 2: ar >> m_nUiViewHeight; break;
case 3: ar >> splitters; break;
default:
{
vWarning() << "Serialized(In) Error";
return false;
}
break;
}
}
// 设置Splitter 在 UI 上无数据的时候的(应该是属性表无数据)Splitter 的 sizes 是无效的
if (splitters.size()==2
&& splitters[0] > 0
&& splitters[1] > 0)
{
ui.splitter->setSizes(splitters);
}
}
return true;
}
///
/// 刷新Undo/Redo按钮
///
void WindowAppUiFrame::refreshUndoMenu()
{
if (actionUndo != nullptr)
{
actionUndo->setEnabled( ui.widgetUiView->uiScene()->m_CommandManager.canUndo());
actionRedo->setEnabled( ui.widgetUiView->uiScene()->m_CommandManager.canRedo());
}
}