| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include <cmath> |
| | #include <cstdlib> |
| | #include <iostream> |
| |
|
| | #include <QDebug> |
| | #include <QGridLayout> |
| | #include <QLabel> |
| | #include <QMenu> |
| | #include <QNativeGestureEvent> |
| | #include <QPoint> |
| | #include <QPointingDevice> |
| | #include <QTimer> |
| |
|
| | #include "qg_graphicview.h" |
| |
|
| | #include "lc_actioncontext.h" |
| | #include "lc_actionmodifymoveadjust.h" |
| | #include "lc_eventhandler.h" |
| | #include "lc_graphicviewport.h" |
| | #include "lc_graphicviewrenderer.h" |
| | #include "lc_overlayentitiescontainer.h" |
| | #include "lc_quickinfowidget.h" |
| | #include "lc_rect.h" |
| | #include "lc_ucs_mark.h" |
| | #include "qc_applicationwindow.h" |
| | #include "qg_blockwidget.h" |
| | #include "qg_scrollbar.h" |
| | #include "rs.h" |
| | #include "rs_actiondefault.h" |
| | #include "rs_actionmodifyentity.h" |
| | #include "rs_actionselectsingle.h" |
| | #include "rs_blocklist.h" |
| | #include "rs_debug.h" |
| | #include "rs_dialogfactoryinterface.h" |
| | #include "rs_entity.h" |
| | #include "rs_entitycontainer.h" |
| | #include "rs_graphic.h" |
| | #include "rs_insert.h" |
| | #include "rs_settings.h" |
| |
|
| | #ifdef EMU_C99 |
| | #include "emu_c99.h" |
| | #endif |
| |
|
| | namespace { |
| | |
| | constexpr int g_cursorSize=32; |
| | |
| | constexpr int g_hotspotXY=-1; |
| |
|
| | |
| | constexpr int g_MaxBlockNameLength = 40; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | constexpr double zoomFactor = 1.137; |
| | |
| | constexpr double zoomWheelDivisor = 200.; |
| |
|
| |
|
| | |
| | bool withinValidRange(double x) { |
| | return x >= RS_MINDOUBLE && x <= RS_MAXDOUBLE; |
| | } |
| |
|
| | bool withinValidRange(const RS_Vector& vp){ |
| | return vp.valid && withinValidRange(vp.x) && withinValidRange(vp.y); |
| | } |
| |
|
| | bool isRectValid(const RS_Vector& vpMin, const RS_Vector& vpMax) { |
| | return |
| | withinValidRange(vpMin) |
| | && withinValidRange(vpMax) |
| | && vpMin.x < vpMax.x |
| | && vpMin.y < vpMax.y |
| | && vpMin.x + 1e6 >= vpMax.x |
| | && vpMin.y + 1e6 >= vpMax.y; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_Entity* snapEntity(const QG_GraphicView& view, const QMouseEvent* event) { |
| | if (event == nullptr) { |
| | return nullptr; |
| | } |
| | RS_EntityContainer* container = view.getContainer(); |
| | if (container == nullptr) { |
| | return nullptr; |
| | } |
| | const QPointF mapped = event->pos(); |
| | double distance = RS_MAXDOUBLE; |
| | const LC_GraphicViewport* viewPort = view.getViewPort(); |
| |
|
| | auto pos = viewPort->toWorldFromUi(mapped.x(), mapped.y()); |
| | RS_Entity* entity = container->getNearestEntity(pos, &distance, RS2::ResolveNone); |
| |
|
| | return (viewPort->toGuiDX(distance) <= g_cursorSize) ? entity : nullptr; |
| | } |
| |
|
| | |
| | |
| | |
| | RS_Insert* getAncestorInsert(RS_Entity* entity) { |
| | while (entity != nullptr) { |
| | if (entity->rtti() == RS2::EntityInsert) { |
| | RS_Insert* parent = getAncestorInsert(entity->getParent()); |
| | return parent != nullptr ? parent : static_cast<RS_Insert*>(entity); |
| | } |
| | entity = entity->getParent(); |
| | } |
| | return nullptr; |
| | } |
| | |
| | |
| | RS_Entity* getParentText(RS_Insert* insert) { |
| | if (insert == nullptr || insert->getBlock() != nullptr || insert->getParent() == nullptr) { |
| | return nullptr; |
| | } |
| | switch (insert->getParent()->rtti()) { |
| | case RS2::EntityText: |
| | case RS2::EntityMText: |
| | return insert->getParent(); |
| | default: |
| | return nullptr; |
| | } |
| | } |
| |
|
| | |
| | void QG_GraphicView::showEntityPropertiesDialog(RS_Entity* entity){ |
| | if (entity == nullptr) { |
| | return; |
| | } |
| |
|
| | |
| | while (entity != nullptr && entity->getParent() != nullptr && entity->getParent()->isSelected()) { |
| | entity = entity->getParent(); |
| | } |
| |
|
| | launchEditProperty(entity); |
| | } |
| |
|
| | void QG_GraphicView::launchEditProperty(RS_Entity* entity){ |
| | RS_EntityContainer* container = getContainer(); |
| | if (entity == nullptr || container == nullptr) { |
| | return; |
| | } |
| | editAction( *entity); |
| |
|
| | |
| | auto* doc = dynamic_cast<RS_Document*>(container); |
| | if (doc != nullptr) { |
| | doc->startUndoCycle(); |
| | } |
| | |
| | auto* defaultAction = dynamic_cast<RS_ActionDefault*>(getEventHandler()->getDefaultAction()); |
| | if (defaultAction != nullptr){ |
| | defaultAction->clearHighLighting(); |
| | } |
| | doc->endUndoCycle(); |
| | } |
| |
|
| | |
| | |
| | |
| | void QG_GraphicView::editAction( RS_Entity& entity){ |
| | RS_EntityContainer* container = getContainer(); |
| | if (container==nullptr) { |
| | return; |
| | } |
| | switch(entity.rtti()) { |
| | case RS2::EntityInsert: { |
| | auto& appWindow = QC_ApplicationWindow::getAppWindow(); |
| | RS_BlockList* blockList = appWindow->getBlockWidget()->getBlockList(); |
| | RS_Block* active = (blockList != nullptr) ? blockList->getActive() : nullptr; |
| | auto* insert = static_cast<RS_Insert*>(&entity); |
| | RS_Block* current = insert->getBlockForInsert(); |
| | if (current == active) { |
| | active=nullptr; |
| | } |
| | else if (blockList != nullptr) { |
| | blockList->activate(current); |
| | } |
| | std::shared_ptr<RS_Block*> scoped{&active, [blockList](RS_Block** pointer) { |
| | if (pointer != nullptr && *pointer != nullptr && blockList != nullptr) |
| | blockList->activate(*pointer); |
| | }}; |
| | switchToAction(RS2::ActionBlocksEdit); |
| | break; |
| | } |
| | default:{ |
| | m_actionContext->saveContextMenuActionContext(&entity,RS_Vector(false), entity.isSelected()); |
| | switchToAction(RS2::ActionModifyEntity); |
| | } |
| | } |
| | } |
| |
|
| | |
| | struct QG_GraphicView::AutoPanData{ |
| | void start(double interval, QG_GraphicView &view){ |
| | m_delayCounter = 0; |
| | panTimer = std::make_unique<QTimer>(&view); |
| | panTimer->start(interval); |
| | connect(panTimer.get(), &QTimer::timeout, &view, &QG_GraphicView::autoPanStep); |
| | } |
| |
|
| | std::unique_ptr<QTimer> panTimer; |
| |
|
| | QPoint panOffset; |
| |
|
| | unsigned m_delayCounter = 0u; |
| | |
| | const unsigned delayCounterMax = 10u; |
| | const double panOffsetMagnitude = 20.0; |
| |
|
| | const double panTimerInterval_minimum = 20.0; |
| | const double panTimerInterval_maximum = 100.0; |
| |
|
| | |
| | const RS_Vector probedAreaOffset = {50 , 50 }; |
| | }; |
| |
|
| | struct QG_GraphicView::UCSHighlightData { |
| | std::unique_ptr<QTimer> m_timer; |
| |
|
| | double m_timerInterval = 200.0; |
| | int m_blinkNumber = 0; |
| | int m_maxBlinkNumber = 15; |
| | bool m_inVisiblePhase = false; |
| | RS_Vector origin; |
| | double angle = 0.0; |
| | bool forWCS = false; |
| |
|
| |
|
| | RS_Vector m_savedViewOffset = RS_Vector(0, 0, 0); |
| | double m_savedViewFactor = 0.0; |
| |
|
| | void start(double interval, QG_GraphicView &view) { |
| | if (m_timer == nullptr) { |
| | m_timer = std::make_unique<QTimer>(&view); |
| | connect(m_timer.get(), &QTimer::timeout, &view, &QG_GraphicView::ucsHighlightStep); |
| | } |
| | m_timer->start(interval); |
| | } |
| |
|
| | bool mayTick(){ |
| | m_blinkNumber++; |
| | m_inVisiblePhase = !m_inVisiblePhase; |
| | return m_blinkNumber <= m_maxBlinkNumber; |
| | } |
| |
|
| | void stop(){ |
| | m_blinkNumber = 0; |
| | m_inVisiblePhase = false; |
| | m_timer->stop(); |
| | } |
| | }; |
| |
|
| | void createViewRenderer(); |
| |
|
| | |
| | |
| | |
| | |
| | QG_GraphicView::QG_GraphicView(QWidget* parent, RS_Document* doc, LC_ActionContext* actionContext) |
| | :RS_GraphicView(parent, {}) |
| | ,m_device("Mouse") |
| | ,m_cursorCad(new QCursor(QPixmap(":cursors/cur_cad_bmp.png"), g_hotspotXY, g_hotspotXY)) |
| | ,m_cursorDel(new QCursor(QPixmap(":cursors/cur_del_bmp.png"), g_hotspotXY, g_hotspotXY)) |
| | ,m_cursorSelect(new QCursor(QPixmap(":cursors/cur_select_bmp.png"), g_hotspotXY, g_hotspotXY)) |
| | ,m_cursorMagnifier(new QCursor(QPixmap(":cursors/cur_glass_bmp.png"), g_hotspotXY, g_hotspotXY)) |
| | ,m_cursorHand(new QCursor(QPixmap(":cursors/cur_hand_bmp.png"), g_hotspotXY, g_hotspotXY)) |
| | ,m_isSmoothScrolling(false) |
| | , m_ucsMarkOptions{std::make_unique<LC_UCSMarkOptions>()} |
| | , m_panData{std::make_unique<AutoPanData>()} |
| | , m_ucsHighlightData{std::make_unique<UCSHighlightData>()} |
| | { |
| | RS_DEBUG->print("QG_GraphicView::QG_GraphicView().."); |
| |
|
| | if (doc != nullptr){ |
| | setContainer(doc); |
| | doc->setGraphicView(this); |
| | actionContext->setDocumentAndView(doc, this); |
| | setDefaultAction(new RS_ActionDefault(actionContext)); |
| | } |
| |
|
| | m_actionContext = actionContext; |
| |
|
| | getViewPort()->justSetOffsetAndFactor(0,0,4.0); |
| | getViewPort()->setBorders(10, 10, 10, 10); |
| |
|
| | setMouseTracking(true); |
| | setFocusPolicy(Qt::NoFocus); |
| |
|
| | |
| | setAttribute(Qt::WA_NoMousePropagation); |
| |
|
| | |
| | #ifdef Q_OS_MAC |
| | setAttribute(Qt::WA_InputMethodEnabled, false); |
| | setInputMethodHints(Qt::ImhNone); |
| | #endif |
| | } |
| |
|
| | void QG_GraphicView::initView() { |
| | createViewRenderer(); |
| | } |
| |
|
| | void QG_GraphicView::createViewRenderer() { |
| | if (getViewPort()) { |
| | getViewPort()->setSize(width(), height()); |
| | setRenderer(std::make_unique<LC_GraphicViewRenderer>(getViewPort(), this)); |
| | } |
| | } |
| |
|
| | void QG_GraphicView::layerToggled(RS_Layer *) { |
| | const RS_EntityContainer::LC_SelectionInfo &info = getContainer()->getSelectionInfo(); |
| | m_actionContext->updateSelectionWidget(info.count, info.length); |
| | |
| | redraw(RS2::RedrawDrawing); |
| | } |
| |
|
| | |
| | |
| | |
| | QG_GraphicView::~QG_GraphicView() { |
| | cleanUp(); |
| | } |
| |
|
| | |
| | |
| | |
| | int QG_GraphicView::getWidth() const{ |
| | if (m_scrollbars) { |
| | return width() - m_vScrollBar->sizeHint().width(); |
| | } |
| | else { |
| | return width(); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | int QG_GraphicView::getHeight() const{ |
| | if (m_scrollbars) { |
| | return height() - m_hScrollBar->sizeHint().height(); |
| | } |
| | else { |
| | return height(); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | void QG_GraphicView::setMouseCursor(RS2::CursorType cursorType) { |
| | switch (cursorType) { |
| | default: |
| | case RS2::ArrowCursor: |
| | setCursor(Qt::ArrowCursor); |
| | break; |
| | case RS2::UpArrowCursor: |
| | setCursor(Qt::UpArrowCursor); |
| | break; |
| | case RS2::CrossCursor: |
| | setCursor(Qt::CrossCursor); |
| | break; |
| | case RS2::WaitCursor: |
| | setCursor(Qt::WaitCursor); |
| | break; |
| | case RS2::IbeamCursor: |
| | setCursor(Qt::IBeamCursor); |
| | break; |
| | case RS2::SizeVerCursor: |
| | setCursor(Qt::SizeVerCursor); |
| | break; |
| | case RS2::SizeHorCursor: |
| | setCursor(Qt::SizeHorCursor); |
| | break; |
| | case RS2::SizeBDiagCursor: |
| | setCursor(Qt::SizeBDiagCursor); |
| | break; |
| | case RS2::SizeFDiagCursor: |
| | setCursor(Qt::SizeFDiagCursor); |
| | break; |
| | case RS2::SizeAllCursor: |
| | setCursor(Qt::SizeAllCursor); |
| | break; |
| | case RS2::BlankCursor: |
| | setCursor(Qt::BlankCursor); |
| | break; |
| | case RS2::SplitVCursor: |
| | setCursor(Qt::SplitVCursor); |
| | break; |
| | case RS2::SplitHCursor: |
| | setCursor(Qt::SplitHCursor); |
| | break; |
| | case RS2::PointingHandCursor: |
| | setCursor(Qt::PointingHandCursor); |
| | break; |
| | case RS2::ForbiddenCursor: |
| | setCursor(Qt::ForbiddenCursor); |
| | break; |
| | case RS2::WhatsThisCursor: |
| | setCursor(Qt::WhatsThisCursor); |
| | break; |
| | case RS2::OpenHandCursor: |
| | setCursor(Qt::OpenHandCursor); |
| | break; |
| | case RS2::ClosedHandCursor: |
| | setCursor(Qt::ClosedHandCursor); |
| | break; |
| | case RS2::CadCursor: |
| | m_cursor_hiding ? setCursor(Qt::BlankCursor) : setCursor(*m_cursorCad); |
| | break; |
| | case RS2::DelCursor: |
| | setCursor(*m_cursorDel); |
| | break; |
| | case RS2::SelectCursor: |
| | m_selectCursor_hiding ? setCursor(Qt::BlankCursor) : setCursor(*m_cursorSelect); |
| | break; |
| | case RS2::MagnifierCursor: |
| | setCursor(*m_cursorMagnifier); |
| | break; |
| | case RS2::MovingHandCursor: |
| | setCursor(*m_cursorHand); |
| | break; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | void QG_GraphicView::updateGridStatusWidget(QString text){ |
| | emit gridStatusChanged(std::move(text)); |
| | } |
| |
|
| | void QG_GraphicView::dragEnterEvent(QDragEnterEvent* event) { |
| | RS_GraphicView::dragEnterEvent(event); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | } |
| |
|
| | |
| | |
| | |
| | void QG_GraphicView::redraw(RS2::RedrawMethod method) { |
| | getRenderer()->invalidate(method); |
| | update(); |
| | } |
| |
|
| | void QG_GraphicView::resizeEvent(QResizeEvent* e) { |
| | RS_GraphicView::resizeEvent(e); |
| | RS_DEBUG->print("QG_GraphicView::resizeEvent begin"); |
| | adjustOffsetControls(); |
| | adjustZoomControls(); |
| | |
| | |
| | getViewPort()->clearOverlayDrawablesContainer(RS2::Snapper); |
| | redraw(); |
| | RS_DEBUG->print("QG_GraphicView::resizeEvent end"); |
| | } |
| |
|
| |
|
| | void QG_GraphicView::switchToAction(RS2::ActionType actionType, void* data) const { |
| | m_actionContext->setCurrentAction(actionType, data); |
| | } |
| |
|
| | RS_Entity* QG_GraphicView::catchContextEntity(QMouseEvent* event, RS_Vector& clickPos) { |
| | auto container = getContainer(); |
| | if (container == nullptr || event == nullptr) { |
| | return nullptr; |
| | } |
| |
|
| | const QPointF mapped = event->pos(); |
| | double distance = RS_MAXDOUBLE; |
| | const LC_GraphicViewport* viewPort = getViewPort(); |
| |
|
| | clickPos = viewPort->toWorldFromUi(mapped.x(), mapped.y()); |
| | RS_Entity* entity = container->getNearestEntity(clickPos, &distance, RS2::ResolveNone); |
| |
|
| | if (viewPort->toGuiDX(distance) <= g_cursorSize) { |
| | return entity; |
| | } |
| | else { |
| | return nullptr; |
| | } |
| | } |
| |
|
| | bool QG_GraphicView::invokeContextMenuForMouseEvent(QMouseEvent* e) { |
| | bool result = false; |
| | RS_Vector clickPos; |
| | RS_Entity* entity = catchContextEntity(e, clickPos); |
| | auto contextMenu = QC_ApplicationWindow::getAppWindow()->createGraphicViewContentMenu(e, this, entity, clickPos); |
| | if (contextMenu != nullptr) { |
| | if (!contextMenu->isEmpty()) { |
| | auto actions = contextMenu->actions(); |
| | if (actions.size() == 1) { |
| | auto action = actions.front(); |
| | action->trigger(); |
| | result = true; |
| | } |
| | else { |
| | contextMenu->exec(mapToGlobal(e->pos())); |
| | result = true; |
| | } |
| | } |
| | delete contextMenu; |
| | } |
| | return result; |
| | } |
| |
|
| | void QG_GraphicView::mousePressEvent(QMouseEvent* event){ |
| | |
| | |
| | if (event->button()==Qt::MiddleButton && event->modifiers() == Qt::NoModifier){ |
| | switchToAction(RS2::ActionZoomPan); |
| | getCurrentAction()->mousePressEvent(event); |
| | } |
| | else { |
| | getEventHandler()->mousePressEvent(event); |
| | } |
| | } |
| |
|
| | void QG_GraphicView::mouseDoubleClickEvent(QMouseEvent* e){ |
| | |
| | if (getEventHandler()->hasAction()) { |
| |
|
| | } |
| | else { |
| | auto defaultAction = getEventHandler()->getDefaultAction(); |
| | RS_Vector clickPos; |
| | RS_Entity* entity = catchContextEntity(e, clickPos); |
| | if (entity == nullptr) { |
| | if (defaultAction == nullptr) { |
| | invokeContextMenuForMouseEvent(e); |
| | } |
| | else if (defaultAction->getStatus() == RS_ActionInterface::InitialActionStatus) { |
| | invokeContextMenuForMouseEvent(e); |
| | } |
| | } |
| | else { |
| | if (e->button() == Qt::LeftButton && e->modifiers() == Qt::NoModifier) { |
| | if (defaultAction == nullptr) { |
| | showEntityPropertiesDialog(entity); |
| | } |
| | else if (defaultAction->getStatus() == RS_ActionInterface::InitialActionStatus) { |
| | showEntityPropertiesDialog(entity); |
| | } |
| | } |
| | else { |
| | invokeContextMenuForMouseEvent(e); |
| | } |
| | } |
| | } |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | e->accept(); |
| | } |
| |
|
| | void QG_GraphicView::mouseReleaseEvent(QMouseEvent* event){ |
| | RS_DEBUG->print("QG_GraphicView::mouseReleaseEvent"); |
| |
|
| | event->accept(); |
| | if (getEventHandler()->hasAction()) { |
| | switch (event->button()) { |
| | case Qt::RightButton: { |
| | if (getEventHandler()->hasAction()) { |
| | back(); |
| | } |
| | break; |
| | } |
| | case Qt::XButton1: |
| | processEnterKey(); |
| | emit xbutton1_released(); |
| | break; |
| | default: |
| | getEventHandler()->mouseReleaseEvent(event); |
| | break; |
| | } |
| | } |
| | else { |
| | auto defaultAction = getEventHandler()->getDefaultAction(); |
| | if (defaultAction != nullptr) { |
| | int defaultActionStatus = defaultAction->getStatus(); |
| | if (defaultActionStatus == RS_ActionInterface::InitialActionStatus) { |
| | if (isMouseReleaseEventForDefaultAction(event)) { |
| | defaultAction->mouseReleaseEvent(event); |
| | } |
| | else { |
| | invokeContextMenuForMouseEvent(event); |
| | } |
| | } |
| | else { |
| | defaultAction->mouseReleaseEvent(event); |
| | } |
| | } |
| | else { |
| | invokeContextMenuForMouseEvent(event); |
| | } |
| | } |
| | RS_DEBUG->print("QG_GraphicView::mouseReleaseEvent: OK"); |
| | } |
| |
|
| | bool QG_GraphicView::isMouseReleaseEventForDefaultAction(QMouseEvent* event) { |
| | |
| | if (event->button() == Qt::LeftButton) { |
| | auto modifiers = event->modifiers(); |
| | if (modifiers == Qt::NoModifier) { |
| | return true; |
| | } |
| | bool control = modifiers & Qt::ControlModifier; |
| | bool alt = modifiers & Qt::AltModifier; |
| | bool shift = modifiers & Qt::ShiftModifier; |
| | if (control && !alt && !shift) { |
| | |
| | return true; |
| | } |
| | if (shift && !alt && !control) { |
| | |
| | return true; |
| | } |
| | } |
| | return false; |
| | } |
| |
|
| | void QG_GraphicView::mouseMoveEvent(QMouseEvent* event){ |
| | |
| | if (isAutoPan(event)) { |
| | startAutoPanTimer(event); |
| | event->accept(); |
| | return; |
| | } |
| | m_panData->panTimer.reset(); |
| | |
| | event->accept(); |
| | getEventHandler()->mouseMoveEvent(event); |
| | } |
| |
|
| | bool QG_GraphicView::proceedEvent(QEvent* event) { |
| | |
| | |
| | if (dynamic_cast<QInputEvent*>(event) == nullptr || getDefaultAction() != nullptr){ |
| | return QWidget::event(event); |
| | } |
| | else { |
| | |
| | } |
| | return true; |
| | } |
| |
|
| | bool QG_GraphicView::event(QEvent *event){ |
| |
|
| | if (event->type() == QEvent::NativeGesture) { |
| | auto *nge = static_cast<QNativeGestureEvent *>(event); |
| |
|
| | if (nge->gestureType() == Qt::ZoomNativeGesture) { |
| | double v = nge->value(); |
| | RS2::ZoomDirection direction = std::signbit(v) ? RS2::Out : RS2::In; |
| | double factor = 1. + std::abs(v); |
| |
|
| | |
| | QPointF g = mapFromGlobal(nge->globalPosition().toPoint()); |
| | RS_Vector mouse = getViewPort()->toWorldFromUi(g.x(), g.y()); |
| | doZoom(direction, mouse, factor); |
| | } |
| | return true; |
| | } |
| | return proceedEvent(event); |
| | } |
| |
|
| | void QG_GraphicView::doZoom(RS2::ZoomDirection direction, RS_Vector& center, double zoom_factor) { |
| | if (direction==RS2::In) { |
| | getViewPort()->zoomIn(zoom_factor, center); |
| | } else { |
| | getViewPort()->zoomOut(zoom_factor, center); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | void QG_GraphicView::tabletEvent(QTabletEvent* e) { |
| | if (testAttribute(Qt::WA_UnderMouse)) { |
| | #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) |
| | switch(e->pointerType()) { |
| | case QPointingDevice::PointerType::Eraser: |
| | if (e->type()==QEvent::TabletRelease) { |
| | if (getContainer() != nullptr) { |
| | auto a = std::make_shared<RS_ActionSelectSingle>(m_actionContext); |
| | setCurrentAction(a); |
| | QMouseEvent ev(QEvent::MouseButtonRelease, e->position(), e->globalPosition(), |
| | Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); |
| | mouseReleaseEvent(&ev); |
| | a->finish(); |
| |
|
| | if (getContainer()->countSelected()>0) { |
| | switchToAction(RS2::ActionModifyDelete); |
| | } |
| | } |
| | } |
| | break; |
| |
|
| | case QPointingDevice::PointerType::Generic: |
| | case QPointingDevice::PointerType::Pen: |
| | case QPointingDevice::PointerType::Cursor: |
| | if (e->type()==QEvent::TabletPress) { |
| | QMouseEvent ev(QEvent::MouseButtonPress, e->position(), e->globalPosition(), |
| | Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); |
| | mousePressEvent(&ev); |
| | } else if (e->type()==QEvent::TabletRelease) { |
| | QMouseEvent ev(QEvent::MouseButtonRelease, e->position(), e->globalPosition(), |
| | Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); |
| | mouseReleaseEvent(&ev); |
| | } else if (e->type()==QEvent::TabletMove) { |
| | QMouseEvent ev(QEvent::MouseMove, e->position(), e->globalPosition(), |
| | Qt::NoButton, {}, Qt::NoModifier); |
| | mouseMoveEvent(&ev); |
| | } |
| | break; |
| | default: |
| | break; |
| | } |
| | #else |
| | #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) |
| | switch (e->deviceType()) { |
| | #else |
| | switch (e->device()) { |
| | #endif |
| | case QTabletEvent::Eraser: |
| | if (e->type()==QEvent::TabletRelease) { |
| | if (getContainer() != nullptr) { |
| |
|
| | RS_ActionSelectSingle* a = |
| | new RS_ActionSelectSingle(*getContainer(), *this); |
| | setCurrentAction(a); |
| | QMouseEvent ev(QEvent::MouseButtonRelease, e->position(), |
| | Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); |
| | mouseReleaseEvent(&ev); |
| | a->finish(); |
| |
|
| | if (getContainer()->countSelected()>0) { |
| | setCurrentAction( |
| | new RS_ActionModifyDelete(*getContainer(), *this)); |
| | } |
| | } |
| | } |
| | break; |
| |
|
| | case QTabletEvent::Stylus: |
| | case QTabletEvent::Puck: |
| | if (e->type()==QEvent::TabletPress) { |
| | QMouseEvent ev(QEvent::MouseButtonPress, e->position(), |
| | Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); |
| | mousePressEvent(&ev); |
| | } else if (e->type()==QEvent::TabletRelease) { |
| | QMouseEvent ev(QEvent::MouseButtonRelease, e->position(), |
| | Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); |
| | mouseReleaseEvent(&ev); |
| | } else if (e->type()==QEvent::TabletMove) { |
| | QMouseEvent ev(QEvent::MouseMove, e->position(), |
| | Qt::NoButton, {}, Qt::NoModifier); |
| | mouseMoveEvent(&ev); |
| | } |
| | break; |
| |
|
| | default: |
| | break; |
| | } |
| | #endif |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | } |
| |
|
| | void QG_GraphicView::leaveEvent(QEvent* e) { |
| | |
| | m_panData->panTimer.reset(); |
| | getEventHandler()->mouseLeaveEvent(); |
| | QWidget::leaveEvent(e); |
| | } |
| |
|
| | void QG_GraphicView::enterEvent(QEnterEvent* e) { |
| | getEventHandler()->mouseEnterEvent(); |
| | QWidget::enterEvent(e); |
| | } |
| |
|
| | void QG_GraphicView::focusOutEvent(QFocusEvent* e) { |
| | QWidget::focusOutEvent(e); |
| | } |
| |
|
| | void QG_GraphicView::focusInEvent(QFocusEvent* e) { |
| | getEventHandler()->mouseEnterEvent(); |
| | QWidget::focusInEvent(e); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | void QG_GraphicView::wheelEvent(QWheelEvent *e) { |
| | |
| | |
| |
|
| | |
| | |
| |
|
| | if (getContainer() == nullptr) { |
| | return; |
| | } |
| |
|
| | #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) |
| | |
| | const QPointF &uiEventPosition = e->position(); |
| | RS_Vector mouse = getViewPort()->toUCSFromGui(uiEventPosition.x(), uiEventPosition.y()); |
| | #else |
| | RS_Vector mouse = toGraph(e->position()); |
| | #endif |
| |
|
| | if (m_device == "Trackpad") { |
| | QPoint numPixels = e->pixelDelta(); |
| |
|
| | |
| | m_isSmoothScrolling |= !numPixels.isNull(); |
| |
|
| | if (m_isSmoothScrolling){ |
| | if (e->phase() == Qt::ScrollEnd) m_isSmoothScrolling = false; |
| | } |
| | else |
| | |
| | { |
| | numPixels = e->angleDelta() / 4; |
| | } |
| |
|
| | if (!numPixels.isNull()){ |
| | if (e->modifiers()==Qt::ControlModifier){ |
| | |
| | double v = (m_invertZoomDirection) ? (numPixels.y() / zoomWheelDivisor) : (-numPixels.y() / zoomWheelDivisor); |
| | RS2::ZoomDirection direction; |
| | if (v < 0) { |
| | direction = RS2::Out; |
| | } else { |
| | direction = RS2::In; |
| | } |
| |
|
| | double zoomFactor = 1. + std::abs(v); |
| | doZoom(direction, mouse, zoomFactor); |
| | } |
| | else{ |
| | int hDelta = (m_invertHorizontalScroll) ? -numPixels.x() : numPixels.x(); |
| | int vDelta = (m_invertVerticalScroll) ? -numPixels.y() : numPixels.y(); |
| |
|
| | |
| | if (m_scrollbars){ |
| | m_hScrollBar->setValue(m_hScrollBar->value() - hDelta); |
| | m_vScrollBar->setValue(m_vScrollBar->value() - vDelta); |
| | } |
| | else { |
| | getViewPort()->zoomPan(hDelta, vDelta); |
| | } |
| | } |
| | redraw(); |
| | } |
| | e->accept(); |
| | return; |
| | } |
| |
|
| | if (e->angleDelta().isNull()) { |
| | |
| | e->accept(); |
| | return; |
| | } |
| |
|
| | bool scroll = false; |
| | RS2::Direction direction = RS2::Up; |
| |
|
| | |
| | int angleDeltaY = e->angleDelta().y(); |
| | int angleDeltaX = e->angleDelta().x(); |
| |
|
| | |
| | |
| | |
| | angleDeltaX = angleDeltaY; |
| | if (e->modifiers() == Qt::ControlModifier) { |
| | scroll = true; |
| | direction= (angleDeltaY > 0) ? RS2::Up : RS2::Down; |
| | } |
| | else if(e->modifiers() == Qt::ShiftModifier){ |
| | scroll = true; |
| | direction= (angleDeltaX > 0) ? RS2::Left : RS2::Right; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | if (scroll && m_scrollbars) { |
| | |
| |
|
| | int delta = 0; |
| |
|
| | switch(direction){ |
| | case RS2::Left: |
| | case RS2::Right: |
| | delta = (m_invertHorizontalScroll) ? -angleDeltaX : angleDeltaX; |
| | m_hScrollBar->setValue(m_hScrollBar->value()+delta); |
| | break; |
| | default: |
| | delta = (m_invertVerticalScroll) ? -angleDeltaY : angleDeltaY; |
| | m_vScrollBar->setValue(m_vScrollBar->value()+delta); |
| | } |
| | } |
| | |
| | else if (e->modifiers()==0) { |
| |
|
| | |
| |
|
| | RS2::ZoomDirection zoomDirection = ((angleDeltaY > 0) != m_invertZoomDirection) ? RS2::In : RS2::Out; |
| |
|
| | const QPoint viewCenter{getWidth()/2, getHeight()/2}; |
| | const QPoint delta = viewCenter - uiEventPosition.toPoint(); |
| |
|
| | if (getPanOnZoom()) { |
| | QCursor::setPos(mapToGlobal(viewCenter)); |
| | getViewPort()->zoomPan(delta.x(), delta.y()); |
| | } |
| | if (!getPanOnZoom() || !getSkipFirstZoom() || (abs(delta.x())<32 && abs(delta.y())<32)) { |
| | RS_Vector& zoomCenter = mouse; |
| | |
| |
|
| | |
| | |
| | |
| | |
| | doZoom(zoomDirection, zoomCenter, m_scrollZoomFactor); |
| | } |
| | } |
| | redraw(); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | } |
| |
|
| | |
| | void QG_GraphicView::keyPressEvent(QKeyEvent * e) { |
| | if (getContainer() == nullptr) { |
| | return; |
| | } |
| | if (m_allowScrollAndMoveAdjustByKeys) { |
| | RS2::Direction direction = RS2::Up; |
| | bool scroll = e->modifiers() == Qt::NoModifier; |
| | bool shift = e->modifiers() & Qt::ShiftModifier; |
| | bool control = e->modifiers() & Qt::ControlModifier; |
| |
|
| | bool move = shift || control; |
| |
|
| | switch (e->key()) { |
| | case Qt::Key_Left: |
| | direction = RS2::Right; |
| | break; |
| | case Qt::Key_Right: |
| | direction = RS2::Left; |
| | break; |
| | case Qt::Key_Up: |
| | direction = RS2::Up; |
| | break; |
| | case Qt::Key_Down: |
| | direction = RS2::Down; |
| | break; |
| | default: |
| | scroll = false; |
| | move = false; |
| | break; |
| | } |
| |
|
| | if (scroll) { |
| | getViewPort()->zoomScroll(direction); |
| | e->accept(); |
| | } |
| | else if (move) { |
| | LC_ActionModifyMoveAdjust::MovementInfo::Step step = LC_ActionModifyMoveAdjust::MovementInfo::GRID; |
| | if (control) { |
| | if (shift) { |
| | step = LC_ActionModifyMoveAdjust::MovementInfo::META_GRID; |
| | } |
| | else { |
| | step = LC_ActionModifyMoveAdjust::MovementInfo::SUB_GRID; |
| | } |
| | } |
| | else if (shift) { |
| | step = LC_ActionModifyMoveAdjust::MovementInfo::GRID; |
| | } |
| |
|
| | LC_ActionModifyMoveAdjust::MovementInfo info(direction, step); |
| | switchToAction(RS2::ActionModifyMoveAdjust, &info); |
| | e->accept(); |
| | } |
| | } |
| | if (!e->isAccepted()){ |
| | getEventHandler()->keyPressEvent(e); |
| | } |
| | } |
| |
|
| | void QG_GraphicView::keyReleaseEvent(QKeyEvent * e){ |
| | getEventHandler()->keyReleaseEvent(e); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | void QG_GraphicView::adjustOffsetControls(){ |
| | if (!m_scrollbars) |
| | return; |
| |
|
| | std::unique_lock<std::mutex> lock(m_scrollbarMutex, std::defer_lock); |
| | if (!lock.try_lock()) { |
| | return; |
| | } |
| |
|
| | if (getContainer()==nullptr || m_hScrollBar==nullptr || m_vScrollBar==nullptr) { |
| | return; |
| | } |
| | LC_LOG<<__func__<<"(): begin"; |
| |
|
| | getContainer()->forcedCalculateBorders(); |
| | RS_Vector vpMin = getContainer()->getMin(); |
| | RS_Vector vpMax = getContainer()->getMax(); |
| |
|
| | |
| | if (!isRectValid(vpMin, vpMax)) { |
| | vpMin = RS_Vector(-10,-10); |
| | vpMax = RS_Vector(100,100); |
| | } |
| |
|
| | int ox = getViewPort()->getOffsetX(); |
| | int oy = getViewPort()->getOffsetY(); |
| |
|
| | int minVal = int(-1.25 * getWidth() - ox); |
| | int maxVal = int( 0.25 * getWidth() - ox); |
| |
|
| | LC_LOG<<__func__<<"(): x scrollbar range["<<minVal<<", "<<maxVal<<"]: "<<getViewPort()->getOffsetX(); |
| | if (minVal<=maxVal) { |
| | m_hScrollBar->setRange(minVal, maxVal); |
| | } |
| |
|
| | minVal = int(0.75 * getHeight() - oy); |
| | maxVal = int(0.25 * getHeight() - oy); |
| |
|
| | if (minVal<=maxVal) { |
| | m_vScrollBar->setRange(minVal, maxVal); |
| | } |
| |
|
| | m_hScrollBar->setPageStep(getWidth()); |
| | m_vScrollBar->setPageStep(getHeight()); |
| |
|
| | m_hScrollBar->setValue(-ox); |
| | m_vScrollBar->setValue(oy); |
| | LC_LOG<<__func__<<"(): y scrollbar range["<<minVal<<", "<<maxVal<<"]: "<<oy; |
| |
|
| | slotHScrolled(-ox); |
| | slotVScrolled(oy); |
| |
|
| |
|
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | LC_LOG<<__func__<<"(): end"; |
| |
|
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | void QG_GraphicView::adjustZoomControls() |
| | { |
| | } |
| |
|
| | |
| | |
| | |
| | void QG_GraphicView::slotHScrolled(int value) { |
| | |
| | |
| |
|
| | auto viewport = getViewPort(); |
| | |
| | |
| | |
| | |
| | if (m_hScrollBar->maximum()==m_hScrollBar->minimum()) { |
| | getContainer()->calculateBorders(); |
| | RS_Vector min = getContainer()->getMin(); |
| | RS_Vector max = getContainer()->getMax(); |
| | RS_Vector ucsMin; |
| | RS_Vector ucsMax; |
| | viewport->ucsBoundingBox(min, max, ucsMin, ucsMax); |
| | RS_Vector containerSize = ucsMax - ucsMin; |
| | viewport->centerOffsetX(ucsMin, containerSize); |
| | } else { |
| | viewport->setOffsetX(-value); |
| | } |
| | |
| | |
| | redraw(); |
| | } |
| |
|
| | |
| | |
| | |
| | void QG_GraphicView::slotVScrolled(int value) { |
| | |
| | |
| |
|
| | if (m_vScrollBar->maximum()==m_vScrollBar->minimum()) { |
| | getContainer()->calculateBorders(); |
| | RS_Vector min = getContainer()->getMin(); |
| | RS_Vector max = getContainer()->getMax(); |
| | RS_Vector ucsMin; |
| | RS_Vector ucsMax; |
| | getViewPort()->ucsBoundingBox(min, max, ucsMin, ucsMax); |
| | RS_Vector containerSize = ucsMax - ucsMin; |
| | getViewPort()->centerOffsetY(ucsMin, containerSize); |
| | } else { |
| | getViewPort()->setOffsetY(value); |
| | } |
| | |
| | |
| | redraw(); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | void QG_GraphicView::setOffset([[maybe_unused]]int ox, [[maybe_unused]]int oy) { |
| | getViewPort()->setOffsetX(ox); |
| | getViewPort()->setOffsetY(oy); |
| | |
| | adjustOffsetControls(); |
| | } |
| |
|
| | void QG_GraphicView::layerActivated(RS_Layer *layer) { |
| | bool toActivated = LC_GET_ONE_BOOL("Modify", "ModifyEntitiesToActiveLayer"); |
| |
|
| | if (toActivated) { |
| | RS_EntityContainer *container = getContainer(); |
| | RS_Graphic *graphic = getGraphic(); |
| | if (graphic != nullptr) { |
| | QList<RS_Entity *> clones; |
| |
|
| | graphic->startUndoCycle(); |
| |
|
| | for (auto en: std::as_const(*container)) { |
| | if (en != nullptr) { |
| | if (en->isSelected()) { |
| | RS_Entity *cl = en->clone(); |
| | cl->setLayer(layer); |
| | en->setSelected(false); |
| | cl->setSelected(false); |
| | clones << cl; |
| |
|
| | en->setUndoState(true); |
| | graphic->addUndoable(en); |
| | } |
| | } |
| | } |
| |
|
| | for (auto cl: std::as_const(clones)) { |
| | container->addEntity(cl); |
| | graphic->addUndoable(cl); |
| | } |
| |
|
| | graphic->endUndoCycle(); |
| | graphic->updateInserts(); |
| |
|
| | container->calculateBorders(); |
| | container->setSelected(false); |
| | redraw(RS2::RedrawDrawing); |
| | } |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | void QG_GraphicView::paintEvent(QPaintEvent *){ |
| | getRenderer()->render(); |
| | } |
| |
|
| |
|
| | #define HIDE_SELECT_CURSOR false |
| |
|
| | void QG_GraphicView::loadSettings() { |
| | RS_GraphicView::loadSettings(); |
| |
|
| | { |
| | LC_GROUP_GUARD("Appearance"); |
| | int zoomFactor1000 = LC_GET_INT("ScrollZoomFactor", 1137); |
| | m_scrollZoomFactor = zoomFactor1000 / 1000.0; |
| |
|
| | m_ucsHighlightData->m_maxBlinkNumber = LC_GET_INT("UCSHighlightBlinkCount",10)*2; |
| | m_ucsHighlightData->m_timerInterval = LC_GET_INT("UCSHighlightBlinkDelay",250); |
| | } |
| |
|
| | { |
| | LC_GROUP_GUARD("Defaults"); |
| | m_invertZoomDirection = LC_GET_ONE_BOOL("Defaults", "InvertZoomDirection"); |
| | m_invertHorizontalScroll = LC_GET_BOOL("WheelScrollInvertH"); |
| | m_invertVerticalScroll = LC_GET_BOOL("WheelScrollInvertV"); |
| | } |
| |
|
| | m_allowScrollAndMoveAdjustByKeys = LC_GET_ONE_BOOL("Keyboard", "AllowScrollMoveAdjustByKeys", true); |
| |
|
| | LC_GROUP("Appearance"); |
| | { |
| | m_cursor_hiding = LC_GET_BOOL("cursor_hiding", false); |
| | bool showSnapIndicatorLines = LC_GET_BOOL("indicator_lines_state", true); |
| | bool showSnapIndicatorShape = LC_GET_BOOL("indicator_shape_state", true); |
| | if (HIDE_SELECT_CURSOR) { |
| | |
| | |
| | |
| | m_selectCursor_hiding = m_cursor_hiding && (showSnapIndicatorLines || showSnapIndicatorShape); |
| | } |
| | else { |
| | m_selectCursor_hiding = false; |
| | } |
| | } |
| | LC_GROUP_END(); |
| | m_ucsMarkOptions->loadSettings(); |
| | } |
| |
|
| | void QG_GraphicView::setAntialiasing(bool state){ |
| | getRenderer()->setAntialiasing(state); |
| | } |
| |
|
| | bool QG_GraphicView::isDraftMode() const { |
| | auto* viewRenderer = dynamic_cast<LC_GraphicViewRenderer*>(getRenderer()); |
| | return (viewRenderer != nullptr) ? viewRenderer->isDraftMode() : false; |
| | } |
| |
|
| | void QG_GraphicView::setDraftMode(bool dm) { |
| | auto* viewRenderer = dynamic_cast<LC_GraphicViewRenderer*>(getRenderer()); |
| | if (viewRenderer != nullptr) { |
| | viewRenderer->setDraftMode(dm); |
| | redraw(); |
| | } |
| | } |
| |
|
| | void QG_GraphicView::setDraftLinesMode(bool mode) { |
| | auto* viewRenderer = dynamic_cast<LC_GraphicViewRenderer*>(getRenderer()); |
| | if (viewRenderer != nullptr) { |
| | viewRenderer->setLineWidthScaling(!mode); |
| | } |
| | } |
| |
|
| | void QG_GraphicView::addScrollbars(){ |
| | m_scrollbars = true; |
| |
|
| | m_hScrollBar = new QG_ScrollBar(Qt::Horizontal, this); |
| | m_vScrollBar = new QG_ScrollBar(Qt::Vertical, this); |
| | m_layout = new QGridLayout(this); |
| |
|
| | setOffset(50, 50); |
| |
|
| | #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) |
| | m_layout->setContentsMargins(QMargins{}); |
| | #else |
| | layout->setMargin(0); |
| | #endif |
| | m_layout->setSpacing(0); |
| | m_layout->setColumnStretch(0, 1); |
| | m_layout->setColumnStretch(1, 0); |
| | m_layout->setColumnStretch(2, 0); |
| | m_layout->setRowStretch(0, 1); |
| | m_layout->setRowStretch(1, 0); |
| |
|
| | m_hScrollBar->setSingleStep(50); |
| | m_hScrollBar->setCursor(Qt::ArrowCursor); |
| | m_layout->addWidget(m_hScrollBar, 1, 0); |
| | connect(m_hScrollBar, &QG_ScrollBar::valueChanged, this, &QG_GraphicView::slotHScrolled); |
| |
|
| | m_vScrollBar->setSingleStep(50); |
| | m_vScrollBar->setCursor(Qt::ArrowCursor); |
| | m_layout->addWidget(m_vScrollBar, 0, 1); |
| | connect(m_vScrollBar, &QG_ScrollBar::valueChanged, this, &QG_GraphicView::slotVScrolled); |
| | } |
| |
|
| | bool QG_GraphicView::hasScrollbars(){ |
| | return m_scrollbars; |
| | } |
| |
|
| | void QG_GraphicView::setCursorHiding(bool state){ |
| | m_cursor_hiding = state; |
| | } |
| |
|
| | void QG_GraphicView::setCurrentQAction(QAction* q_action){ |
| | getEventHandler()->setQAction(q_action); |
| |
|
| | if (m_recent_actions.contains(q_action)){ |
| | m_recent_actions.removeOne(q_action); |
| | } |
| | m_recent_actions.prepend(q_action); |
| | } |
| |
|
| |
|
| | void QG_GraphicView::startAutoPanTimer(QMouseEvent *event){ |
| | if (event == nullptr) { |
| | return; |
| | } |
| | const RS_Vector cadArea_minCoord(0., 0.); |
| | const RS_Vector cadArea_maxCoord(getWidth(), getHeight()); |
| | const LC_Rect cadArea_actual(cadArea_minCoord, cadArea_maxCoord); |
| | const LC_Rect cadArea_unprobed(cadArea_minCoord + m_panData->probedAreaOffset, |
| | cadArea_maxCoord - m_panData->probedAreaOffset); |
| |
|
| | RS_Vector mouseCoord{event->position()}; |
| | mouseCoord.y = cadArea_actual.height() - mouseCoord.y; |
| |
|
| | const RS_Vector cadArea_centerPoint((cadArea_minCoord + cadArea_maxCoord) / 2.0); |
| | RS_Vector offset = mouseCoord - cadArea_centerPoint; |
| | offset = {std::abs(offset.x) - cadArea_unprobed.width() / 2., |
| | std::abs(offset.y) - cadArea_unprobed.height() / 2.}; |
| | offset = {std::max(offset.x, 1.), std::max(offset.y, 1.)}; |
| |
|
| | double panOffset_angle{cadArea_centerPoint.angleTo(mouseCoord)}; |
| |
|
| | |
| | const double quarterAngle = cadArea_centerPoint.angleTo(cadArea_actual.upperRightCorner()); |
| |
|
| | double percentageFactor = 1.; |
| |
|
| | if (((panOffset_angle > quarterAngle) && (panOffset_angle <= (M_PI - quarterAngle))) |
| | || ((panOffset_angle > (quarterAngle + M_PI)) |
| | && (panOffset_angle <= (M_PI + M_PI - quarterAngle)))) { |
| | percentageFactor = (std::abs((mouseCoord - cadArea_centerPoint).y) |
| | - (cadArea_unprobed.height() / 2.0)) |
| | / ((cadArea_actual.height() / 2.0) - (cadArea_unprobed.height() / 2.0)); |
| | } else { |
| | percentageFactor = (std::abs((mouseCoord - cadArea_centerPoint).x) |
| | - (cadArea_unprobed.width() / 2.0)) |
| | / ((cadArea_actual.width() / 2.0) - (cadArea_unprobed.width() / 2.0)); |
| | } |
| |
|
| | const double panTimerInterval{ |
| | m_panData->panTimerInterval_minimum |
| | + ((m_panData->panTimerInterval_maximum - m_panData->panTimerInterval_minimum) |
| | * (1.0 - percentageFactor))}; |
| |
|
| | offset = RS_Vector::polar(offset.magnitude(), M_PI - panOffset_angle); |
| | m_panData->panOffset = {static_cast<int>(offset.x), static_cast<int>(offset.y)}; |
| |
|
| | if (m_panData->panTimer != nullptr) { |
| | m_panData->panTimer->setInterval(panTimerInterval); |
| | } else { |
| | m_panData->start(panTimerInterval, *this); |
| | } |
| |
|
| | if (RS_DEBUG->getLevel() >= RS_Debug::D_INFORMATIONAL) { |
| | std::cout << " CAD area centre point = " << cadArea_centerPoint << std::endl |
| | << " Actual CAD area quarter angle (deg) = " << quarterAngle * 180.0 / M_PI |
| | << std::endl |
| | << " Percentage factor = " << percentageFactor << std::endl |
| | << " Pan offset angle (radians) = " << panOffset_angle << std::endl |
| | << " Pan offset angle (degrees) = " << panOffset_angle * 180.0 / M_PI |
| | << std::endl |
| | << " Pan offset vector = " << m_panData->panOffset.x() << ", " |
| | << m_panData->panOffset.y() |
| | << std::endl |
| | |
| | << std::endl |
| | << " Mouse (cursor) position (adjusted) = " << mouseCoord << std::endl |
| | << " Mouse position w.r.t. centre point = " << mouseCoord - cadArea_centerPoint |
| | << std::endl |
| | << std::endl |
| | << std::endl; |
| | } |
| | } |
| |
|
| | bool QG_GraphicView::isAutoPan(QMouseEvent *event) const{ |
| | if (event == nullptr) { |
| | return false; |
| | } |
| |
|
| | const bool autopanEnabled = LC_GET_ONE_BOOL("Appearance", "Autopanning"); |
| |
|
| | if (!autopanEnabled) { |
| | return false; |
| | } |
| |
|
| | const RS_Vector cadArea_minCoord(0., 0.); |
| | const RS_Vector cadArea_maxCoord(getWidth(), getHeight()); |
| | const LC_Rect cadArea_actual(cadArea_minCoord, cadArea_maxCoord); |
| | const LC_Rect cadArea_unprobed(cadArea_minCoord + m_panData->probedAreaOffset, |
| | cadArea_maxCoord - m_panData->probedAreaOffset); |
| | if (cadArea_unprobed.width() < 0. || cadArea_unprobed.height() < 0.) { |
| | return false; |
| | } |
| |
|
| | RS_Vector mouseCoord{event->position()}; |
| |
|
| | if (RS_DEBUG->getLevel() >= RS_Debug::D_INFORMATIONAL) { |
| | std::cout << " Unprobed CAD area width and height = " << cadArea_unprobed.width() << "/" |
| | << cadArea_unprobed.height() << std::endl |
| | << " Actual CAD area width and height = " << cadArea_actual.width() << "/" |
| | << cadArea_actual.height() << std::endl |
| | << " Mouse (cursor) position = " << mouseCoord << std::endl |
| | << std::endl; |
| | } |
| |
|
| | return cadArea_actual.inArea(mouseCoord) && !cadArea_unprobed.inArea(mouseCoord); |
| | } |
| |
|
| | void QG_GraphicView::deleteActionContext() { |
| | delete m_actionContext; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | void QG_GraphicView::autoPanStep(){ |
| | |
| | m_panData->m_delayCounter = std::min(++ m_panData->m_delayCounter, m_panData->delayCounterMax); |
| | if (m_panData->m_delayCounter < m_panData->delayCounterMax) { |
| | return; |
| | } |
| |
|
| | RS_DEBUG->print(RS_Debug::D_INFORMATIONAL, "%s(): Timer is ticking!", __func__); |
| | getViewPort()->zoomPan(m_panData->panOffset.x(), m_panData->panOffset.y()); |
| | } |
| |
|
| |
|
| | QString QG_GraphicView::obtainEntityDescription(RS_Entity *entity, RS2::EntityDescriptionLevel shortDescription) { |
| | LC_QuickInfoWidget *entityInfoWidget = QC_ApplicationWindow::getAppWindow()->getEntityInfoWidget(); |
| | if (entityInfoWidget != nullptr){ |
| | QString result = entityInfoWidget->getEntityDescription(entity, shortDescription); |
| | return result; |
| | } |
| | return ""; |
| | } |
| |
|
| | void QG_GraphicView::ucsHighlightStep(){ |
| | auto overlayContainer = getViewPort()->getOverlaysDrawablesContainer(RS2::OverlayGraphics::ActionPreviewEntity); |
| | overlayContainer->clear(); |
| | if (m_ucsHighlightData->mayTick()){ |
| | if (m_ucsHighlightData->m_inVisiblePhase) { |
| | |
| | |
| | auto m_ucsMark = new LC_OverlayUCSMark(m_ucsHighlightData->origin, m_ucsHighlightData->angle, |
| | m_ucsHighlightData->forWCS, m_ucsMarkOptions.get()); |
| | overlayContainer->add(m_ucsMark); |
| | } |
| | else{ |
| | } |
| | } |
| | else{ |
| | m_ucsHighlightData->stop(); |
| | |
| | getViewPort()->justSetOffsetAndFactor(m_ucsHighlightData->m_savedViewOffset.x, |
| | m_ucsHighlightData->m_savedViewOffset.y, |
| | m_ucsHighlightData->m_savedViewFactor); |
| | } |
| | redraw(RS2::RedrawOverlay); |
| | update(); |
| | } |
| |
|
| | void QG_GraphicView::highlightUCSLocation(LC_UCS *ucs){ |
| | if (ucs == nullptr){ |
| | return; |
| | } |
| |
|
| | auto viewport = getViewPort(); |
| | |
| | m_ucsHighlightData->m_savedViewOffset.x = viewport->getOffsetX(); |
| | m_ucsHighlightData->m_savedViewOffset.y = viewport->getOffsetY(); |
| | m_ucsHighlightData->m_savedViewFactor = viewport->getFactor().x; |
| |
|
| | RS_Vector origin = ucs->getOrigin(); |
| | double angle = ucs->getXAxisDirection(); |
| |
|
| | |
| | double AXIS_SIZE = viewport->toUcsDX(20); |
| | viewport->zoomAutoEnsurePointsIncluded(origin, origin.relative(AXIS_SIZE, angle), origin.relative(AXIS_SIZE, angle+M_PI_2)); |
| |
|
| | double uiOriginPointX=0., uiOriginPointY=0.; |
| | viewport->toUI(origin, uiOriginPointX, uiOriginPointY); |
| |
|
| | double ucsXAxisAngleInUCS = viewport->toUCSAngle(angle); |
| |
|
| | m_ucsHighlightData->origin = RS_Vector(uiOriginPointX, uiOriginPointY); |
| | m_ucsHighlightData->angle = -ucsXAxisAngleInUCS; |
| | m_ucsHighlightData->forWCS = ! ucs->isUCS(); |
| | double timerInterval = m_ucsHighlightData->m_timerInterval; |
| | m_ucsHighlightData->start(timerInterval, *this); |
| | } |
| |
|