libreCAD源码阅读笔记4
前言
总的来说,程序主窗口QC_ApplicationWindow使用QMdiArea作为多文档主界面,每个文档QC_MDIWindow使用RS_Document作为数据存储模型,QG_Graphicview作为每个文档窗口部件;QC_ApplicationWindow主窗口构造函数中使用工具类LC_ActionFactory生成各种程序Action,这些Action触发后都将调用QG_ActionHandler中的函数作为Action信号的槽函数。QG_ActionHandler槽函数根据信号源确定是什么Action操作类型,调用其成员函数setCurrentAction()产生具体Action对象,并调用其关联的QG_GraphicView也调用其自身setCurrentAction()将Action对象传递给RS_EventHandler。此后,当用户窗口绘图后,回调用当前的Action对象进行相关操作。
比如画线
- 1 当主窗口点击画线按钮,触发画线的Action,根据下面代码,程序将会调用QG_ActionHandler的slotDrawLine()函数。
LC_ActionFactory.cpp : 120行
action = new QAction(tr("&2 Points"), agm->line);
action->setIcon(QIcon(":/icons/line_2p.svg"));
connect(action, SIGNAL(triggered()),
action_handler, SLOT(slotDrawLine()));
action->setObjectName("DrawLine");
a_map["DrawLine"] = action;
QG_ActionHandler.cpp : 1329行
void QG_ActionHandler::slotDrawLine() {
setCurrentAction(RS2::ActionDrawLine);
}
RS_ActionInterface* QG_ActionHandler::setCurrentAction(RS2::ActionType id) {
......
switch (id) {
......
case RS2::ActionDrawLine:
a = new RS_ActionDrawLine(*document, *view);
break;
......
if (a) {
view->setCurrentAction(a);
}
- 2 QG_ActionHandler生成具体Action后,将其传递给QG_GraphicView,作为当前需要执行的动作。
QG_GraphicView.cpp : 1054行
void QG_GraphicView::setCurrentQAction(QAction* q_action)
{
eventHandler->setQAction(q_action);
if (recent_actions.contains(q_action))
{
recent_actions.removeOne(q_action);
}
recent_actions.prepend(q_action);
}
- 3 QG_GraphicView将此Action传递给RS_EventHandler。RS_EventHandler作为事件监听,当用户按下鼠标键或者鼠标移动时候,会触发器相应的函数。
QG_GraphicView.cpp : 288 行
void QG_GraphicView::mouseReleaseEvent(QMouseEvent* event)
{
......
switch (event->button())
{
case Qt::RightButton:
......
default:
eventHandler->mouseReleaseEvent(event);
break;
}
RS_DEBUG->print("QG_GraphicView::mouseReleaseEvent: OK");
}
RS_EventHandler.cpp : 115行
void RS_EventHandler::mouseReleaseEvent(QMouseEvent* e) {
if(hasAction()){
// if (actionIndex>=0 && currentActions[actionIndex] &&
// !currentActions[actionIndex]->isFinished()) {
RS_DEBUG->print("call action %s",
currentActions.last()->getName().toLatin1().data());
currentActions.last()->mouseReleaseEvent(e); /// 注意:调用具体Action的mouseReleaseEvent函数
// Clean up actions - one might be finished now
cleanUp();
e->accept();
} else {
if (defaultAction) {
defaultAction->mouseReleaseEvent(e);
} else {
e->ignore();
}
}
}
- 4 最后将事件传递给具体实体对象,实体对象完成自身绘制。
RS_ActionDrawLine.cpp : 164行
void RS_ActionDrawLine::mouseReleaseEvent(QMouseEvent* e)
{
if (e->button() == Qt::LeftButton) {
RS_Vector snapped = snapPoint(e);
// Snapping to angle(15*) if shift key is pressed
if ((e->modifiers() & Qt::ShiftModifier)
&& getStatus() == SetEndpoint ) {
snapped = snapToAngle(snapped, pPoints->data.startpoint, 15.);
}
RS_CoordinateEvent ce(snapped);
coordinateEvent(&ce);
}
else if (e->button() == Qt::RightButton) {
deletePreview();
switch (getStatus()) {
default:
case SetStartpoint:
init( getStatus() - 1);
break;
case SetEndpoint:
next();
break;
}
}
}
结束
学习记录下大体程序流程,其他还有很多细节内容需要进一步分析学习。比如libreCAD如何实现命令窗口绘制实体对象的?下次学习从RS_Commands类开始吧。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容