MDIApplication Example
#include <math.h>
#include <qevent.h>
#include <QApplication>
#include <QLineEdit>
#include <QLabel>
#include <QIcon>
#include <QWidget>
#include <QtitanDef.h>
#include <QtnRibbonGroup.h>
#include "sketchdocument.h"
#include "sketchobject.h"
#include "sketchtool.h"
static double distance(const QPointF& p1, const QPointF& p2)
{
double x = p1.x() - p2.x();
double y = p1.y() - p2.y();
return sqrt (x * x + y * y);
}
Cursor::Cursor()
{
}
Cursor::~Cursor()
{
}
State::State(const QString& strNameState, const QString& strNextNameState, StateState ss, initFunction init, workFunction work)
{
m_init = init;
m_work = work;
m_bActive = false;
m_strNameState = strNameState;
m_strNextNameState = strNextNameState;
m_pCursor = new Cursor;
m_stateState = ss;
}
State::~State()
{
delete m_pCursor;
}
bool GeometricTool::m_autoCreateObject = true;
GeometricTool::GeometricTool(QWidget* pViewPort, SketchDocument* pDoc, GeomObject* pObject)
{
m_editableObject = pObject;
m_viewPort = pViewPort;
m_document = pDoc;
m_currentState = Q_NULL;
m_startTool = false;
}
GeometricTool::~GeometricTool()
{
for (int i = m_statesTool.size()-1; i >= 0; i--)
{
State* object = m_statesTool[i];
m_statesTool.removeAt(i);
delete object;
}
delete m_editableObject;
}
bool GeometricTool::startTool()
{
m_oldCursor = m_viewPort->cursor();
m_startTool = true;
return true;
}
void GeometricTool::stopTool()
{
if (m_startTool)
{
m_startTool = false;
m_viewPort->setCursor(m_oldCursor);
}
m_viewPort->repaint();
m_viewPort->parentWidget()->setStatusTip(QString());
}
bool GeometricTool::createObject()
{
if (m_currentState->getStateState() != ss_readyCreateObject)
return false;
m_document->addObject(m_editableObject->clone());
if (m_autoCreateObject && m_statesTool.size() > 0)
{
delete m_editableObject;
m_editableObject = Q_NULL;
setCurrentState(m_statesTool[0]->nameState());
}
m_viewPort->repaint();
return true;
}
bool GeometricTool::isReady() const
{
if (m_currentState)
return m_currentState->getStateState() == ss_readyCreateObject;
return false;
}
void GeometricTool::mousePressEvent(double posX, double posY)
{
if (m_currentState)
{
QString nextState = m_currentState->nameNextState();
if (!nextState.isEmpty())
{
State* pState = findState(nextState);
pState->cursor()->setPosCursor(QPointF(posX, posY));
setCurrentState(nextState);
}
}
}
void GeometricTool::mouseReleaseEvent(double posX, double posY)
{
Q_UNUSED(posX);
Q_UNUSED(posY);
}
void GeometricTool::mouseMoveEvent(double posX, double posY)
{
if (m_currentState && m_currentState->m_work)
{
m_currentState->cursor()->setPosCursor(QPointF(posX, posY));
(this->*(m_currentState->m_work))();
}
m_viewPort->parentWidget()->setStatusTip(m_currentState ? m_currentState->getStatusTip() : QString());
}
State* GeometricTool::addState(QString strNameState, QString strNextNameState, StateState ss, initFunction init, workFunction work)
{
State* pState = findState(strNameState);
Q_ASSERT(!pState);
if (pState)
return pState;
pState = new State(strNameState, strNextNameState, ss, init, work);
m_statesTool.append(pState);
return pState;
}
void GeometricTool::setCurrentState(const QString& strNameState)
{
Q_ASSERT(!strNameState.isEmpty());
if (!m_startTool)
return;
if (strNameState.isEmpty())
return;
m_currentState = Q_NULL;
int nIndexCurrent = -1;
for(int i= 0, count = m_statesTool.count(); count > i; i++)
{
bool bCurrent = strNameState == m_statesTool[i]->nameState();
m_statesTool[i]->setActive(bCurrent);
if (bCurrent)
nIndexCurrent = i;
}
Q_ASSERT(nIndexCurrent != -1);
if (nIndexCurrent != -1)
{
m_currentState = m_statesTool[nIndexCurrent];
if (m_currentState->m_init)
(this->*(m_currentState->m_init))();
}
if (m_autoCreateObject && m_currentState && m_currentState->getStateState() == ss_readyCreateObject)
createObject();
setCursorState(m_currentState ? m_currentState->nameState() : QString());
m_viewPort->parentWidget()->setStatusTip(m_currentState ? m_currentState->getStatusTip() : QString());
emit stateChanged(m_currentState ? m_currentState->getStateState() : ss_notDefined);
}
State* GeometricTool::currentState() const
{
return m_currentState;
}
void GeometricTool::setCursorState(const QString& nameState)
{
Q_UNUSED(nameState)
}
State* GeometricTool::findState(const QString& strNameState)
{
for(int i= 0, count = m_statesTool.count(); count > i; i++)
{
if (strNameState == m_statesTool[i]->nameState())
return m_statesTool[i];
}
return Q_NULL;
}
#define MAX_WIDTH_WIDGET 80
#define LINE dynamic_cast<GeomLine*>(m_editableObject)
LineTool::LineTool(QWidget* pView, SketchDocument* pDoc, GeomObject* pObject)
: GeometricTool(pView, pDoc, pObject)
{
Q_UNUSED(pObject);
State* pState = Q_NULL;
pState = ADDSTATE(QStringLiteral("initStart"), QString(), ss_notDefined, EV_INIT(LineTool::initStart), Q_NULL );
pState = ADDSTATE(QStringLiteral("findPoint1"), QStringLiteral("findPoint2"), ss_notDefined, Q_NULL, EV_WORK(LineTool::findPoint1));
pState->setStatusTip(tr("Specify the first point of the segment"));
pState = ADDSTATE(QStringLiteral("findPoint2"), QStringLiteral("ready"), ss_notDefined, EV_INIT(LineTool::initP2), EV_WORK(LineTool::findPoint2));
pState->setStatusTip(tr("Specify the second point of the segment"));
pState = ADDSTATE(QStringLiteral("ready"), QString(), ss_readyCreateObject, EV_INIT(LineTool::initReady), Q_NULL );
pState->setStatusTip(tr("Create a circle"));
}
LineTool::~LineTool()
{
}
bool LineTool::startTool()
{
if (GeometricTool::startTool())
{
setCurrentState(QStringLiteral("initStart"));
return true;
}
return false;
}
void LineTool::activate()
{
m_pLabel1 = new QLabel(tr("Point 1, mm"));
m_holder->addWidget(m_pLabel1);
m_pEditX1 = new QLineEdit();
m_pEditX1->setReadOnly(true);
m_pEditX1->setMaximumWidth(MAX_WIDTH_WIDGET);
m_holder->addWidget(QIcon(), tr("X:"), true, m_pEditX1);
m_pEditY1 = new QLineEdit();
m_pEditY1->setReadOnly(true);
m_pEditY1->setMaximumWidth(MAX_WIDTH_WIDGET);
m_holder->addWidget(QIcon(), tr("Y:"), true, m_pEditY1);
m_pLabel2 = new QLabel(tr(" Point 2, mm"));
m_holder->addWidget(m_pLabel2);
m_pEditX2 = new QLineEdit();
m_pEditX2->setReadOnly(true);
m_pEditX2->setMaximumWidth(MAX_WIDTH_WIDGET);
m_holder->addWidget(QIcon(), tr(" X:"), true, m_pEditX2);
m_pEditY2 = new QLineEdit();
m_pEditY2->setReadOnly(true);
m_pEditY2->setMaximumWidth(MAX_WIDTH_WIDGET);
m_holder->addWidget(QIcon(), tr(" Y:"), true, m_pEditY2);
m_pLabel3 = new QLabel(tr(" Length, mm"));
m_holder->addWidget(m_pLabel3);
m_pLength = new QLineEdit();
m_pLength->setReadOnly(true);
m_pLength->setMaximumWidth(MAX_WIDTH_WIDGET);
m_holder->addWidget(QIcon(), tr(" L:"), m_pLength);
if (LINE)
{
m_pEditX1->setText(QStringLiteral("%1").arg(LINE->getFirstPoint().x()));
m_pEditY1->setText(QStringLiteral("%1").arg(LINE->getFirstPoint().y()));
m_pEditX2->setText(QStringLiteral("%1").arg(LINE->getSecondPoint().x()));
m_pEditY2->setText(QStringLiteral("%1").arg(LINE->getSecondPoint().y()));
m_pLength->setText(QStringLiteral("%1").arg(::distance(LINE->getFirstPoint(), LINE->getSecondPoint())));
}
}
void LineTool::deactivate()
{
Q_DELETE_AND_NULL(m_pLabel1);
Q_DELETE_AND_NULL(m_pEditX1);
Q_DELETE_AND_NULL(m_pEditY1);
Q_DELETE_AND_NULL(m_pLabel2);
Q_DELETE_AND_NULL(m_pEditX2);
Q_DELETE_AND_NULL(m_pEditY2);
Q_DELETE_AND_NULL(m_pLabel3);
Q_DELETE_AND_NULL(m_pLength);
}
void LineTool::setCursorState(const QString& nameState)
{
if (QStringLiteral("findPoint1") == nameState)
m_viewPort->setCursor(QCursor(QPixmap(QStringLiteral(":/res/firstCursor.png"))));
else if (QStringLiteral("findPoint2") == nameState)
m_viewPort->setCursor(QCursor(QPixmap(QStringLiteral(":/res/secondCursor.png"))));
else
m_viewPort->setCursor(QCursor(QPixmap(QStringLiteral(":/res/findObjectCursor.png"))));
}
bool LineTool::initStart()
{
Q_ASSERT(!m_editableObject);
m_editableObject = new GeomLine();
LINE->setVisible(false);
setCurrentState(QStringLiteral("findPoint1"));
if (m_pEditX1 && m_pEditY1 && m_pEditX2 && m_pEditY2 && m_pLength)
{
m_pEditX1->setText(QString());
m_pEditY1->setText(QString());
m_pEditX2->setText(QString());
m_pEditY2->setText(QString());
m_pLength->setText(QString());
}
return false;
}
void LineTool::findPoint1()
{
if (m_pEditX1 && m_pEditY1)
{
QPointF pos(currentState()->cursor()->posCursor());
m_pEditX1->setText(QStringLiteral("%1").arg(pos.x()));
m_pEditY1->setText(QStringLiteral("%1").arg(pos.y()));
}
}
bool LineTool::initP2()
{
QPointF pos(currentState()->cursor()->posCursor());
LINE->setFirstPoint(pos);
LINE->setSecondPoint(pos);
LINE->setVisible(true);
m_viewPort->repaint();
return true;
}
void LineTool::findPoint2()
{
QPointF pos(currentState()->cursor()->posCursor());
LINE->setSecondPoint(pos);
if (m_pEditX2 && m_pEditY2)
{
m_pEditX2->setText(QStringLiteral("%1").arg(pos.x()));
m_pEditY2->setText(QStringLiteral("%1").arg(pos.y()));
}
if (m_pLength)
m_pLength->setText(QStringLiteral("%1").arg(::distance(LINE->getFirstPoint(), LINE->getSecondPoint())));
m_viewPort->repaint();
}
bool LineTool::initReady()
{
QPointF pos(currentState()->cursor()->posCursor());
LINE->setSecondPoint(pos);
m_viewPort->repaint();
return true;
}
#undef LINE
#define CIRCLE dynamic_cast<GeomCircle*>(m_editableObject)
CircleTool::CircleTool(QWidget* pView, SketchDocument* pDoc, GeomObject* pObject)
: GeometricTool(pView, pDoc, pObject)
{
Q_UNUSED(pObject);
State* pState = Q_NULL;
pState = ADDSTATE(QStringLiteral("initStart"), QString(), ss_notDefined, EV_INIT(CircleTool::initStart), Q_NULL );
pState = ADDSTATE(QStringLiteral("findCenter"), QStringLiteral("findRadius"), ss_notDefined, Q_NULL, EV_WORK(CircleTool::findCenter));
pState->setStatusTip(tr("Specify the center of the circle"));
pState = ADDSTATE(QStringLiteral("findRadius"), QStringLiteral("ready"), ss_notDefined, EV_INIT(CircleTool::initCenter), EV_WORK(CircleTool::findRadius ));
pState->setStatusTip(tr("Specify the radius of the circle"));
pState = ADDSTATE(QStringLiteral("ready"), QString(), ss_readyCreateObject, EV_INIT(CircleTool::initReady), Q_NULL );
pState->setStatusTip(tr("Create a circle"));
}
CircleTool::~CircleTool()
{
}
bool CircleTool::startTool()
{
if (GeometricTool::startTool())
{
setCurrentState(QStringLiteral("initStart"));
return true;
}
return false;
}
void CircleTool::activate()
{
m_pLabel1 = new QLabel(tr("Center, mm"));
m_holder->addWidget(m_pLabel1);
m_pEditX1 = new QLineEdit();
m_pEditX1->setReadOnly(true);
m_pEditX1->setMaximumWidth(MAX_WIDTH_WIDGET);
m_holder->addWidget(QIcon(), tr("X:"), true, m_pEditX1);
m_pEditY1 = new QLineEdit();
m_pEditY1->setReadOnly(true);
m_pEditY1->setMaximumWidth(MAX_WIDTH_WIDGET);
m_holder->addWidget(QIcon(), tr("Y:"), true, m_pEditY1);
m_pLabel2 = new QLabel(tr(" Radius, mm"));
m_holder->addWidget(m_pLabel2);
m_pRadius = new QLineEdit();;
m_pRadius->setReadOnly(true);
m_pRadius->setMaximumWidth(MAX_WIDTH_WIDGET);
m_holder->addWidget(QIcon(), tr(" R:"), m_pRadius);
if (CIRCLE)
{
m_pEditX1->setText(QStringLiteral("%1").arg(CIRCLE->getCenter().x()));
m_pEditY1->setText(QStringLiteral("%1").arg(CIRCLE->getCenter().y()));
m_pRadius->setText(QStringLiteral("%1").arg(CIRCLE->getRadius()));
}
}
void CircleTool::deactivate()
{
m_holder->remove(m_pLabel1);
delete m_pLabel1;
m_pLabel1 = Q_NULL;
m_holder->remove(m_pEditX1);
delete m_pEditX1;
m_pEditX1 = Q_NULL;
m_holder->remove(m_pEditY1);
delete m_pEditY1;
m_pEditY1 = Q_NULL;
m_holder->remove(m_pLabel2);
delete m_pLabel2;
m_pLabel2 = Q_NULL;
m_holder->remove(m_pRadius);
delete m_pRadius;
m_pRadius = Q_NULL;
}
void CircleTool::setCursorState(const QString& nameState)
{
if (QStringLiteral("findCenter") == nameState)
m_viewPort->setCursor(QCursor(QPixmap(QStringLiteral(":/res/centerCursor.png"))));
else if (QStringLiteral("findRadius") == nameState)
m_viewPort->setCursor(QCursor(QPixmap(QStringLiteral(":/res/secondCursor.png"))));
else
m_viewPort->setCursor(QCursor(QPixmap(QStringLiteral(":/res/findObjectCursor.png"))));
}
bool CircleTool::initStart()
{
Q_ASSERT(!m_editableObject);
m_editableObject = new GeomCircle();
CIRCLE->setVisible(false);
setCurrentState(QStringLiteral("findCenter"));
if (m_pEditX1 && m_pEditY1 && m_pRadius)
{
m_pEditX1->setText(QString());
m_pEditY1->setText(QString());
m_pRadius->setText(QString());
}
return false;
}
void CircleTool::findCenter()
{
QPointF pos(currentState()->cursor()->posCursor());
if (m_pEditX1 && m_pEditY1)
{
m_pEditX1->setText(QStringLiteral("%1").arg(pos.x()));
m_pEditY1->setText(QStringLiteral("%1").arg(pos.y()));
}
}
bool CircleTool::initCenter()
{
QPointF pos(currentState()->cursor()->posCursor());
CIRCLE->setCenter(pos);
CIRCLE->setRadius(::distance(pos, pos));
CIRCLE->setVisible(true);
if (m_pRadius)
m_pRadius->setText(QStringLiteral("%1").arg(CIRCLE->getRadius()));
m_viewPort->repaint();
return true;
}
void CircleTool::findRadius()
{
QPointF pos(currentState()->cursor()->posCursor());
CIRCLE->setRadius(::distance(CIRCLE->getCenter(), pos));
if (m_pRadius)
m_pRadius->setText(QStringLiteral("%1").arg(CIRCLE->getRadius()));
m_viewPort->repaint();
}
bool CircleTool::initReady()
{
QPointF pos(currentState()->cursor()->posCursor());
CIRCLE->setRadius(::distance(CIRCLE->getCenter(), pos));
m_viewPort->repaint();
return true;
}
#undef CIRCLE
#define RECTANGLE dynamic_cast<GeomRectangle*>(m_editableObject)
RectangleTool::RectangleTool(QWidget* pView, SketchDocument* pDoc, GeomObject* pObject)
: GeometricTool(pView, pDoc, pObject)
{
Q_UNUSED(pObject);
State* pState = Q_NULL;
pState = ADDSTATE(QStringLiteral("initStart"), QString(), ss_notDefined, EV_INIT(RectangleTool::initStart), Q_NULL );
pState = ADDSTATE(QStringLiteral("findPoint1"), QStringLiteral("findPoint2"), ss_notDefined, Q_NULL, EV_WORK(RectangleTool::findPoint1));
pState->setStatusTip(tr("Specify the first point of the segment"));
pState = ADDSTATE(QStringLiteral("findPoint2"), QStringLiteral("ready"), ss_notDefined, EV_INIT(RectangleTool::initP2), EV_WORK(RectangleTool::findPoint2));
pState->setStatusTip(tr("Specify the second point of the segment"));
pState = ADDSTATE(QStringLiteral("ready"), QString(), ss_readyCreateObject, EV_INIT(RectangleTool::initReady), Q_NULL );
pState->setStatusTip(tr("Create a circle"));
}
RectangleTool::~RectangleTool()
{
}
bool RectangleTool::startTool()
{
if (GeometricTool::startTool())
{
setCurrentState(QStringLiteral("initStart"));
return true;
}
return false;
}
void RectangleTool::setCursorState(const QString& nameState)
{
if (QStringLiteral("findPoint1") == nameState)
m_viewPort->setCursor(QCursor(QPixmap(QStringLiteral(":/res/firstCursor.png"))));
else if (QStringLiteral("findPoint2") == nameState)
m_viewPort->setCursor(QCursor(QPixmap(QStringLiteral(":/res/secondCursor.png"))));
else
m_viewPort->setCursor(QCursor(QPixmap(QStringLiteral(":/res/findObjectCursor.png"))));
}
bool RectangleTool::initStart()
{
Q_ASSERT(!m_editableObject);
m_editableObject = new GeomRectangle();
RECTANGLE->setVisible(false);
setCurrentState(QStringLiteral("findPoint1"));
return false;
}
void RectangleTool::findPoint1()
{
}
bool RectangleTool::initP2()
{
QPointF pos(currentState()->cursor()->posCursor());
RECTANGLE->setFirstPoint(pos);
RECTANGLE->setSecondPoint(pos);
RECTANGLE->setVisible(true);
m_viewPort->repaint();
return true;
}
void RectangleTool::findPoint2()
{
QPointF pos(currentState()->cursor()->posCursor());
RECTANGLE->setSecondPoint(pos);
m_viewPort->repaint();
}
bool RectangleTool::initReady()
{
QPointF pos(currentState()->cursor()->posCursor());
RECTANGLE->setSecondPoint(pos);
m_viewPort->repaint();
return true;
}
#undef RECTANGLE