| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include "rs_actioninterface.h" |
| |
|
| | #include <QMouseEvent> |
| |
|
| | #include "lc_actioncontext.h" |
| | #include "lc_actionoptionswidget.h" |
| | #include "lc_cursoroverlayinfo.h" |
| | #include "lc_graphicviewport.h" |
| | #include "rs_commandevent.h" |
| | #include "rs_commands.h" |
| | #include "rs_coordinateevent.h" |
| | #include "rs_debug.h" |
| | #include "rs_entitycontainer.h" |
| | #include "rs_graphic.h" |
| | #include "rs_graphicview.h" |
| | #include "rs_settings.h" |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_ActionInterface::RS_ActionInterface(const char *name, |
| | LC_ActionContext *actionContext, |
| | RS2::ActionType actionType) |
| | :RS_Snapper(actionContext) |
| | , m_status{0} |
| | , m_name{name} |
| | , m_finished{false} |
| | , m_graphic{m_container->getGraphic()} |
| | , m_document{m_container->getDocument()} |
| | , m_actionType{actionType}{ |
| |
|
| | RS_DEBUG->print("RS_ActionInterface::RS_ActionInterface: Setting up action: \"%s\"", name); |
| |
|
| | |
| |
|
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| |
|
| | updateSnapAngleStep(); |
| |
|
| | RS_DEBUG->print("RS_ActionInterface::RS_ActionInterface: Setting up action: \"%s\": OK", name); |
| | } |
| |
|
| | RS_ActionInterface::~RS_ActionInterface(){ |
| | if (m_optionWidget != nullptr){ |
| | m_optionWidget->deleteLater(); |
| | m_optionWidget.release(); |
| | m_optionWidget.reset(); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | RS2::ActionType RS_ActionInterface::rtti() const{ |
| | return m_actionType; |
| | } |
| |
|
| | |
| | |
| | |
| | QString RS_ActionInterface::getName() { |
| | return m_name; |
| | } |
| |
|
| | void RS_ActionInterface::setName(const char* _name) { |
| | m_name=_name; |
| | } |
| |
|
| | bool RS_ActionInterface::mayInitWithContextEntity(int status) { |
| | return status == InitialActionStatus; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::init(int status){ |
| | setStatus(status); |
| | if (status >= InitialActionStatus) { |
| | RS_Snapper::init(); |
| | updateMouseButtonHints(); |
| | updateMouseCursor(); |
| | if (mayInitWithContextEntity(status)) { |
| | doInitialInit(); |
| | auto contextEntity = m_actionContext->getContextMenuActionContextEntity(); |
| | if (contextEntity != nullptr) { |
| | |
| | doInitWithContextEntity(contextEntity, m_actionContext->getContextMenuActionClickPosition()); |
| | m_actionContext->clearContextMenuActionContext(); |
| | } |
| | } |
| | } else{ |
| | |
| | deleteSnapper(); |
| | } |
| | } |
| |
|
| | void RS_ActionInterface::doInitWithContextEntity([[maybe_unused]]RS_Entity* contextEntity, [[maybe_unused]]const RS_Vector& clickPos) { |
| | } |
| |
|
| | void RS_ActionInterface::doInitialInit() { |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::mouseMoveEvent(QMouseEvent*) {} |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::mousePressEvent(QMouseEvent* e) { |
| | Qt::MouseButton button = e->button(); |
| | if (button == Qt::LeftButton){ |
| | onMouseLeftButtonPress(m_status, e); |
| | } else if (button == Qt::RightButton){ |
| | onMouseRightButtonPress(m_status, e); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::mouseReleaseEvent(QMouseEvent* e){ |
| | Qt::MouseButton button; |
| | button = e->button(); |
| | if (button == Qt::LeftButton){ |
| | onMouseLeftButtonRelease(m_status, e); |
| | } else if (button == Qt::RightButton){ |
| | onMouseRightButtonRelease(m_status, e); |
| | } |
| | } |
| |
|
| | void RS_ActionInterface::onMouseLeftButtonRelease([[maybe_unused]]int status, [[maybe_unused]]QMouseEvent* e){} |
| | void RS_ActionInterface::onMouseRightButtonRelease([[maybe_unused]]int status, [[maybe_unused]]QMouseEvent* e){} |
| | void RS_ActionInterface::onMouseLeftButtonPress([[maybe_unused]]int status, [[maybe_unused]]QMouseEvent* e){} |
| | void RS_ActionInterface::onMouseRightButtonPress([[maybe_unused]]int status, [[maybe_unused]]QMouseEvent* e){} |
| |
|
| | |
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::keyPressEvent(QKeyEvent* e) { |
| | e->ignore(); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::keyReleaseEvent(QKeyEvent* e) { |
| | e->ignore(); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::coordinateEvent(RS_CoordinateEvent* e) { |
| | if (e == nullptr){ |
| | return; |
| | } |
| |
|
| | |
| | RS_Vector wcsPos = e->getCoordinate(); |
| | if (!wcsPos.valid){ |
| | return; |
| | } |
| | |
| | |
| | bool isZero = e->isZero(); |
| |
|
| | |
| | onCoordinateEvent(m_status, isZero, wcsPos); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::onCoordinateEvent([[maybe_unused]]int status, [[maybe_unused]]bool isZero, [[maybe_unused]]const RS_Vector &pos) {} |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::commandEvent(RS_CommandEvent* e) { |
| | QString c = prepareCommand(e); |
| | if (!c.isEmpty()) { |
| | if (checkCommand("help", c)) { |
| | const QStringList &list = getAvailableCommands(); |
| | if (!list.isEmpty()) { |
| | commandMessage(msgAvailableCommands() + list.join(", ") + getAdditionalHelpMessage()); |
| | } else { |
| | |
| | } |
| | e->accept(); |
| | } else { |
| | bool accept = doProcessCommand(getStatus(), c); |
| | if (accept) { |
| | e->accept(); |
| | } |
| | } |
| | } |
| | } |
| |
|
| | QString RS_ActionInterface::prepareCommand(RS_CommandEvent *e) const { |
| | QString const &c = e->getCommand().toLower().trimmed(); |
| | return c; |
| | } |
| |
|
| | QString RS_ActionInterface::getAdditionalHelpMessage() {return {};} |
| |
|
| | bool RS_ActionInterface::doProcessCommand([[maybe_unused]]int status, [[maybe_unused]]const QString &command) {return false;} |
| |
|
| | |
| | |
| | |
| | |
| | QStringList RS_ActionInterface::getAvailableCommands() { |
| | return {}; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::setStatus(int status) { |
| | m_status = status; |
| | updateMouseButtonHints(); |
| | updateMouseCursor(); |
| | if(status<0) { |
| | finish(); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | int RS_ActionInterface::getStatus() const { |
| | return m_status; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::trigger() {} |
| |
|
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::updateMouseButtonHints() {} |
| |
|
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::updateMouseCursor(){ |
| | int status = getStatus(); |
| | RS2::CursorType cursor = doGetMouseCursor(status); |
| | if (cursor != RS2::NoCursorChange){ |
| | setMouseCursor(cursor); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | RS2::CursorType RS_ActionInterface::doGetMouseCursor([[maybe_unused]]int status){ |
| | return RS2::NoCursorChange; |
| | } |
| |
|
| | |
| | |
| | |
| | bool RS_ActionInterface::isFinished() const { |
| | return m_finished; |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | void RS_ActionInterface::setFinished() { |
| | m_status = -1; |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | void RS_ActionInterface::finish(bool ){ |
| | RS_DEBUG->print("RS_ActionInterface::finish"); |
| | |
| | if(rtti() != RS2::ActionDefault) { |
| | m_status = -1; |
| | m_finished = true; |
| | hideOptions(); |
| | RS_Snapper::finish(); |
| | } |
| | RS_DEBUG->print("RS_ActionInterface::finish: OK"); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::setPredecessor(std::shared_ptr<RS_ActionInterface> pre) { |
| | m_predecessor = pre; |
| | } |
| |
|
| | std::shared_ptr<RS_ActionInterface> RS_ActionInterface::getPredecessor() const { |
| | return m_predecessor; |
| | } |
| |
|
| | |
| | |
| | |
| | void RS_ActionInterface::suspend() { |
| | RS_Snapper::suspend(); |
| | } |
| |
|
| | |
| | |
| | |
| | void RS_ActionInterface::resume() { |
| | updateMouseCursor(); |
| | updateMouseButtonHints(); |
| | updateSnapAngleStep(); |
| | RS_Snapper::resume(); |
| | } |
| |
|
| | |
| | |
| | |
| | void RS_ActionInterface::hideOptions() { |
| | if (m_optionWidget != nullptr){ |
| | m_optionWidget->hideOptions(); |
| | } |
| | } |
| |
|
| | void RS_ActionInterface::updateOptions(const QString &tagToFocus){ |
| | if (m_optionWidget == nullptr){ |
| | LC_ActionOptionsWidget* widget = createOptionsWidget(); |
| | if (widget != nullptr){ |
| | m_optionWidget.reset(widget); |
| | } |
| | } |
| | if (m_optionWidget != nullptr){ |
| | if (!m_optionWidget->isVisible()){ |
| | if (m_optionWidget->parent() == nullptr){ |
| | m_actionContext->addOptionsWidget(m_optionWidget.get()); |
| | m_optionWidget->setAction(this, true); |
| | } else { |
| | m_optionWidget->setAction(this, true); |
| | m_optionWidget->show(); |
| | } |
| | } |
| | else{ |
| | m_optionWidget->setAction(this, true); |
| | } |
| | if (!tagToFocus.isEmpty()) { |
| | m_optionWidget->requestFocusForTag(tagToFocus); |
| | } |
| | } |
| | } |
| |
|
| | void RS_ActionInterface::updateOptionsUI(int mode){ |
| | if (m_optionWidget != nullptr){ |
| | m_optionWidget->updateUI(mode); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | void RS_ActionInterface::showOptions() { |
| | if (m_optionWidget == nullptr){ |
| | m_optionWidget.reset(createOptionsWidget()); |
| | } |
| | if (m_optionWidget != nullptr){ |
| | if (!m_optionWidget->isVisible()){ |
| | if (m_optionWidget->parent() == nullptr){ |
| | m_actionContext->addOptionsWidget(m_optionWidget.get()); |
| | m_optionWidget->setAction(this); |
| | } else { |
| | m_optionWidget->show(); |
| | } |
| | } |
| | } |
| | } |
| |
|
| | void RS_ActionInterface::onLateRequestCompleted(bool shouldBeSkipped) { |
| | if (!shouldBeSkipped) { |
| | auto inputInfo = m_actionContext->getInteractiveInputInfo(); |
| | bool updated = false; |
| | auto requestorTag = inputInfo->m_requestorTag; |
| | switch (inputInfo->m_inputType) { |
| | case LC_ActionContext::InteractiveInputInfo::ANGLE: { |
| | updated = doUpdateAngleByInteractiveInput(requestorTag, inputInfo->m_angleRad); |
| | break; |
| | } |
| | case LC_ActionContext::InteractiveInputInfo::DISTANCE: { |
| | updated = doUpdateDistanceByInteractiveInput(requestorTag, inputInfo->m_distance); |
| | break; |
| | } |
| | case LC_ActionContext::InteractiveInputInfo::POINT: { |
| | updated = doUpdatePointByInteractiveInput(requestorTag, inputInfo->m_wcsPoint); |
| | break; |
| | } |
| | default: |
| | break; |
| | } |
| | if (updated) { |
| | updateOptions(requestorTag); |
| | } |
| | } |
| | m_actionContext->interactiveInputRequestCancel(); |
| | } |
| |
|
| | LC_ActionOptionsWidget* RS_ActionInterface::createOptionsWidget(){ |
| | return nullptr; |
| | } |
| |
|
| | void RS_ActionInterface::setActionType(RS2::ActionType actionType){ |
| | this->m_actionType=actionType; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | bool RS_ActionInterface::checkCommand(const QString& cmd, const QString& str, |
| | RS2::ActionType action) { |
| | return (getAvailableCommands().contains(str) && cmd == str) |
| | || RS_COMMANDS->checkCommand(cmd, str, action); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | QString RS_ActionInterface::command(const QString& cmd) { |
| | return RS_COMMANDS->command(cmd); |
| | } |
| |
|
| | void RS_ActionInterface::switchToAction(RS2::ActionType actionType, void* data) { |
| | m_actionContext->setCurrentAction(actionType, data); |
| | } |
| |
|
| | |
| | |
| | |
| | QString RS_ActionInterface::msgAvailableCommands() { |
| | return RS_COMMANDS->msgAvailableCommands(); |
| | } |
| |
|
| | int RS_ActionInterface::getGraphicVariableInt(const QString& key, int def) const{ |
| | return (m_graphic != nullptr) ? m_graphic->getGraphicVariableInt(key, def) : def; |
| | } |
| |
|
| | void RS_ActionInterface::updateSelectionWidget() const{ |
| | const RS_EntityContainer::LC_SelectionInfo &info = m_container->getSelectionInfo(); |
| | updateSelectionWidget(info.count, info.length); |
| | } |
| |
|
| | void RS_ActionInterface::updateSelectionWidget(int countSelected, double selectedLength) const{ |
| | m_actionContext->updateSelectionWidget(countSelected,selectedLength); |
| | } |
| |
|
| | void RS_ActionInterface::setMouseCursor(const RS2::CursorType &cursor){ |
| | if (m_graphicView != nullptr) { |
| | m_graphicView->setMouseCursor(cursor); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::updateMouseWidgetTRBack(const QString &msg, const LC_ModifiersInfo& modifiers){ |
| | if (m_infoCursorOverlayPrefs->enabled) { |
| | preparePromptForInfoCursorOverlay(msg, modifiers); |
| | } |
| | m_actionContext->updateMouseWidget(msg,tr("Back"), modifiers); |
| | } |
| |
|
| | void RS_ActionInterface::preparePromptForInfoCursorOverlay(const QString &msg, const LC_ModifiersInfo &modifiers) { |
| | QString prompt = ""; |
| | LC_InfoCursorOverlayPrefs* prefs = getInfoCursorOverlayPrefs(); |
| | if (prefs->showCommandPrompt){ |
| | if (prefs->showCurrentActionName) { |
| | QString actionName = m_graphicView->getCurrentActionName(); |
| | if (!actionName.isEmpty()){ |
| | prompt = actionName + ": " + msg; |
| | } |
| | else { |
| | prompt = msg; |
| | } |
| | } |
| | else{ |
| | prompt = msg; |
| | } |
| | QString modifiersStr = ""; |
| | const QString &shiftMessage = modifiers.getShiftMessage(); |
| | if (!shiftMessage.isEmpty()){ |
| | modifiersStr = modifiersStr + tr("SHIFT:") + shiftMessage; |
| | } |
| | const QString &ctrlMessage = modifiers.getCtrlMessage(); |
| | if (!ctrlMessage.isEmpty()){ |
| | if (!modifiersStr.isEmpty()){ |
| | modifiersStr = modifiersStr + " | "; |
| | } |
| | modifiersStr = modifiersStr + tr("CTRL:") + ctrlMessage; |
| | } |
| |
|
| | if (!modifiersStr.isEmpty()){ |
| | prompt = prompt + "\n" + modifiersStr; |
| | } |
| | } |
| | m_infoCursorOverlayData->setZone4(prompt); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::updateMouseWidgetTRCancel(const QString &msg, const LC_ModifiersInfo& modifiers){ |
| | if (m_infoCursorOverlayPrefs->enabled) { |
| | preparePromptForInfoCursorOverlay(msg, modifiers); |
| | } |
| | m_actionContext->updateMouseWidget(msg,tr("Cancel"), modifiers); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::updateMouseWidget(const QString& left,const QString& right, const LC_ModifiersInfo& modifiers){ |
| | if (m_infoCursorOverlayPrefs->enabled) { |
| | preparePromptForInfoCursorOverlay(left, modifiers); |
| | } |
| | m_actionContext->updateMouseWidget(left, right, modifiers); |
| | } |
| |
|
| | void RS_ActionInterface::clearMouseWidgetIcon(){ |
| | m_infoCursorOverlayData->setZone4(""); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::commandMessage(const QString &msg) const{ |
| | m_actionContext->commandMessage(msg); |
| | } |
| |
|
| | void RS_ActionInterface::commandPrompt(const QString &msg) const{ |
| | m_actionContext->commandPrompt(msg); |
| | } |
| |
|
| | void RS_ActionInterface::updateSnapAngleStep() { |
| | int stepType = LC_GET_ONE_INT("Defaults", "AngleSnapStep", 3); |
| | double snapStepDegrees; |
| | switch (stepType){ |
| | case 0: |
| | snapStepDegrees = 1.0; |
| | break; |
| | case 1: |
| | snapStepDegrees = 3.0; |
| | break; |
| | case 2: |
| | snapStepDegrees = 5.0; |
| | break; |
| | case 3: |
| | snapStepDegrees = 10.0; |
| | break; |
| | case 4: |
| | snapStepDegrees = 15.0; |
| | break; |
| | case 5: |
| | snapStepDegrees = 18.0; |
| | break; |
| | case 6: |
| | snapStepDegrees = 22.5; |
| | break; |
| | case 7: |
| | snapStepDegrees = 30.0; |
| | break; |
| | case 8: |
| | snapStepDegrees = 45.0; |
| | break; |
| | case 9: |
| | snapStepDegrees = 90.0; |
| | break; |
| | default: |
| | snapStepDegrees = 15.0; |
| | } |
| | m_snapToAngleStep = RS_Math::deg2rad(snapStepDegrees); |
| | } |
| |
|
| | bool RS_ActionInterface::isControl(const QInputEvent *e){ |
| | return e->modifiers() & (Qt::ControlModifier | Qt::MetaModifier); |
| | } |
| |
|
| | bool RS_ActionInterface::isShift(const QInputEvent *e){ |
| | return e->modifiers() & Qt::ShiftModifier; |
| | } |
| |
|
| | bool RS_ActionInterface::isAlt(const QInputEvent *e){ |
| | return e->modifiers() & Qt::AltModifier; |
| | } |
| |
|
| |
|
| | void RS_ActionInterface::fireCoordinateEvent(const RS_Vector &coord){ |
| | auto ce = RS_CoordinateEvent(coord); |
| | coordinateEvent(&ce); |
| | } |
| |
|
| | void RS_ActionInterface::initPrevious(int stat) { |
| | init(stat - 1); |
| | } |
| |
|
| | bool RS_ActionInterface::undoCycleAdd(RS_Entity *e, bool addToContainer) const{ |
| | |
| | if (addToContainer){ |
| | m_container->addEntity(e); |
| | } |
| | if (m_document){ |
| | undoCycleStart(); |
| | undoableAdd(e); |
| | undoCycleEnd(); |
| | return true; |
| | } |
| | return false; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | void RS_ActionInterface::undoableDeleteEntity(RS_Entity *entity){ |
| | entity->changeUndoState(); |
| | undoableAdd(entity); |
| | } |
| |
|
| | void RS_ActionInterface::undoCycleReplace(RS_Entity *entityToReplace, RS_Entity *entityReplacing) { |
| | if (m_document != nullptr) { |
| | undoCycleStart(); |
| | undoableDeleteEntity(entityToReplace); |
| | undoableAdd(entityReplacing); |
| | undoCycleEnd(); |
| | } |
| | } |
| |
|
| | void RS_ActionInterface::undoCycleEnd() const { |
| | RS_Undoable* relZeroUndoable = m_viewport->getRelativeZeroUndoable(); |
| | if (relZeroUndoable != nullptr) { |
| | m_document->addUndoable(relZeroUndoable); |
| | } |
| | m_document->endUndoCycle(); |
| | } |
| |
|
| | void RS_ActionInterface::undoCycleStart() const { m_document->startUndoCycle(); } |
| | void RS_ActionInterface::undoableAdd(RS_Undoable *e) const { m_document->addUndoable(e); } |
| |
|
| | void RS_ActionInterface::setPenAndLayerToActive(RS_Entity *e) { |
| | e->setLayerToActive(); |
| | e->setPenToActive(); |
| | } |
| |
|