From 1071fb1cddcd52c2f3fca3a6917d3e3688c94a36 Mon Sep 17 00:00:00 2001 From: Paddle Date: Thu, 6 Apr 2023 22:35:49 +0200 Subject: [PATCH 01/18] Image: Merge taskboxes into one 'Image plane Settings' - Allow user to position the image with a X / Y distance. - Allow user to rotate the image on its plane. - Adds Transparency. - Image sizes change from PX to System unit as PX don't make sense for the user. --- src/Gui/CMakeLists.txt | 10 +- .../{TaskImageScale.cpp => TaskImage.cpp} | 291 +++++++++++++-- .../{TaskImageScale.h => TaskImage.h} | 55 ++- src/Gui/TaskView/TaskImage.ui | 346 ++++++++++++++++++ src/Gui/TaskView/TaskImageScale.ui | 184 ---------- src/Gui/ViewProviderImagePlane.cpp | 10 +- 6 files changed, 654 insertions(+), 242 deletions(-) rename src/Gui/TaskView/{TaskImageScale.cpp => TaskImage.cpp} (54%) rename src/Gui/TaskView/{TaskImageScale.h => TaskImage.h} (75%) create mode 100644 src/Gui/TaskView/TaskImage.ui delete mode 100644 src/Gui/TaskView/TaskImageScale.ui diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 6255b96070..b795387fa8 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -342,8 +342,8 @@ SET(Gui_UIC_SRCS Placement.ui TextureMapping.ui TaskView/TaskAppearance.ui - TaskView/TaskImageScale.ui TaskView/TaskOrientation.ui + TaskView/TaskImage.ui TaskView/TaskSelectLinkProperty.ui TaskElementColors.ui DlgObjectSelection.ui @@ -720,12 +720,12 @@ SET(Task_View_SRCS TaskView/TaskAppearance.cpp TaskView/TaskAppearance.h TaskView/TaskAppearance.ui - TaskView/TaskImageScale.cpp - TaskView/TaskImageScale.h - TaskView/TaskImageScale.ui TaskView/TaskOrientation.cpp TaskView/TaskOrientation.h TaskView/TaskOrientation.ui + TaskView/TaskImage.cpp + TaskView/TaskImage.h + TaskView/TaskImage.ui TaskView/TaskSelectLinkProperty.cpp TaskView/TaskSelectLinkProperty.h TaskView/TaskSelectLinkProperty.ui @@ -1235,8 +1235,8 @@ if(MSVC) propertyeditor/PropertyItemDelegate.cpp propertyeditor/PropertyModel.cpp TaskView/TaskAppearance.cpp - TaskView/TaskImageScale.cpp TaskView/TaskOrientation.cpp + TaskView/TaskImage.cpp TaskView/TaskSelectLinkProperty.cpp TaskView/TaskEditControl.cpp TaskView/TaskView.cpp diff --git a/src/Gui/TaskView/TaskImageScale.cpp b/src/Gui/TaskView/TaskImage.cpp similarity index 54% rename from src/Gui/TaskView/TaskImageScale.cpp rename to src/Gui/TaskView/TaskImage.cpp index a09e3c7573..c9d955b0b1 100644 --- a/src/Gui/TaskView/TaskImageScale.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -48,38 +48,31 @@ #include #include -#include "TaskImageScale.h" -#include "ui_TaskImageScale.h" +#include "TaskImage.h" +#include "ui_TaskImage.h" using namespace Gui; -/* TRANSLATOR Gui::TaskImageScale */ +/* TRANSLATOR Gui::TaskImage */ -TaskImageScale::TaskImageScale(Image::ImagePlane* obj, QWidget* parent) +TaskImage::TaskImage(Image::ImagePlane* obj, QWidget* parent) : QWidget(parent) - , ui(new Ui_TaskImageScale) + , ui(new Ui_TaskImage) , feature(obj) - , aspectRatio{1.0} + , aspectRatio(1.0) { ui->setupUi(this); ui->pushButtonCancel->hide(); - ui->spinBoxWidth->setValue(obj->getXSizeInPixel()); - ui->spinBoxHeight->setValue(obj->getYSizeInPixel()); + + initialiseTransparency(); aspectRatio = obj->XSize.getValue() / obj->YSize.getValue(); - connect(ui->spinBoxWidth, qOverload(&QSpinBox::valueChanged), - this, &TaskImageScale::changeWidth); - connect(ui->spinBoxHeight, qOverload(&QSpinBox::valueChanged), - this, &TaskImageScale::changeHeight); - connect(ui->pushButtonScale, &QPushButton::clicked, - this, &TaskImageScale::onInteractiveScale); - connect(ui->pushButtonCancel, &QPushButton::clicked, - this, &TaskImageScale::rejectScale); + connectSignals(); } -TaskImageScale::~TaskImageScale() +TaskImage::~TaskImage() { if (scale) { if (scale->isActive()) { @@ -89,33 +82,93 @@ TaskImageScale::~TaskImageScale() } } -void TaskImageScale::changeWidth() +void TaskImage::connectSignals() +{ + connect(ui->Reverse_checkBox, &QCheckBox::clicked, + this, &TaskImage::onPreview); + connect(ui->XY_radioButton, &QRadioButton::clicked, + this, &TaskImage::onPreview); + connect(ui->XZ_radioButton, &QRadioButton::clicked, + this, &TaskImage::onPreview); + connect(ui->YZ_radioButton, &QRadioButton::clicked, + this, &TaskImage::onPreview); + connect(ui->spinBoxZ, qOverload(&QuantitySpinBox::valueChanged), + this, &TaskImage::onPreview); + connect(ui->spinBoxX, qOverload(&QuantitySpinBox::valueChanged), + this, &TaskImage::onPreview); + connect(ui->spinBoxY, qOverload(&QuantitySpinBox::valueChanged), + this, &TaskImage::onPreview); + connect(ui->spinBoxRotation, qOverload(&QuantitySpinBox::valueChanged), + this, &TaskImage::onPreview); + connect(ui->spinBoxTransparency, qOverload(&QSpinBox::valueChanged), + this, &TaskImage::changeTransparency); + connect(ui->sliderTransparency, qOverload(&QSlider::valueChanged), + this, &TaskImage::changeTransparency); + + connect(ui->spinBoxWidth, qOverload(&QuantitySpinBox::valueChanged), + this, &TaskImage::changeWidth); + connect(ui->spinBoxHeight, qOverload(&QuantitySpinBox::valueChanged), + this, &TaskImage::changeHeight); + connect(ui->pushButtonScale, &QPushButton::clicked, + this, &TaskImage::onInteractiveScale); + connect(ui->pushButtonCancel, &QPushButton::clicked, + this, &TaskImage::rejectScale); +} + +void TaskImage::initialiseTransparency() +{ + auto vp = Application::Instance->getViewProvider(feature.get()); + App::Property* prop = vp->getPropertyByName("Transparency"); + if (prop && prop->getTypeId().isDerivedFrom(App::PropertyInteger::getClassTypeId())) { + auto Transparency = static_cast(prop); + ui->spinBoxTransparency->setValue(Transparency->getValue()); + ui->sliderTransparency->setValue(Transparency->getValue()); + } +} + +void TaskImage::changeTransparency(int val) +{ + if (feature.expired()) + return; + + auto vp = Application::Instance->getViewProvider(feature.get()); + App::Property* prop = vp->getPropertyByName("Transparency"); + if (prop && prop->getTypeId().isDerivedFrom(App::PropertyInteger::getClassTypeId())) { + auto Transparency = static_cast(prop); + Transparency->setValue(val); + + QSignalBlocker block(ui->spinBoxTransparency); + QSignalBlocker blocks(ui->sliderTransparency); + ui->spinBoxTransparency->setValue(val); + ui->sliderTransparency->setValue(val); + } +} + +void TaskImage::changeWidth(double val) { if (!feature.expired()) { - int value = ui->spinBoxWidth->value(); - feature->setXSizeInPixel(value); + feature->XSize.setValue(val); if (ui->checkBoxRatio->isChecked()) { QSignalBlocker block(ui->spinBoxWidth); - ui->spinBoxHeight->setValue(int(double(value) / aspectRatio)); + ui->spinBoxHeight->setValue(val / aspectRatio); } } } -void TaskImageScale::changeHeight() +void TaskImage::changeHeight(double val) { if (!feature.expired()) { - int value = ui->spinBoxHeight->value(); - feature->setYSizeInPixel(value); + feature->YSize.setValue(val); if (ui->checkBoxRatio->isChecked()) { QSignalBlocker block(ui->spinBoxHeight); - ui->spinBoxWidth->setValue(int(double(value) * aspectRatio)); + ui->spinBoxWidth->setValue(val * aspectRatio); } } } -View3DInventorViewer* TaskImageScale::getViewer() const +View3DInventorViewer* TaskImage::getViewer() const { if (!feature.expired()) { auto vp = Application::Instance->getViewProvider(feature.get()); @@ -129,7 +182,7 @@ View3DInventorViewer* TaskImageScale::getViewer() const return nullptr; } -void TaskImageScale::selectedPoints(size_t num) +void TaskImage::selectedPoints(size_t num) { if (num == 1) { ui->labelInstruction->setText(tr("Select second point")); @@ -139,23 +192,24 @@ void TaskImageScale::selectedPoints(size_t num) ui->pushButtonScale->setEnabled(true); ui->quantitySpinBox->setEnabled(true); ui->quantitySpinBox->setValue(scale->getDistance()); + ui->quantitySpinBox->setFocus(); } } -void TaskImageScale::scaleImage(double factor) +void TaskImage::scaleImage(double factor) { if (!feature.expired()) { feature->XSize.setValue(feature->XSize.getValue() * factor); feature->YSize.setValue(feature->YSize.getValue() * factor); QSignalBlocker blockW(ui->spinBoxWidth); - ui->spinBoxWidth->setValue(feature->getXSizeInPixel()); + ui->spinBoxWidth->setValue(feature->XSize.getValue()); QSignalBlocker blockH(ui->spinBoxHeight); - ui->spinBoxHeight->setValue(feature->getYSizeInPixel()); + ui->spinBoxHeight->setValue(feature->YSize.getValue()); } } -void TaskImageScale::startScale() +void TaskImage::startScale() { scale->activate(ui->checkBoxOutside->isChecked()); if (ui->checkBoxOutside->isChecked()) { @@ -171,13 +225,13 @@ void TaskImageScale::startScale() ui->quantitySpinBox->setEnabled(false); } -void TaskImageScale::acceptScale() +void TaskImage::acceptScale() { scaleImage(ui->quantitySpinBox->value().getValue() / scale->getDistance()); rejectScale(); } -void TaskImageScale::rejectScale() +void TaskImage::rejectScale() { scale->deactivate(); ui->labelInstruction->clear(); @@ -190,7 +244,7 @@ void TaskImageScale::rejectScale() scale->clearPoints(); } -void TaskImageScale::onInteractiveScale() +void TaskImage::onInteractiveScale() { if (!feature.expired() && !scale) { View3DInventorViewer* viewer = getViewer(); @@ -198,7 +252,7 @@ void TaskImageScale::onInteractiveScale() auto vp = Application::Instance->getViewProvider(feature.get()); scale = new InteractiveScale(viewer, vp); connect(scale, &InteractiveScale::selectedPoints, - this, &TaskImageScale::selectedPoints); + this, &TaskImage::selectedPoints); } } @@ -212,6 +266,143 @@ void TaskImageScale::onInteractiveScale() } } +void TaskImage::open() +{ + if (!feature.expired()) { + App::Document* doc = feature->getDocument(); + doc->openTransaction(QT_TRANSLATE_NOOP("Command", "Edit image")); + restore(feature->Placement.getValue()); + } +} + +void TaskImage::accept() +{ + if (!feature.expired()) { + App::Document* doc = feature->getDocument(); + doc->commitTransaction(); + doc->recompute(); + } +} + +void TaskImage::reject() +{ + if (!feature.expired()) { + App::Document* doc = feature->getDocument(); + doc->abortTransaction(); + feature->purgeTouched(); + } +} + +void TaskImage::onPreview() +{ + updateIcon(); + updatePlacement(); +} + +void TaskImage::restore(const Base::Placement& plm) +{ + if (feature.expired()) + return; + + QSignalBlocker blockW(ui->spinBoxWidth); + QSignalBlocker blockH(ui->spinBoxHeight); + ui->spinBoxWidth->setValue(feature->XSize.getValue()); + ui->spinBoxHeight->setValue(feature->YSize.getValue()); + + Base::Rotation rot = plm.getRotation(); + Base::Vector3d pos = plm.getPosition(); + + double yaw, pitch, roll; + rot.getYawPitchRoll(yaw, pitch, roll); + + double tol = 1.0e-5; + bool reverse = false; + if (fabs(pitch) < tol && (fabs(roll) < tol || fabs(roll - 180.) < tol)) { + if (fabs(roll - 180.) < tol) + reverse = true; + int inv = reverse ? -1 : 1; + ui->XY_radioButton->setChecked(true); + ui->spinBoxX->setValue(pos.x); + ui->spinBoxY->setValue(pos.y * inv); + ui->spinBoxZ->setValue(pos.z * inv); + ui->spinBoxRotation->setValue(yaw * inv); + } + else if (fabs(roll - 90.) < tol && (fabs(yaw) < tol || fabs(yaw - 180.) < tol)) { + if (fabs(yaw - 180.) < tol) + reverse = true; + int inv = reverse ? -1 : 1; + ui->XZ_radioButton->setChecked(true); + ui->spinBoxX->setValue(- inv * pos.x); + ui->spinBoxY->setValue(pos.z); + ui->spinBoxZ->setValue(inv * pos.y); + ui->spinBoxRotation->setValue(- pitch); + } + else if (fabs(roll - 90.) < tol && (fabs(yaw - 90.) < tol || fabs(yaw + 90.) < tol)) { + if (fabs(yaw + 90.) < tol) + reverse = true; + int inv = reverse ? -1 : 1; + ui->YZ_radioButton->setChecked(true); + ui->spinBoxX->setValue(-inv * pos.y); + ui->spinBoxY->setValue(pos.z); + ui->spinBoxZ->setValue(inv * pos.x); + ui->spinBoxRotation->setValue(-pitch); + } + + ui->Reverse_checkBox->setChecked(reverse); + + onPreview(); +} + +void TaskImage::updatePlacement() +{ + Base::Placement Pos; + double offsetX = ui->spinBoxX->value().getValue(); + double offsetY = ui->spinBoxY->value().getValue(); + double offsetZ = ui->spinBoxZ->value().getValue(); + double angle = ui->spinBoxRotation->value().getValue(); + bool reverse = ui->Reverse_checkBox->isChecked(); + + Base::Rotation rot; + double dir = reverse ? 180. : 0.; + int inv = reverse ? -1 : 1; + + if (ui->XY_radioButton->isChecked()) { + rot.setYawPitchRoll(inv * angle, 0., dir); + Pos = Base::Placement(Base::Vector3d(offsetX, inv * offsetY, inv * offsetZ), rot); + } + else if (ui->XZ_radioButton->isChecked()) { + rot.setYawPitchRoll(dir, -angle, 90.); + Pos = Base::Placement(Base::Vector3d(- inv * offsetX, inv * offsetZ, offsetY), rot); + } + else if (ui->YZ_radioButton->isChecked()) { + rot.setYawPitchRoll(90. - dir, -angle, 90.); + Pos = Base::Placement(Base::Vector3d(inv * offsetZ, - inv * offsetX, offsetY), rot); + } + + if (!feature.expired()) { + feature->Placement.setValue(Pos); + } +} + +void TaskImage::updateIcon() +{ + std::string icon; + bool reverse = ui->Reverse_checkBox->isChecked(); + if (ui->XY_radioButton->isChecked()) { + icon = reverse ? "view-bottom" : "view-top"; + } + else if (ui->XZ_radioButton->isChecked()) { + icon = reverse ? "view-rear" : "view-front"; + } + else if (ui->YZ_radioButton->isChecked()) { + icon = reverse ? "view-left" : "view-right"; + } + + ui->previewLabel->setPixmap( + Gui::BitmapFactory().pixmapFromSvg(icon.c_str(), + ui->previewLabel->size())); +} + // ---------------------------------------------------------------------------- InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp) @@ -366,4 +557,32 @@ void InteractiveScale::getMousePosition(void * ud, SoEventCallback * ecb) } } -#include "moc_TaskImageScale.cpp" +// ---------------------------------------------------------------------------- + +TaskImageDialog::TaskImageDialog(Image::ImagePlane* obj) +{ + widget = new TaskImage(obj); + Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox( + QPixmap(), widget->windowTitle(), true, nullptr); + taskbox->groupLayout()->addWidget(widget); + Content.push_back(taskbox); +} + +void TaskImageDialog::open() +{ + widget->open(); +} + +bool TaskImageDialog::accept() +{ + widget->accept(); + return true; +} + +bool TaskImageDialog::reject() +{ + widget->reject(); + return true; +} + +#include "moc_TaskImage.cpp" diff --git a/src/Gui/TaskView/TaskImageScale.h b/src/Gui/TaskView/TaskImage.h similarity index 75% rename from src/Gui/TaskView/TaskImageScale.h rename to src/Gui/TaskView/TaskImage.h index 4327abee4c..43bc490171 100644 --- a/src/Gui/TaskView/TaskImageScale.h +++ b/src/Gui/TaskView/TaskImage.h @@ -21,8 +21,8 @@ * * **************************************************************************/ -#ifndef GUI_TASKIMAGESCALE_H -#define GUI_TASKIMAGESCALE_H +#ifndef GUI_TASKIMAGE_H +#define GUI_TASKIMAGE_H #include #include @@ -78,18 +78,23 @@ private: std::vector points; }; -class Ui_TaskImageScale; -class TaskImageScale : public QWidget +class Ui_TaskImage; +class TaskImage : public QWidget { Q_OBJECT public: - explicit TaskImageScale(Image::ImagePlane* obj, QWidget* parent = nullptr); - ~TaskImageScale() override; + explicit TaskImage(Image::ImagePlane* obj, QWidget* parent = nullptr); + ~TaskImage() override; + + void open(); + void accept(); + void reject(); private: - void changeWidth(); - void changeHeight(); + void initialiseTransparency(); + void connectSignals(); + void onInteractiveScale(); View3DInventorViewer* getViewer() const; void selectedPoints(size_t num); @@ -98,13 +103,43 @@ private: void acceptScale(); void rejectScale(); + void restore(const Base::Placement&); + void onPreview(); + void updateIcon(); + void updatePlacement(); + +private Q_SLOTS: + void changeTransparency(int val); + void changeWidth(double val); + void changeHeight(double val); + private: - std::unique_ptr ui; + std::unique_ptr ui; QPointer scale; App::WeakPtrT feature; double aspectRatio; }; +class TaskImageDialog : public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + explicit TaskImageDialog(Image::ImagePlane* obj); + +public: + void open() override; + bool accept() override; + bool reject() override; + + QDialogButtonBox::StandardButtons getStandardButtons() const override { + return QDialogButtonBox::Ok | QDialogButtonBox::Cancel; + } + +private: + TaskImage* widget; +}; + } -#endif // GUI_TASKIMAGESCALE_H +#endif // GUI_TASKIMAGE_H diff --git a/src/Gui/TaskView/TaskImage.ui b/src/Gui/TaskView/TaskImage.ui new file mode 100644 index 0000000000..7efbd2c21d --- /dev/null +++ b/src/Gui/TaskView/TaskImage.ui @@ -0,0 +1,346 @@ + + + Gui::TaskImage + + + + 0 + 0 + 421 + 267 + + + + Image plane settings + + + + + + + + Planes + + + + + + XY-Plane + + + true + + + + + + + XZ-Plane + + + + + + + YZ-Plane + + + + + + + + + + + 48 + 48 + + + + + 48 + 48 + + + + Preview + + + + + + + + + Reverse direction + + + + + + + Offset: + + + + + + + mm + + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + + + + + X distance: + + + + + + + mm + + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + + + + + Y distance: + + + + + + + mm + + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + + + + + Rotation : + + + + + + + deg + + + + + + + + + Transparency : + + + + + + + 100 + + + Qt::Horizontal + + + + + + + 0 + + + 0 + + + 100 + + + + + + + + + Image size + + + + + + + + Width: + + + + + + + mm + + + 0.00000001 + + + 999999999.000000000000000 + + + + + + + Height: + + + + + + + mm + + + 0.00000001 + + + 999999999.000000000000000 + + + + + + + + + Keep aspect ratio + + + true + + + + + + + + + + + + + + + + + + Interactively scale the image + + + Interactive + + + + + + + Cancel + + + + + + + Qt::Horizontal + + + + 136 + 20 + + + + + + + + + 0 + 0 + + + + Allow points outside the image + + + + + + + + + + + Desired distance: + + + + + + + false + + + mm + + + + + + + + + + + + + + + + + + + + Gui::QuantitySpinBox + QWidget +
Gui/QuantitySpinBox.h
+
+
+ + +
diff --git a/src/Gui/TaskView/TaskImageScale.ui b/src/Gui/TaskView/TaskImageScale.ui deleted file mode 100644 index bc51452a36..0000000000 --- a/src/Gui/TaskView/TaskImageScale.ui +++ /dev/null @@ -1,184 +0,0 @@ - - - Gui::TaskImageScale - - - - 0 - 0 - 421 - 267 - - - - Scale image - - - - - - Image size - - - - - - - - Width: - - - - - - - px - - - 1 - - - 100000000 - - - - - - - Height: - - - - - - - px - - - 1 - - - 100000000 - - - - - - - - - Keep aspect ratio - - - true - - - - - - - - - - - - - - - - - - Interactively scale the image - - - Interactive - - - - - - - Cancel - - - - - - - Qt::Horizontal - - - - 136 - 20 - - - - - - - - - 0 - 0 - - - - Allow points outside the image - - - - - - - - - - - Desired distance: - - - - - - - false - - - mm - - - - - - - - - - - - - - - - - - - - Gui::QuantitySpinBox - QWidget -
Gui/QuantitySpinBox.h
-
-
- - spinBoxWidth - spinBoxHeight - checkBoxRatio - pushButtonScale - pushButtonCancel - checkBoxOutside - quantitySpinBox - - - -
diff --git a/src/Gui/ViewProviderImagePlane.cpp b/src/Gui/ViewProviderImagePlane.cpp index 267c9fc99d..0f16a3afc2 100644 --- a/src/Gui/ViewProviderImagePlane.cpp +++ b/src/Gui/ViewProviderImagePlane.cpp @@ -41,8 +41,7 @@ #include #include #include -#include -#include +#include #include #include "ViewProviderImagePlane.h" @@ -159,12 +158,9 @@ bool ViewProviderImagePlane::doubleClicked() void ViewProviderImagePlane::manipulateImage() { - auto dialog = new TaskOrientationDialog( - dynamic_cast(getObject()) - ); - dialog->addTaskBox(new TaskImageScale( + auto dialog = new TaskImageDialog( dynamic_cast(getObject()) - )); + ); Gui::Control().showDialog(dialog); } From fc8c1cbed79434c28bd234c49958e827e45f0708 Mon Sep 17 00:00:00 2001 From: Paddle Date: Fri, 7 Apr 2023 10:06:01 +0200 Subject: [PATCH 02/18] Move SoDatumLabel from Sketcher to Core so that it can be reused anywhere. --- src/Gui/CMakeLists.txt | 2 ++ src/{Mod/Sketcher => }/Gui/SoDatumLabel.cpp | 2 +- src/{Mod/Sketcher => }/Gui/SoDatumLabel.h | 12 ++++++------ src/Gui/SoFCDB.cpp | 2 ++ src/Mod/Sketcher/Gui/AppSketcherGui.cpp | 2 -- src/Mod/Sketcher/Gui/CMakeLists.txt | 2 -- .../Sketcher/Gui/EditModeConstraintCoinManager.cpp | 3 ++- 7 files changed, 13 insertions(+), 12 deletions(-) rename src/{Mod/Sketcher => }/Gui/SoDatumLabel.cpp (99%) rename src/{Mod/Sketcher => }/Gui/SoDatumLabel.h (93%) diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index b795387fa8..fd7adbde1b 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -968,6 +968,7 @@ SET(Inventor_CPP_SRCS SoNavigationDragger.cpp SoAxisCrossKit.cpp SoTextLabel.cpp + SoDatumLabel.cpp SoTouchEvents.cpp SoMouseWheelEvent.cpp SoFCCSysDragger.cpp @@ -995,6 +996,7 @@ SET(Inventor_SRCS SoNavigationDragger.h SoAxisCrossKit.h SoTextLabel.h + SoDatumLabel.h SoTouchEvents.h SoMouseWheelEvent.h SoFCCSysDragger.h diff --git a/src/Mod/Sketcher/Gui/SoDatumLabel.cpp b/src/Gui/SoDatumLabel.cpp similarity index 99% rename from src/Mod/Sketcher/Gui/SoDatumLabel.cpp rename to src/Gui/SoDatumLabel.cpp index 1c5c4add8d..9ab80a1f4b 100644 --- a/src/Mod/Sketcher/Gui/SoDatumLabel.cpp +++ b/src/Gui/SoDatumLabel.cpp @@ -55,7 +55,7 @@ #define ZCONSTR 0.006f -using namespace SketcherGui; +using namespace Gui; // ------------------------------------------------------ diff --git a/src/Mod/Sketcher/Gui/SoDatumLabel.h b/src/Gui/SoDatumLabel.h similarity index 93% rename from src/Mod/Sketcher/Gui/SoDatumLabel.h rename to src/Gui/SoDatumLabel.h index 766979d1e3..f4eb5685d3 100644 --- a/src/Mod/Sketcher/Gui/SoDatumLabel.h +++ b/src/Gui/SoDatumLabel.h @@ -20,8 +20,8 @@ * * ***************************************************************************/ -#ifndef SKETCHERGUI_SODATUMLABEL_H -#define SKETCHERGUI_SODATUMLABEL_H +#ifndef GUI_SODATUMLABEL_H +#define GUI_SODATUMLABEL_H #include #include @@ -35,12 +35,12 @@ #include #include -#include +#include -namespace SketcherGui { +namespace Gui { -class SketcherGuiExport SoDatumLabel : public SoShape { +class GuiExport SoDatumLabel : public SoShape { using inherited = SoShape; SO_NODE_HEADER(SoDatumLabel); @@ -99,4 +99,4 @@ private: } -#endif // SKETCHERGUI_SODATUMLABEL_H +#endif // GUI_SODATUMLABEL_H diff --git a/src/Gui/SoFCDB.cpp b/src/Gui/SoFCDB.cpp index 1fb8002705..08598a269b 100644 --- a/src/Gui/SoFCDB.cpp +++ b/src/Gui/SoFCDB.cpp @@ -69,6 +69,7 @@ #include "SoMouseWheelEvent.h" #include "SoNavigationDragger.h" #include "SoTextLabel.h" +#include "SoDatumLabel.h" #include "Inventor/MarkerBitmaps.h" #include "Inventor/SmSwitchboard.h" #include "Inventor/SoAutoZoomTranslation.h" @@ -124,6 +125,7 @@ void Gui::SoFCDB::init() SoVRMLAction ::initClass(); SoSkipBoundingGroup ::initClass(); SoTextLabel ::initClass(); + SoDatumLabel ::initClass(); SoColorBarLabel ::initClass(); SoStringLabel ::initClass(); SoFrameLabel ::initClass(); diff --git a/src/Mod/Sketcher/Gui/AppSketcherGui.cpp b/src/Mod/Sketcher/Gui/AppSketcherGui.cpp index 5400376a45..37d62d793c 100644 --- a/src/Mod/Sketcher/Gui/AppSketcherGui.cpp +++ b/src/Mod/Sketcher/Gui/AppSketcherGui.cpp @@ -32,7 +32,6 @@ #include "PropertyConstraintListItem.h" #include "SketcherSettings.h" -#include "SoDatumLabel.h" #include "SoZoomTranslation.h" #include "ViewProviderPython.h" #include "ViewProviderSketch.h" @@ -125,7 +124,6 @@ PyMOD_INIT_FUNC(SketcherGui) SketcherGui::ViewProviderPython ::init(); SketcherGui::ViewProviderCustom ::init(); SketcherGui::ViewProviderCustomPython ::init(); - SketcherGui::SoDatumLabel ::initClass(); SketcherGui::SoZoomTranslation ::initClass(); SketcherGui::PropertyConstraintListItem ::init(); SketcherGui::ViewProviderSketchGeometryExtension ::init(); diff --git a/src/Mod/Sketcher/Gui/CMakeLists.txt b/src/Mod/Sketcher/Gui/CMakeLists.txt index 74f4fdedbf..bf24df36fc 100644 --- a/src/Mod/Sketcher/Gui/CMakeLists.txt +++ b/src/Mod/Sketcher/Gui/CMakeLists.txt @@ -87,8 +87,6 @@ SET(SketcherGui_SRCS PreCompiled.h SoZoomTranslation.cpp SoZoomTranslation.h - SoDatumLabel.cpp - SoDatumLabel.h PropertyConstraintListItem.h PropertyConstraintListItem.cpp TaskSketcherConstraints.ui diff --git a/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp index ffeb8283ee..3f62f61884 100644 --- a/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -58,13 +59,13 @@ #include #include "EditModeConstraintCoinManager.h" -#include "SoDatumLabel.h" #include "SoZoomTranslation.h" #include "ViewProviderSketch.h" #include "ViewProviderSketchCoinAttorney.h" #include "Utils.h" +using namespace Gui; using namespace SketcherGui; using namespace Sketcher; From 9172157d40c77dbcc45704a7617322aa9ac82149 Mon Sep 17 00:00:00 2001 From: Paddle Date: Fri, 7 Apr 2023 14:05:13 +0200 Subject: [PATCH 03/18] TaskImage: use SoDatumLabel instead of basic line. --- src/Gui/SoDatumLabel.cpp | 2 + src/Gui/TaskView/TaskImage.cpp | 94 +++++++++++++++++++++++++--------- src/Gui/TaskView/TaskImage.h | 10 ++-- 3 files changed, 77 insertions(+), 29 deletions(-) diff --git a/src/Gui/SoDatumLabel.cpp b/src/Gui/SoDatumLabel.cpp index 9ab80a1f4b..05d005880a 100644 --- a/src/Gui/SoDatumLabel.cpp +++ b/src/Gui/SoDatumLabel.cpp @@ -615,11 +615,13 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action) } // Perp Lines glBegin(GL_LINES); + if (length != 0.) { glVertex2f(p1[0], p1[1]); glVertex2f(perp1[0], perp1[1]); glVertex2f(p2[0], p2[1]); glVertex2f(perp2[0], perp2[1]); + } glVertex2f(par1[0], par1[1]); glVertex2f(par2[0], par2[1]); diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index c9d955b0b1..980446d490 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -37,12 +37,14 @@ #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -240,8 +242,6 @@ void TaskImage::rejectScale() ui->pushButtonCancel->hide(); ui->quantitySpinBox->setEnabled(false); ui->checkBoxOutside->setEnabled(true); - - scale->clearPoints(); } void TaskImage::onInteractiveScale() @@ -250,7 +250,7 @@ void TaskImage::onInteractiveScale() View3DInventorViewer* viewer = getViewer(); if (viewer) { auto vp = Application::Instance->getViewProvider(feature.get()); - scale = new InteractiveScale(viewer, vp); + scale = new InteractiveScale(viewer, vp, getNorm()); connect(scale, &InteractiveScale::selectedPoints, this, &TaskImage::selectedPoints); } @@ -403,31 +403,51 @@ void TaskImage::updateIcon() ui->previewLabel->size())); } +SbVec3f TaskImage::getNorm() +{ + if (feature.expired()) + return SbVec3f(0., 0., 1.); + + // Get imagePlane normal + Base::Vector3d RN(0, 0, 1); + + // move to position of Sketch + Base::Placement Plz = feature->Placement.getValue(); + Base::Rotation tmp(Plz.getRotation()); + tmp.multVec(RN, RN); + Plz.setRotation(tmp); + return SbVec3f(RN.x, RN.y, RN.z); +} + // ---------------------------------------------------------------------------- -InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp) +InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, SbVec3f normal) : active{false} , allowOutsideImage{false} , viewer{view} , viewProv{vp} + , norm{normal} { - coords = new SoCoordinate3; - coords->ref(); root = new SoAnnotation; root->ref(); + root->renderCaching = SoSeparator::OFF; - root->addChild(coords); - - SoBaseColor* color = new SoBaseColor; - color->rgb.setValue(1.0F, 0.0F, 0.0F); - root->addChild(color); - root->addChild(new SoLineSet); + measureLabel = new SoDatumLabel(); + measureLabel->ref(); + measureLabel->norm.setValue(norm); + measureLabel->string = ""; + measureLabel->textColor = SbColor(1.0f, 0.149f, 0.0f); + measureLabel->size.setValue(17); + measureLabel->lineWidth = 2.0; + measureLabel->useAntialiasing = false; + measureLabel->param1 = 0.; + measureLabel->param2 = 0.; } InteractiveScale::~InteractiveScale() { - coords->unref(); root->unref(); + measureLabel->unref(); } void InteractiveScale::activate(bool allowOutside) @@ -447,6 +467,8 @@ void InteractiveScale::activate(bool allowOutside) void InteractiveScale::deactivate() { if (viewer) { + points.clear(); + root->removeChild(measureLabel); static_cast(viewer->getSceneGraph())->removeChild(root); viewer->setEditing(false); viewer->removeEventCallback(SoLocation2Event::getClassTypeId(), InteractiveScale::getMousePosition, this); @@ -473,12 +495,6 @@ double InteractiveScale::getDistance(const SbVec3f& pt) const return (points[0] - pt).length(); } -void InteractiveScale::clearPoints() -{ - points.clear(); - coords->point.setNum(0); -} - void InteractiveScale::findPointOnPlane(SoEventCallback * ecb) { if (allowOutsideImage) { @@ -516,13 +532,13 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d) { if (points.empty()) { points.push_back(pos3d); - coords->point.set1Value(0, pos3d); + + root->addChild(measureLabel); } else if (points.size() == 1) { double distance = getDistance(pos3d); if (distance > Base::Precision::Confusion()) { points.push_back(pos3d); - coords->point.set1Value(1, pos3d); } else { Base::Console().Warning(std::string("Image scale"), "The second point is too close. Retry!\n"); @@ -551,9 +567,39 @@ void InteractiveScale::getMousePosition(void * ud, SoEventCallback * ecb) if (scale->points.size() == 1) { ecb->setHandled(); - auto pos2d = l2e->getPosition(); - auto pos3d = view->getPointOnFocalPlane(pos2d); - scale->coords->point.set1Value(1, pos3d); + SbVec3f pos3d; + if (scale->allowOutsideImage) { + auto pos2d = l2e->getPosition(); + pos3d = view->getPointOnFocalPlane(pos2d); + } + else { + std::unique_ptr pp(view->getPointOnRay(l2e->getPosition(), scale->viewProv)); + if (pp.get()) { + pos3d = pp->getPoint(); + } + else { + return; + } + } + + Base::Quantity quantity; + quantity.setValue((pos3d - scale->points[0]).length()); + quantity.setUnit(Base::Unit::Length); + + //Update the displayed distance + double factor; + QString unitStr, valueStr; + valueStr = quantity.getUserString(factor, unitStr); + scale->measureLabel->string = SbString(valueStr.toUtf8().constData()); + + //Update the points. + scale->measureLabel->pnts.setNum(2); + SbVec3f* verts = scale->measureLabel->pnts.startEditing(); + + verts[0] = scale->points[0]; + verts[1] = pos3d; + + scale->measureLabel->pnts.finishEditing(); } } diff --git a/src/Gui/TaskView/TaskImage.h b/src/Gui/TaskView/TaskImage.h index 43bc490171..b75ec22930 100644 --- a/src/Gui/TaskView/TaskImage.h +++ b/src/Gui/TaskView/TaskImage.h @@ -33,9 +33,8 @@ class SbVec3f; class SoEventCallback; -class SoCoordinate3; class SoSeparator; -class SoLineSet; +class SoDatumLabel; namespace Gui { @@ -46,7 +45,7 @@ class InteractiveScale : public QObject Q_OBJECT public: - explicit InteractiveScale(View3DInventorViewer* view, ViewProvider* vp); + explicit InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, SbVec3f normal); ~InteractiveScale(); void activate(bool allowOutside); void deactivate(); @@ -55,7 +54,6 @@ public: } double getDistance() const; double getDistance(const SbVec3f&) const; - void clearPoints(); private: static void getMouseClick(void * ud, SoEventCallback * ecb); @@ -71,11 +69,12 @@ Q_SIGNALS: private: bool active; bool allowOutsideImage; - SoCoordinate3* coords; SoSeparator* root; + SoDatumLabel* measureLabel; QPointer viewer; ViewProvider* viewProv; std::vector points; + SbVec3f norm; }; class Ui_TaskImage; @@ -102,6 +101,7 @@ private: void startScale(); void acceptScale(); void rejectScale(); + SbVec3f getNorm(); void restore(const Base::Placement&); void onPreview(); From 0acbb881cb05e162e815e876696403a47bb40d88 Mon Sep 17 00:00:00 2001 From: Paddle Date: Sun, 9 Apr 2023 08:10:59 +0200 Subject: [PATCH 04/18] TaskImage: rework interactive scaling tool. --- src/Gui/TaskView/TaskImage.cpp | 179 ++++++++++++++++++++------------- src/Gui/TaskView/TaskImage.h | 25 +++-- src/Gui/TaskView/TaskImage.ui | 57 +---------- 3 files changed, 135 insertions(+), 126 deletions(-) diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index 980446d490..a020ae142a 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -25,14 +25,18 @@ #ifndef _PreComp_ # include # include +# include # include # include # include # include +# include +# include # include # include # include # include +# include #endif #include @@ -71,6 +75,11 @@ TaskImage::TaskImage(Image::ImagePlane* obj, QWidget* parent) aspectRatio = obj->XSize.getValue() / obj->YSize.getValue(); + QAction* action = new QAction(tr("Allow points outside the image"), this); + action->setCheckable(true); + action->setChecked(false); + ui->pushButtonScale->addAction(action); + connectSignals(); } @@ -184,20 +193,6 @@ View3DInventorViewer* TaskImage::getViewer() const return nullptr; } -void TaskImage::selectedPoints(size_t num) -{ - if (num == 1) { - ui->labelInstruction->setText(tr("Select second point")); - } - else if (num == 2) { - ui->labelInstruction->setText(tr("Enter desired distance between the points")); - ui->pushButtonScale->setEnabled(true); - ui->quantitySpinBox->setEnabled(true); - ui->quantitySpinBox->setValue(scale->getDistance()); - ui->quantitySpinBox->setFocus(); - } -} - void TaskImage::scaleImage(double factor) { if (!feature.expired()) { @@ -213,35 +208,22 @@ void TaskImage::scaleImage(double factor) void TaskImage::startScale() { - scale->activate(ui->checkBoxOutside->isChecked()); - if (ui->checkBoxOutside->isChecked()) { - ui->labelInstruction->setText(tr("Select two points in the 3d view")); - } - else { - ui->labelInstruction->setText(tr("Select two points on the image")); - } - ui->checkBoxOutside->setEnabled(false); - ui->pushButtonScale->setEnabled(false); - ui->pushButtonScale->setText(tr("Accept")); + scale->activate(qAsConst(ui->pushButtonScale)->actions()[0]->isChecked()); + ui->pushButtonScale->hide(); ui->pushButtonCancel->show(); - ui->quantitySpinBox->setEnabled(false); } -void TaskImage::acceptScale() +void TaskImage::acceptScale(double val) { - scaleImage(ui->quantitySpinBox->value().getValue() / scale->getDistance()); + scaleImage(val / scale->getDistance()); rejectScale(); } void TaskImage::rejectScale() { scale->deactivate(); - ui->labelInstruction->clear(); - ui->pushButtonScale->setEnabled(true); - ui->pushButtonScale->setText(tr("Interactive")); + ui->pushButtonScale->show(); ui->pushButtonCancel->hide(); - ui->quantitySpinBox->setEnabled(false); - ui->checkBoxOutside->setEnabled(true); } void TaskImage::onInteractiveScale() @@ -250,20 +232,14 @@ void TaskImage::onInteractiveScale() View3DInventorViewer* viewer = getViewer(); if (viewer) { auto vp = Application::Instance->getViewProvider(feature.get()); - scale = new InteractiveScale(viewer, vp, getNorm()); - connect(scale, &InteractiveScale::selectedPoints, - this, &TaskImage::selectedPoints); + Base::Placement placement = feature->Placement.getValue(); + scale = new InteractiveScale(viewer, vp, placement); + connect(scale, &InteractiveScale::scaleRequired, + this, &TaskImage::acceptScale); } } - if (scale) { - if (scale->isActive()) { - acceptScale(); - } - else { - startScale(); - } - } + startScale(); } void TaskImage::open() @@ -381,6 +357,8 @@ void TaskImage::updatePlacement() if (!feature.expired()) { feature->Placement.setValue(Pos); + if(scale) + scale->setPlacement(Pos); } } @@ -403,30 +381,20 @@ void TaskImage::updateIcon() ui->previewLabel->size())); } -SbVec3f TaskImage::getNorm() -{ - if (feature.expired()) - return SbVec3f(0., 0., 1.); - - // Get imagePlane normal - Base::Vector3d RN(0, 0, 1); - - // move to position of Sketch - Base::Placement Plz = feature->Placement.getValue(); - Base::Rotation tmp(Plz.getRotation()); - tmp.multVec(RN, RN); - Plz.setRotation(tmp); - return SbVec3f(RN.x, RN.y, RN.z); -} - // ---------------------------------------------------------------------------- -InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, SbVec3f normal) + +struct NodeData { + InteractiveScale* scale; +}; + +InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, Base::Placement plc) : active{false} , allowOutsideImage{false} + , placement{plc} , viewer{view} , viewProv{vp} - , norm{normal} + , midPoint{SbVec3f(0,0,0)} { root = new SoAnnotation; root->ref(); @@ -434,7 +402,6 @@ InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, measureLabel = new SoDatumLabel(); measureLabel->ref(); - measureLabel->norm.setValue(norm); measureLabel->string = ""; measureLabel->textColor = SbColor(1.0f, 0.149f, 0.0f); measureLabel->size.setValue(17); @@ -442,12 +409,39 @@ InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, measureLabel->useAntialiasing = false; measureLabel->param1 = 0.; measureLabel->param2 = 0.; + + transform = new SoTransform(); + root->addChild(transform); + setPlacement(placement); + + Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView(); + distanceBox = new QuantitySpinBox(mdi); + distanceBox->setUnit(Base::Unit::Length); + distanceBox->setMinimum(0.0); + distanceBox->setMaximum(INT_MAX); + distanceBox->setButtonSymbols(QAbstractSpinBox::NoButtons); + distanceBox->setToolTip(tr("Enter desired distance between the points")); + distanceBox->setKeyboardTracking(false); + + // Pressing enter will validate the tool. + connect(distanceBox, qOverload(& QuantitySpinBox::valueChanged), + this, &InteractiveScale::distanceEntered); + + //track camera movements to update spinbox position. + NodeData* info = new NodeData{ this }; + cameraSensor = new SoNodeSensor([](void* data, SoSensor* sensor) { + NodeData* info = static_cast(data); + info->scale->positionWidget(); + }, info); + cameraSensor->attach(viewer->getCamera()); } InteractiveScale::~InteractiveScale() { root->unref(); measureLabel->unref(); + distanceBox->deleteLater(); + cameraSensor->detach(); } void InteractiveScale::activate(bool allowOutside) @@ -467,6 +461,7 @@ void InteractiveScale::activate(bool allowOutside) void InteractiveScale::deactivate() { if (viewer) { + distanceBox->hide(); points.clear(); root->removeChild(measureLabel); static_cast(viewer->getSceneGraph())->removeChild(root); @@ -539,13 +534,30 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d) double distance = getDistance(pos3d); if (distance > Base::Precision::Confusion()) { points.push_back(pos3d); + + midPoint = points[0] + (points[1] - points[0]) / 2; + + measureLabel->string = ""; + positionWidget(); + QSignalBlocker block(distanceBox); + distanceBox->setValue((points[1] - points[0]).length()); + distanceBox->show(); + distanceBox->selectNumber(); + distanceBox->setFocus(); } else { Base::Console().Warning(std::string("Image scale"), "The second point is too close. Retry!\n"); } } +} - Q_EMIT selectedPoints(points.size()); +void InteractiveScale::positionWidget() +{ + QSize wSize = distanceBox->size(); + QPoint pxCoord = viewer->toQPoint(viewer->getPointOnViewport(midPoint)); + pxCoord.setX(std::max(pxCoord.x() - wSize.width() / 2, 0)); + pxCoord.setY(std::max(pxCoord.y() - wSize.height() / 2, 0)); + distanceBox->move(pxCoord); } void InteractiveScale::getMouseClick(void * ud, SoEventCallback * ecb) @@ -592,17 +604,48 @@ void InteractiveScale::getMousePosition(void * ud, SoEventCallback * ecb) valueStr = quantity.getUserString(factor, unitStr); scale->measureLabel->string = SbString(valueStr.toUtf8().constData()); - //Update the points. + //Update the SoDatumLabel. It needs 2D points! scale->measureLabel->pnts.setNum(2); SbVec3f* verts = scale->measureLabel->pnts.startEditing(); - - verts[0] = scale->points[0]; - verts[1] = pos3d; - + verts[0] = scale->getCoordsOnImagePlane(scale->points[0]); + verts[1] = scale->getCoordsOnImagePlane(pos3d); scale->measureLabel->pnts.finishEditing(); } } +void InteractiveScale::distanceEntered(double val) +{ + Q_EMIT scaleRequired(val); +} + +void InteractiveScale::setPlacement(Base::Placement plc) +{ + placement = plc; + double x, y, z, w; + placement.getRotation().getValue(x, y, z, w); + transform->rotation.setValue(x, y, z, w); + + Base::Vector3d RN(0, 0, 1); + RN = placement.getRotation().multVec(RN); + measureLabel->norm.setValue(SbVec3f(RN.x, RN.y, RN.z)); +} + +SbVec3f InteractiveScale::getCoordsOnImagePlane(const SbVec3f& point) +{ + // Plane form + Base::Vector3d R0(0, 0, 0), RX(1, 0, 0), RY(0, 1, 0); + + // move to position of Sketch + Base::Rotation tmp(placement.getRotation()); + RX = tmp.multVec(RX); + RY = tmp.multVec(RY); + + Base::Vector3d S(point[0], point[1], point[2]); + S.TransformToCoordinateSystem(R0, RX, RY); + + return SbVec3f(S.x, S.y, 0.); +} + // ---------------------------------------------------------------------------- TaskImageDialog::TaskImageDialog(Image::ImagePlane* obj) diff --git a/src/Gui/TaskView/TaskImage.h b/src/Gui/TaskView/TaskImage.h index b75ec22930..b1093610f1 100644 --- a/src/Gui/TaskView/TaskImage.h +++ b/src/Gui/TaskView/TaskImage.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -35,6 +36,8 @@ class SbVec3f; class SoEventCallback; class SoSeparator; class SoDatumLabel; +class SoNodeSensor; +class SoTransform; namespace Gui { @@ -45,7 +48,7 @@ class InteractiveScale : public QObject Q_OBJECT public: - explicit InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, SbVec3f normal); + explicit InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, Base::Placement plc); ~InteractiveScale(); void activate(bool allowOutside); void deactivate(); @@ -54,6 +57,7 @@ public: } double getDistance() const; double getDistance(const SbVec3f&) const; + void setPlacement(Base::Placement plc); private: static void getMouseClick(void * ud, SoEventCallback * ecb); @@ -62,19 +66,30 @@ private: void findPointOnImagePlane(SoEventCallback * ecb); void findPointOnFocalPlane(SoEventCallback * ecb); void collectPoint(const SbVec3f&); + void positionWidget(); + + /// give the coordinates of a line on the image plane in imagePlane (2D) coordinates + SbVec3f getCoordsOnImagePlane(const SbVec3f& point); Q_SIGNALS: - void selectedPoints(size_t); + void scaleRequired(double); + +protected Q_SLOTS: + void distanceEntered(double); private: bool active; bool allowOutsideImage; + Base::Placement placement; SoSeparator* root; SoDatumLabel* measureLabel; + SoTransform* transform; QPointer viewer; ViewProvider* viewProv; std::vector points; - SbVec3f norm; + SbVec3f midPoint; + QuantitySpinBox* distanceBox; + SoNodeSensor* cameraSensor; }; class Ui_TaskImage; @@ -96,12 +111,10 @@ private: void onInteractiveScale(); View3DInventorViewer* getViewer() const; - void selectedPoints(size_t num); void scaleImage(double); void startScale(); - void acceptScale(); + void acceptScale(double val); void rejectScale(); - SbVec3f getNorm(); void restore(const Base::Placement&); void onPreview(); diff --git a/src/Gui/TaskView/TaskImage.ui b/src/Gui/TaskView/TaskImage.ui index 7efbd2c21d..6126d70a35 100644 --- a/src/Gui/TaskView/TaskImage.ui +++ b/src/Gui/TaskView/TaskImage.ui @@ -245,25 +245,19 @@ - - - - - - - - - - + - + Interactively scale the image Interactive + + QToolButton::MenuButtonPopup + @@ -286,49 +280,8 @@ - - - - - 0 - 0 - - - - Allow points outside the image - - - - - - - - - Desired distance: - - - - - - - false - - - mm - - - - - - - - - - - - From 31b2cf68d642ea398b8a4caee9222cbd25a06009 Mon Sep 17 00:00:00 2001 From: Paddle Date: Tue, 11 Apr 2023 14:36:06 +0200 Subject: [PATCH 05/18] TaskImage : Add OK and Cancel buttons. --- src/Gui/TaskView/TaskImage.cpp | 66 ++++++++++++++++++++++++++++------ src/Gui/TaskView/TaskImage.h | 8 +++-- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index a020ae142a..9d5548c8bc 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -26,6 +26,7 @@ # include # include # include +# include # include # include # include @@ -236,6 +237,8 @@ void TaskImage::onInteractiveScale() scale = new InteractiveScale(viewer, vp, placement); connect(scale, &InteractiveScale::scaleRequired, this, &TaskImage::acceptScale); + connect(scale, &InteractiveScale::scaleCanceled, + this, &TaskImage::rejectScale); } } @@ -415,17 +418,38 @@ InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, setPlacement(placement); Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView(); - distanceBox = new QuantitySpinBox(mdi); + overlayWidget = new QWidget(mdi); + + distanceBox = new QuantitySpinBox(overlayWidget); distanceBox->setUnit(Base::Unit::Length); distanceBox->setMinimum(0.0); distanceBox->setMaximum(INT_MAX); distanceBox->setButtonSymbols(QAbstractSpinBox::NoButtons); distanceBox->setToolTip(tr("Enter desired distance between the points")); distanceBox->setKeyboardTracking(false); + distanceBox->installEventFilter(this); - // Pressing enter will validate the tool. - connect(distanceBox, qOverload(& QuantitySpinBox::valueChanged), - this, &InteractiveScale::distanceEntered); + QToolButton* okBtn = new QToolButton(overlayWidget); + QIcon icon1; + icon1.addFile(QString::fromUtf8(":/icons/edit_OK.svg"), QSize(), QIcon::Normal, QIcon::Off); + okBtn->setIcon(icon1); + connect(okBtn, &QToolButton::clicked, this, &InteractiveScale::scaleValidated); + + QToolButton* cancelBtn = new QToolButton(overlayWidget); + QIcon icon2; + icon2.addFile(QString::fromUtf8(":/icons/edit_Cancel.svg"), QSize(), QIcon::Normal, QIcon::Off); + cancelBtn->setIcon(icon2); + connect(cancelBtn, &QToolButton::clicked, this, &InteractiveScale::scaleCanceled); + + auto* layout = new QHBoxLayout(overlayWidget); + layout->addWidget(distanceBox); + layout->addWidget(okBtn); + layout->addWidget(cancelBtn); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + overlayWidget->setLayout(layout); + + this->installEventFilter(this); //track camera movements to update spinbox position. NodeData* info = new NodeData{ this }; @@ -440,7 +464,7 @@ InteractiveScale::~InteractiveScale() { root->unref(); measureLabel->unref(); - distanceBox->deleteLater(); + overlayWidget->deleteLater(); cameraSensor->detach(); } @@ -461,7 +485,7 @@ void InteractiveScale::activate(bool allowOutside) void InteractiveScale::deactivate() { if (viewer) { - distanceBox->hide(); + overlayWidget->hide(); points.clear(); root->removeChild(measureLabel); static_cast(viewer->getSceneGraph())->removeChild(root); @@ -539,9 +563,10 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d) measureLabel->string = ""; positionWidget(); + overlayWidget->show(); + overlayWidget->adjustSize(); QSignalBlocker block(distanceBox); distanceBox->setValue((points[1] - points[0]).length()); - distanceBox->show(); distanceBox->selectNumber(); distanceBox->setFocus(); } @@ -553,11 +578,11 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d) void InteractiveScale::positionWidget() { - QSize wSize = distanceBox->size(); + QSize wSize = overlayWidget->size(); QPoint pxCoord = viewer->toQPoint(viewer->getPointOnViewport(midPoint)); pxCoord.setX(std::max(pxCoord.x() - wSize.width() / 2, 0)); pxCoord.setY(std::max(pxCoord.y() - wSize.height() / 2, 0)); - distanceBox->move(pxCoord); + overlayWidget->move(pxCoord); } void InteractiveScale::getMouseClick(void * ud, SoEventCallback * ecb) @@ -613,9 +638,28 @@ void InteractiveScale::getMousePosition(void * ud, SoEventCallback * ecb) } } -void InteractiveScale::distanceEntered(double val) +bool InteractiveScale::eventFilter(QObject* object, QEvent* event) { - Q_EMIT scaleRequired(val); + if (event->type() == QEvent::KeyRelease) { + QKeyEvent* keyEvent = static_cast(event); + + /* If user press enter in the spinbox, then we validate the tool.*/ + if (keyEvent->key() == Qt::Key_Enter && dynamic_cast(object)) { + Q_EMIT scaleRequired(distanceBox->value().getValue()); + } + + /* If user press escape, then we cancel the tool.*/ + if (keyEvent->key() == Qt::Key_Escape) { + Q_EMIT scaleCanceled(); + } + } + + return false; +} + +void InteractiveScale::scaleValidated() +{ + Q_EMIT scaleRequired(distanceBox->value().getValue()); } void InteractiveScale::setPlacement(Base::Placement plc) diff --git a/src/Gui/TaskView/TaskImage.h b/src/Gui/TaskView/TaskImage.h index b1093610f1..c64e1720ca 100644 --- a/src/Gui/TaskView/TaskImage.h +++ b/src/Gui/TaskView/TaskImage.h @@ -50,6 +50,8 @@ class InteractiveScale : public QObject public: explicit InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, Base::Placement plc); ~InteractiveScale(); + + bool eventFilter(QObject* object, QEvent* event); void activate(bool allowOutside); void deactivate(); bool isActive() const { @@ -73,9 +75,10 @@ private: Q_SIGNALS: void scaleRequired(double); + void scaleCanceled(); -protected Q_SLOTS: - void distanceEntered(double); +private Q_SLOTS: + void scaleValidated(); private: bool active; @@ -89,6 +92,7 @@ private: std::vector points; SbVec3f midPoint; QuantitySpinBox* distanceBox; + QWidget* overlayWidget; SoNodeSensor* cameraSensor; }; From 33614f4c02667987ba570212b3518a0d601a3cbe Mon Sep 17 00:00:00 2001 From: Paddle Date: Tue, 11 Apr 2023 18:13:11 +0200 Subject: [PATCH 06/18] TaskImage : Remove OK and Cancel buttons and others --- src/Gui/TaskView/TaskImage.cpp | 60 +++++++++++----------------------- src/Gui/TaskView/TaskImage.h | 10 ++---- src/Gui/TaskView/TaskImage.ui | 11 +++++-- 3 files changed, 31 insertions(+), 50 deletions(-) diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index 9d5548c8bc..b56e59de1f 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -70,6 +70,7 @@ TaskImage::TaskImage(Image::ImagePlane* obj, QWidget* parent) , aspectRatio(1.0) { ui->setupUi(this); + ui->pushButtonApply->hide(); ui->pushButtonCancel->hide(); initialiseTransparency(); @@ -123,6 +124,8 @@ void TaskImage::connectSignals() this, &TaskImage::changeHeight); connect(ui->pushButtonScale, &QPushButton::clicked, this, &TaskImage::onInteractiveScale); + connect(ui->pushButtonApply, &QPushButton::clicked, + this, &TaskImage::acceptScale); connect(ui->pushButtonCancel, &QPushButton::clicked, this, &TaskImage::rejectScale); } @@ -211,12 +214,13 @@ void TaskImage::startScale() { scale->activate(qAsConst(ui->pushButtonScale)->actions()[0]->isChecked()); ui->pushButtonScale->hide(); + ui->pushButtonApply->show(); ui->pushButtonCancel->show(); } -void TaskImage::acceptScale(double val) +void TaskImage::acceptScale() { - scaleImage(val / scale->getDistance()); + scaleImage(scale->getScaleFactor()); rejectScale(); } @@ -224,6 +228,7 @@ void TaskImage::rejectScale() { scale->deactivate(); ui->pushButtonScale->show(); + ui->pushButtonApply->hide(); ui->pushButtonCancel->hide(); } @@ -418,9 +423,7 @@ InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, setPlacement(placement); Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView(); - overlayWidget = new QWidget(mdi); - - distanceBox = new QuantitySpinBox(overlayWidget); + distanceBox = new QuantitySpinBox(mdi); distanceBox->setUnit(Base::Unit::Length); distanceBox->setMinimum(0.0); distanceBox->setMaximum(INT_MAX); @@ -429,26 +432,6 @@ InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, distanceBox->setKeyboardTracking(false); distanceBox->installEventFilter(this); - QToolButton* okBtn = new QToolButton(overlayWidget); - QIcon icon1; - icon1.addFile(QString::fromUtf8(":/icons/edit_OK.svg"), QSize(), QIcon::Normal, QIcon::Off); - okBtn->setIcon(icon1); - connect(okBtn, &QToolButton::clicked, this, &InteractiveScale::scaleValidated); - - QToolButton* cancelBtn = new QToolButton(overlayWidget); - QIcon icon2; - icon2.addFile(QString::fromUtf8(":/icons/edit_Cancel.svg"), QSize(), QIcon::Normal, QIcon::Off); - cancelBtn->setIcon(icon2); - connect(cancelBtn, &QToolButton::clicked, this, &InteractiveScale::scaleCanceled); - - auto* layout = new QHBoxLayout(overlayWidget); - layout->addWidget(distanceBox); - layout->addWidget(okBtn); - layout->addWidget(cancelBtn); - layout->setContentsMargins(0, 0, 0, 0); - layout->setSpacing(0); - overlayWidget->setLayout(layout); - this->installEventFilter(this); //track camera movements to update spinbox position. @@ -464,7 +447,7 @@ InteractiveScale::~InteractiveScale() { root->unref(); measureLabel->unref(); - overlayWidget->deleteLater(); + distanceBox->deleteLater(); cameraSensor->detach(); } @@ -485,7 +468,7 @@ void InteractiveScale::activate(bool allowOutside) void InteractiveScale::deactivate() { if (viewer) { - overlayWidget->hide(); + distanceBox->hide(); points.clear(); root->removeChild(measureLabel); static_cast(viewer->getSceneGraph())->removeChild(root); @@ -498,12 +481,12 @@ void InteractiveScale::deactivate() } } -double InteractiveScale::getDistance() const +double InteractiveScale::getScaleFactor() const { - if (points.size() < 2) - return 0.0; + if ((points[0] - points[1]).length() == 0.) + return 1.0; - return (points[0] - points[1]).length(); + return distanceBox->value().getValue() / (points[0] - points[1]).length(); } double InteractiveScale::getDistance(const SbVec3f& pt) const @@ -563,8 +546,8 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d) measureLabel->string = ""; positionWidget(); - overlayWidget->show(); - overlayWidget->adjustSize(); + distanceBox->show(); + distanceBox->adjustSize(); QSignalBlocker block(distanceBox); distanceBox->setValue((points[1] - points[0]).length()); distanceBox->selectNumber(); @@ -578,11 +561,11 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d) void InteractiveScale::positionWidget() { - QSize wSize = overlayWidget->size(); + QSize wSize = distanceBox->size(); QPoint pxCoord = viewer->toQPoint(viewer->getPointOnViewport(midPoint)); pxCoord.setX(std::max(pxCoord.x() - wSize.width() / 2, 0)); pxCoord.setY(std::max(pxCoord.y() - wSize.height() / 2, 0)); - overlayWidget->move(pxCoord); + distanceBox->move(pxCoord); } void InteractiveScale::getMouseClick(void * ud, SoEventCallback * ecb) @@ -645,7 +628,7 @@ bool InteractiveScale::eventFilter(QObject* object, QEvent* event) /* If user press enter in the spinbox, then we validate the tool.*/ if (keyEvent->key() == Qt::Key_Enter && dynamic_cast(object)) { - Q_EMIT scaleRequired(distanceBox->value().getValue()); + Q_EMIT scaleRequired(); } /* If user press escape, then we cancel the tool.*/ @@ -657,11 +640,6 @@ bool InteractiveScale::eventFilter(QObject* object, QEvent* event) return false; } -void InteractiveScale::scaleValidated() -{ - Q_EMIT scaleRequired(distanceBox->value().getValue()); -} - void InteractiveScale::setPlacement(Base::Placement plc) { placement = plc; diff --git a/src/Gui/TaskView/TaskImage.h b/src/Gui/TaskView/TaskImage.h index c64e1720ca..aef78d8c8b 100644 --- a/src/Gui/TaskView/TaskImage.h +++ b/src/Gui/TaskView/TaskImage.h @@ -57,7 +57,7 @@ public: bool isActive() const { return active; } - double getDistance() const; + double getScaleFactor() const; double getDistance(const SbVec3f&) const; void setPlacement(Base::Placement plc); @@ -74,12 +74,9 @@ private: SbVec3f getCoordsOnImagePlane(const SbVec3f& point); Q_SIGNALS: - void scaleRequired(double); + void scaleRequired(); void scaleCanceled(); -private Q_SLOTS: - void scaleValidated(); - private: bool active; bool allowOutsideImage; @@ -92,7 +89,6 @@ private: std::vector points; SbVec3f midPoint; QuantitySpinBox* distanceBox; - QWidget* overlayWidget; SoNodeSensor* cameraSensor; }; @@ -117,7 +113,7 @@ private: View3DInventorViewer* getViewer() const; void scaleImage(double); void startScale(); - void acceptScale(double val); + void acceptScale(); void rejectScale(); void restore(const Base::Placement&); diff --git a/src/Gui/TaskView/TaskImage.ui b/src/Gui/TaskView/TaskImage.ui index 6126d70a35..96eedc9eab 100644 --- a/src/Gui/TaskView/TaskImage.ui +++ b/src/Gui/TaskView/TaskImage.ui @@ -250,16 +250,23 @@ - Interactively scale the image + Interactively scale the image by setting a length between two points of the image. - Interactive + Calibrate QToolButton::MenuButtonPopup + + + + Apply + + + From 3be327d29e4e1ae6a52f1de26ccb3ba86f22935f Mon Sep 17 00:00:00 2001 From: Paddle Date: Wed, 12 Apr 2023 10:25:00 +0200 Subject: [PATCH 07/18] TaskImage: Fix Cancel on Esc and final ui adjustments. --- src/Gui/TaskView/TaskImage.cpp | 78 ++++++++++------ src/Gui/TaskView/TaskImage.h | 4 +- src/Gui/TaskView/TaskImage.ui | 158 +++++++++++++++------------------ 3 files changed, 127 insertions(+), 113 deletions(-) diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index b56e59de1f..ef84205011 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -70,8 +70,7 @@ TaskImage::TaskImage(Image::ImagePlane* obj, QWidget* parent) , aspectRatio(1.0) { ui->setupUi(this); - ui->pushButtonApply->hide(); - ui->pushButtonCancel->hide(); + ui->groupBoxCalibration->hide(); initialiseTransparency(); @@ -214,8 +213,8 @@ void TaskImage::startScale() { scale->activate(qAsConst(ui->pushButtonScale)->actions()[0]->isChecked()); ui->pushButtonScale->hide(); - ui->pushButtonApply->show(); - ui->pushButtonCancel->show(); + ui->groupBoxCalibration->show(); + ui->pushButtonApply->setEnabled(false); } void TaskImage::acceptScale() @@ -224,12 +223,16 @@ void TaskImage::acceptScale() rejectScale(); } +void TaskImage::enableApplyBtn() +{ + ui->pushButtonApply->setEnabled(true); +} + void TaskImage::rejectScale() { scale->deactivate(); ui->pushButtonScale->show(); - ui->pushButtonApply->hide(); - ui->pushButtonCancel->hide(); + ui->groupBoxCalibration->hide(); } void TaskImage::onInteractiveScale() @@ -244,6 +247,8 @@ void TaskImage::onInteractiveScale() this, &TaskImage::acceptScale); connect(scale, &InteractiveScale::scaleCanceled, this, &TaskImage::rejectScale); + connect(scale, &InteractiveScale::enableApplyBtn, + this, &TaskImage::enableApplyBtn); } } @@ -432,8 +437,6 @@ InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, distanceBox->setKeyboardTracking(false); distanceBox->installEventFilter(this); - this->installEventFilter(this); - //track camera movements to update spinbox position. NodeData* info = new NodeData{ this }; cameraSensor = new SoNodeSensor([](void* data, SoSensor* sensor) { @@ -457,7 +460,7 @@ void InteractiveScale::activate(bool allowOutside) static_cast(viewer->getSceneGraph())->addChild(root); viewer->setEditing(true); viewer->addEventCallback(SoLocation2Event::getClassTypeId(), InteractiveScale::getMousePosition, this); - viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), InteractiveScale::getMouseClick, this); + viewer->addEventCallback(SoButtonEvent::getClassTypeId(), InteractiveScale::soEventFilter, this); viewer->setSelectionEnabled(false); viewer->getWidget()->setCursor(QCursor(Qt::CrossCursor)); active = true; @@ -474,7 +477,7 @@ void InteractiveScale::deactivate() static_cast(viewer->getSceneGraph())->removeChild(root); viewer->setEditing(false); viewer->removeEventCallback(SoLocation2Event::getClassTypeId(), InteractiveScale::getMousePosition, this); - viewer->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), InteractiveScale::getMouseClick, this); + viewer->removeEventCallback(SoButtonEvent::getClassTypeId(), InteractiveScale::soEventFilter, this); viewer->setSelectionEnabled(true); viewer->getWidget()->setCursor(QCursor(Qt::ArrowCursor)); active = false; @@ -545,13 +548,15 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d) midPoint = points[0] + (points[1] - points[0]) / 2; measureLabel->string = ""; - positionWidget(); distanceBox->show(); - distanceBox->adjustSize(); QSignalBlocker block(distanceBox); distanceBox->setValue((points[1] - points[0]).length()); + distanceBox->adjustSize(); + positionWidget(); distanceBox->selectNumber(); distanceBox->setFocus(); + + Q_EMIT enableApplyBtn(); } else { Base::Console().Warning(std::string("Image scale"), "The second point is too close. Retry!\n"); @@ -568,17 +573,6 @@ void InteractiveScale::positionWidget() distanceBox->move(pxCoord); } -void InteractiveScale::getMouseClick(void * ud, SoEventCallback * ecb) -{ - InteractiveScale* scale = static_cast(ud); - const SoMouseButtonEvent * mbe = static_cast(ecb->getEvent()); - - if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) { - ecb->setHandled(); - scale->findPointOnPlane(ecb); - } -} - void InteractiveScale::getMousePosition(void * ud, SoEventCallback * ecb) { InteractiveScale* scale = static_cast(ud); @@ -621,9 +615,40 @@ void InteractiveScale::getMousePosition(void * ud, SoEventCallback * ecb) } } +void InteractiveScale::soEventFilter(void* ud, SoEventCallback* ecb) +{ + InteractiveScale* scale = static_cast(ud); + + const SoEvent* soEvent = ecb->getEvent(); + if (soEvent->isOfType(SoKeyboardEvent::getClassTypeId())) { + /* If user press escape, then we cancel the tool.*/ + const auto kbe = static_cast(soEvent); + + if (kbe->getKey() == SoKeyboardEvent::ESCAPE && kbe->getState() == SoButtonEvent::UP) { + ecb->setHandled(); + ecb->getAction()->setHandled(); + Q_EMIT scale->scaleCanceled(); + } + } + else if (soEvent->isOfType(SoMouseButtonEvent::getClassTypeId())) { + const auto mbe = static_cast(soEvent); + + if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) + { + ecb->setHandled(); + scale->findPointOnPlane(ecb); + } + if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::DOWN) + { + ecb->setHandled(); + Q_EMIT scale->scaleCanceled(); + } + } +} + bool InteractiveScale::eventFilter(QObject* object, QEvent* event) { - if (event->type() == QEvent::KeyRelease) { + if (event->type() == QEvent::KeyPress) { QKeyEvent* keyEvent = static_cast(event); /* If user press enter in the spinbox, then we validate the tool.*/ @@ -631,12 +656,11 @@ bool InteractiveScale::eventFilter(QObject* object, QEvent* event) Q_EMIT scaleRequired(); } - /* If user press escape, then we cancel the tool.*/ + /* If user press escape, then we cancel the tool. Required here as well for when checkbox has focus.*/ if (keyEvent->key() == Qt::Key_Escape) { Q_EMIT scaleCanceled(); } } - return false; } @@ -674,7 +698,7 @@ TaskImageDialog::TaskImageDialog(Image::ImagePlane* obj) { widget = new TaskImage(obj); Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox( - QPixmap(), widget->windowTitle(), true, nullptr); + Gui::BitmapFactory().pixmap("image-plane"), widget->windowTitle(), true, nullptr); taskbox->groupLayout()->addWidget(widget); Content.push_back(taskbox); } diff --git a/src/Gui/TaskView/TaskImage.h b/src/Gui/TaskView/TaskImage.h index aef78d8c8b..41ffc97b05 100644 --- a/src/Gui/TaskView/TaskImage.h +++ b/src/Gui/TaskView/TaskImage.h @@ -62,7 +62,7 @@ public: void setPlacement(Base::Placement plc); private: - static void getMouseClick(void * ud, SoEventCallback * ecb); + static void soEventFilter(void * ud, SoEventCallback * ecb); static void getMousePosition(void * ud, SoEventCallback * ecb); void findPointOnPlane(SoEventCallback * ecb); void findPointOnImagePlane(SoEventCallback * ecb); @@ -76,6 +76,7 @@ private: Q_SIGNALS: void scaleRequired(); void scaleCanceled(); + void enableApplyBtn(); private: bool active; @@ -115,6 +116,7 @@ private: void startScale(); void acceptScale(); void rejectScale(); + void enableApplyBtn(); void restore(const Base::Placement&); void onPreview(); diff --git a/src/Gui/TaskView/TaskImage.ui b/src/Gui/TaskView/TaskImage.ui index 96eedc9eab..346b2f6520 100644 --- a/src/Gui/TaskView/TaskImage.ui +++ b/src/Gui/TaskView/TaskImage.ui @@ -192,50 +192,46 @@ - - - - - Width: - - - - - - - mm - - - 0.00000001 - - - 999999999.000000000000000 - - - - - - - Height: - - - - - - - mm - - - 0.00000001 - - - 999999999.000000000000000 - - - - + + + Width: + + + + + + + mm + + + 0.00000001 + + + 999999999.000000000000000 + + + + + Height: + + + + + + + mm + + + 0.00000001 + + + 999999999.000000000000000 + + + + Keep aspect ratio @@ -245,49 +241,41 @@ - - - - - - Interactively scale the image by setting a length between two points of the image. - - - Calibrate - - - QToolButton::MenuButtonPopup - - - - - - - Apply - - - - - - - Cancel - - - - - - - Qt::Horizontal - - - - 136 - 20 - - - - - + + + + Interactively scale the image by setting a length between two points of the image. + + + Calibrate + + + QToolButton::MenuButtonPopup + + + + + + + Calibration + + + + + + Apply + + + + + + + Cancel + + + + + From 46a9d89e4be0088f59a7988b8fd5de615b240df1 Mon Sep 17 00:00:00 2001 From: Paddle Date: Wed, 12 Apr 2023 10:41:10 +0200 Subject: [PATCH 08/18] TaskImage: add missing headers --- src/Gui/TaskView/TaskImage.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index ef84205011..e3eb38b8ef 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -30,7 +30,9 @@ # include # include # include +# include # include +# include # include # include # include From a8f65156dbee446035c46d46b5e1148ce33b6974 Mon Sep 17 00:00:00 2001 From: Paddle Date: Wed, 12 Apr 2023 14:06:55 +0200 Subject: [PATCH 09/18] TaskImage: fix issues --- src/Gui/SoDatumLabel.cpp | 9 +++++++++ src/Gui/SoDatumLabel.h | 4 ++++ src/Gui/TaskView/TaskImage.cpp | 10 ++++------ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/Gui/SoDatumLabel.cpp b/src/Gui/SoDatumLabel.cpp index 05d005880a..a2cde08acd 100644 --- a/src/Gui/SoDatumLabel.cpp +++ b/src/Gui/SoDatumLabel.cpp @@ -1021,3 +1021,12 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action) glPopAttrib(); state->pop(); } + +void SoDatumLabel::setPoints(SbVec3f p1, SbVec3f p2) +{ + pnts.setNum(2); + SbVec3f* verts = pnts.startEditing(); + verts[0] = p1; + verts[1] = p2; + pnts.finishEditing(); +} \ No newline at end of file diff --git a/src/Gui/SoDatumLabel.h b/src/Gui/SoDatumLabel.h index f4eb5685d3..183076ec0d 100644 --- a/src/Gui/SoDatumLabel.h +++ b/src/Gui/SoDatumLabel.h @@ -60,6 +60,10 @@ public: static void initClass(); SoDatumLabel(); + /*The points have to be on XY plane, ie they need to be 2D points. + To draw on other planes, you need to attach a SoTransform to the SoDatumLabel (or parent).*/ + void setPoints(SbVec3f p1, SbVec3f p2); + SoMFString string; SoSFColor textColor; SoSFEnum datumtype; diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index e3eb38b8ef..4ee5236c3f 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -540,6 +540,7 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d) if (points.empty()) { points.push_back(pos3d); + measureLabel->setPoints(getCoordsOnImagePlane(pos3d), getCoordsOnImagePlane(pos3d)); root->addChild(measureLabel); } else if (points.size() == 1) { @@ -608,12 +609,7 @@ void InteractiveScale::getMousePosition(void * ud, SoEventCallback * ecb) valueStr = quantity.getUserString(factor, unitStr); scale->measureLabel->string = SbString(valueStr.toUtf8().constData()); - //Update the SoDatumLabel. It needs 2D points! - scale->measureLabel->pnts.setNum(2); - SbVec3f* verts = scale->measureLabel->pnts.startEditing(); - verts[0] = scale->getCoordsOnImagePlane(scale->points[0]); - verts[1] = scale->getCoordsOnImagePlane(pos3d); - scale->measureLabel->pnts.finishEditing(); + scale->measureLabel->setPoints(scale->getCoordsOnImagePlane(scale->points[0]), scale->getCoordsOnImagePlane(pos3d)); } } @@ -672,6 +668,8 @@ void InteractiveScale::setPlacement(Base::Placement plc) double x, y, z, w; placement.getRotation().getValue(x, y, z, w); transform->rotation.setValue(x, y, z, w); + Base::Vector3d pos = placement.getPosition(); + transform->translation.setValue(pos.x, pos.y, pos.z); Base::Vector3d RN(0, 0, 1); RN = placement.getRotation().multVec(RN); From c9c9920531861b8341c63b2a3ae92464bf9001fc Mon Sep 17 00:00:00 2001 From: Paddle Date: Wed, 12 Apr 2023 15:55:45 +0200 Subject: [PATCH 10/18] TaskImage: Fix enter doesn't work. --- src/Gui/TaskView/TaskImage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index 4ee5236c3f..88d569d9eb 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -646,7 +646,7 @@ void InteractiveScale::soEventFilter(void* ud, SoEventCallback* ecb) bool InteractiveScale::eventFilter(QObject* object, QEvent* event) { - if (event->type() == QEvent::KeyPress) { + if (event->type() == QEvent::KeyRelease) { QKeyEvent* keyEvent = static_cast(event); /* If user press enter in the spinbox, then we validate the tool.*/ From c90dc541cdfdbe62419bc283066efd746e8be1b5 Mon Sep 17 00:00:00 2001 From: Paddle Date: Wed, 12 Apr 2023 17:49:18 +0200 Subject: [PATCH 11/18] TaskImage: fix X,Y distance that were reversed on XZ and ZY. --- src/Gui/TaskView/TaskImage.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index 88d569d9eb..15125a58c4 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -323,7 +323,7 @@ void TaskImage::restore(const Base::Placement& plm) reverse = true; int inv = reverse ? -1 : 1; ui->XZ_radioButton->setChecked(true); - ui->spinBoxX->setValue(- inv * pos.x); + ui->spinBoxX->setValue(inv * pos.x); ui->spinBoxY->setValue(pos.z); ui->spinBoxZ->setValue(inv * pos.y); ui->spinBoxRotation->setValue(- pitch); @@ -333,7 +333,7 @@ void TaskImage::restore(const Base::Placement& plm) reverse = true; int inv = reverse ? -1 : 1; ui->YZ_radioButton->setChecked(true); - ui->spinBoxX->setValue(-inv * pos.y); + ui->spinBoxX->setValue(inv * pos.y); ui->spinBoxY->setValue(pos.z); ui->spinBoxZ->setValue(inv * pos.x); ui->spinBoxRotation->setValue(-pitch); @@ -363,11 +363,11 @@ void TaskImage::updatePlacement() } else if (ui->XZ_radioButton->isChecked()) { rot.setYawPitchRoll(dir, -angle, 90.); - Pos = Base::Placement(Base::Vector3d(- inv * offsetX, inv * offsetZ, offsetY), rot); + Pos = Base::Placement(Base::Vector3d(inv * offsetX, inv * offsetZ, offsetY), rot); } else if (ui->YZ_radioButton->isChecked()) { rot.setYawPitchRoll(90. - dir, -angle, 90.); - Pos = Base::Placement(Base::Vector3d(inv * offsetZ, - inv * offsetX, offsetY), rot); + Pos = Base::Placement(Base::Vector3d(inv * offsetZ, inv * offsetX, offsetY), rot); } if (!feature.expired()) { From 08d87644a9d677726e48efc5eb7bfb51102416e8 Mon Sep 17 00:00:00 2001 From: Paddle Date: Wed, 12 Apr 2023 17:49:54 +0200 Subject: [PATCH 12/18] Task image. replace {} with () in the ctor for consistency --- src/Gui/TaskView/TaskImage.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index 15125a58c4..1a80089090 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -404,12 +404,12 @@ struct NodeData { }; InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, Base::Placement plc) - : active{false} - , allowOutsideImage{false} - , placement{plc} - , viewer{view} - , viewProv{vp} - , midPoint{SbVec3f(0,0,0)} + : active(false) + , allowOutsideImage(false) + , placement(plc) + , viewer(view) + , viewProv(vp) + , midPoint(SbVec3f(0,0,0)) { root = new SoAnnotation; root->ref(); From 6487c748e654c0dc168da041fd952148934c252e Mon Sep 17 00:00:00 2001 From: Paddle Date: Wed, 12 Apr 2023 17:50:42 +0200 Subject: [PATCH 13/18] TaskImage : fix X Y distances that were not taken into account for SoDatumLabel transform. --- src/Gui/TaskView/TaskImage.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index 1a80089090..c6547186c0 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -679,15 +679,16 @@ void InteractiveScale::setPlacement(Base::Placement plc) SbVec3f InteractiveScale::getCoordsOnImagePlane(const SbVec3f& point) { // Plane form - Base::Vector3d R0(0, 0, 0), RX(1, 0, 0), RY(0, 1, 0); + Base::Vector3d RX(1, 0, 0), RY(0, 1, 0); // move to position of Sketch Base::Rotation tmp(placement.getRotation()); RX = tmp.multVec(RX); RY = tmp.multVec(RY); + Base::Vector3d pos = placement.getPosition(); Base::Vector3d S(point[0], point[1], point[2]); - S.TransformToCoordinateSystem(R0, RX, RY); + S.TransformToCoordinateSystem(pos, RX, RY); return SbVec3f(S.x, S.y, 0.); } From e168be33971772cc232d233c1f1a62ab11f80667 Mon Sep 17 00:00:00 2001 From: Paddle Date: Wed, 12 Apr 2023 17:50:59 +0200 Subject: [PATCH 14/18] TaskImage: try to fix bug when in Part container. --- src/Gui/TaskView/TaskImage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index c6547186c0..1533fdd092 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -373,7 +373,7 @@ void TaskImage::updatePlacement() if (!feature.expired()) { feature->Placement.setValue(Pos); if(scale) - scale->setPlacement(Pos); + scale->setPlacement(feature->globalPlacement()); } } From b10a7a65db30cc13a820499257e368ceb7b45b49 Mon Sep 17 00:00:00 2001 From: Paddle Date: Wed, 12 Apr 2023 18:23:35 +0200 Subject: [PATCH 15/18] TaskImage: finish fixing when imageplane is in transformed part. --- src/Gui/TaskView/TaskImage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index 1533fdd092..1a83c3e2fa 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -243,8 +243,7 @@ void TaskImage::onInteractiveScale() View3DInventorViewer* viewer = getViewer(); if (viewer) { auto vp = Application::Instance->getViewProvider(feature.get()); - Base::Placement placement = feature->Placement.getValue(); - scale = new InteractiveScale(viewer, vp, placement); + scale = new InteractiveScale(viewer, vp, feature->globalPlacement()); connect(scale, &InteractiveScale::scaleRequired, this, &TaskImage::acceptScale); connect(scale, &InteractiveScale::scaleCanceled, @@ -687,6 +686,7 @@ SbVec3f InteractiveScale::getCoordsOnImagePlane(const SbVec3f& point) RY = tmp.multVec(RY); Base::Vector3d pos = placement.getPosition(); + //we use pos as the Base because in setPlacement we set transform->translation using placement.getPosition() to fix the Zoffset. But this applies the X & Y translation too. Base::Vector3d S(point[0], point[1], point[2]); S.TransformToCoordinateSystem(pos, RX, RY); From 7b3069868d64564649f88315baeec10629b35578 Mon Sep 17 00:00:00 2001 From: Paddle Date: Wed, 12 Apr 2023 18:52:04 +0200 Subject: [PATCH 16/18] TaskImage: Simplify restore & updatePlacement. It will make it easier if we want to enable other planes than XY XZ ZY. --- src/Gui/TaskView/TaskImage.cpp | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index 1a83c3e2fa..a9dbc9af8e 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -312,9 +312,6 @@ void TaskImage::restore(const Base::Placement& plm) reverse = true; int inv = reverse ? -1 : 1; ui->XY_radioButton->setChecked(true); - ui->spinBoxX->setValue(pos.x); - ui->spinBoxY->setValue(pos.y * inv); - ui->spinBoxZ->setValue(pos.z * inv); ui->spinBoxRotation->setValue(yaw * inv); } else if (fabs(roll - 90.) < tol && (fabs(yaw) < tol || fabs(yaw - 180.) < tol)) { @@ -322,9 +319,6 @@ void TaskImage::restore(const Base::Placement& plm) reverse = true; int inv = reverse ? -1 : 1; ui->XZ_radioButton->setChecked(true); - ui->spinBoxX->setValue(inv * pos.x); - ui->spinBoxY->setValue(pos.z); - ui->spinBoxZ->setValue(inv * pos.y); ui->spinBoxRotation->setValue(- pitch); } else if (fabs(roll - 90.) < tol && (fabs(yaw - 90.) < tol || fabs(yaw + 90.) < tol)) { @@ -332,43 +326,46 @@ void TaskImage::restore(const Base::Placement& plm) reverse = true; int inv = reverse ? -1 : 1; ui->YZ_radioButton->setChecked(true); - ui->spinBoxX->setValue(inv * pos.y); - ui->spinBoxY->setValue(pos.z); - ui->spinBoxZ->setValue(inv * pos.x); ui->spinBoxRotation->setValue(-pitch); } - ui->Reverse_checkBox->setChecked(reverse); + Base::Vector3d R0(0, 0, 0), RX(1, 0, 0), RY(0, 1, 0); + + RX = rot.multVec(RX); + RY = rot.multVec(RY); + pos.TransformToCoordinateSystem(R0, RX, RY); + ui->spinBoxX->setValue(pos.x); + ui->spinBoxY->setValue(pos.y); + ui->spinBoxZ->setValue(pos.z); + onPreview(); } void TaskImage::updatePlacement() { - Base::Placement Pos; - double offsetX = ui->spinBoxX->value().getValue(); - double offsetY = ui->spinBoxY->value().getValue(); - double offsetZ = ui->spinBoxZ->value().getValue(); double angle = ui->spinBoxRotation->value().getValue(); bool reverse = ui->Reverse_checkBox->isChecked(); + Base::Placement Pos; Base::Rotation rot; double dir = reverse ? 180. : 0.; int inv = reverse ? -1 : 1; if (ui->XY_radioButton->isChecked()) { rot.setYawPitchRoll(inv * angle, 0., dir); - Pos = Base::Placement(Base::Vector3d(offsetX, inv * offsetY, inv * offsetZ), rot); } else if (ui->XZ_radioButton->isChecked()) { rot.setYawPitchRoll(dir, -angle, 90.); - Pos = Base::Placement(Base::Vector3d(inv * offsetX, inv * offsetZ, offsetY), rot); } else if (ui->YZ_radioButton->isChecked()) { rot.setYawPitchRoll(90. - dir, -angle, 90.); - Pos = Base::Placement(Base::Vector3d(inv * offsetZ, inv * offsetX, offsetY), rot); } + Base::Vector3d offset = Base::Vector3d(ui->spinBoxX->value().getValue(), ui->spinBoxY->value().getValue(), ui->spinBoxZ->value().getValue()); + offset = rot.multVec(offset); + Pos = Base::Placement(offset, rot); + if (!feature.expired()) { feature->Placement.setValue(Pos); if(scale) From ba1ed196437e1c9835ac5ce60a3eecd3367a5568 Mon Sep 17 00:00:00 2001 From: Paddle Date: Mon, 17 Apr 2023 15:10:13 +0200 Subject: [PATCH 17/18] TaskImage: Remove 'outside picture' mode. --- src/Gui/TaskView/TaskImage.cpp | 49 ++++++---------------------------- src/Gui/TaskView/TaskImage.h | 5 +--- src/Gui/TaskView/TaskImage.ui | 5 +--- 3 files changed, 10 insertions(+), 49 deletions(-) diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index a9dbc9af8e..5fb8cf1448 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -78,11 +78,6 @@ TaskImage::TaskImage(Image::ImagePlane* obj, QWidget* parent) aspectRatio = obj->XSize.getValue() / obj->YSize.getValue(); - QAction* action = new QAction(tr("Allow points outside the image"), this); - action->setCheckable(true); - action->setChecked(false); - ui->pushButtonScale->addAction(action); - connectSignals(); } @@ -213,7 +208,7 @@ void TaskImage::scaleImage(double factor) void TaskImage::startScale() { - scale->activate(qAsConst(ui->pushButtonScale)->actions()[0]->isChecked()); + scale->activate(); ui->pushButtonScale->hide(); ui->groupBoxCalibration->show(); ui->pushButtonApply->setEnabled(false); @@ -401,7 +396,6 @@ struct NodeData { InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, Base::Placement plc) : active(false) - , allowOutsideImage(false) , placement(plc) , viewer(view) , viewProv(vp) @@ -452,7 +446,7 @@ InteractiveScale::~InteractiveScale() cameraSensor->detach(); } -void InteractiveScale::activate(bool allowOutside) +void InteractiveScale::activate() { if (viewer) { static_cast(viewer->getSceneGraph())->addChild(root); @@ -462,7 +456,6 @@ void InteractiveScale::activate(bool allowOutside) viewer->setSelectionEnabled(false); viewer->getWidget()->setCursor(QCursor(Qt::CrossCursor)); active = true; - allowOutsideImage = allowOutside; } } @@ -498,16 +491,6 @@ double InteractiveScale::getDistance(const SbVec3f& pt) const return (points[0] - pt).length(); } -void InteractiveScale::findPointOnPlane(SoEventCallback * ecb) -{ - if (allowOutsideImage) { - findPointOnFocalPlane(ecb); - } - else { - findPointOnImagePlane(ecb); - } -} - void InteractiveScale::findPointOnImagePlane(SoEventCallback * ecb) { const SoMouseButtonEvent * mbe = static_cast(ecb->getEvent()); @@ -520,17 +503,6 @@ void InteractiveScale::findPointOnImagePlane(SoEventCallback * ecb) } } -void InteractiveScale::findPointOnFocalPlane(SoEventCallback * ecb) -{ - const SoMouseButtonEvent * mbe = static_cast(ecb->getEvent()); - Gui::View3DInventorViewer* view = static_cast(ecb->getUserData()); - - auto pos2d = mbe->getPosition(); - auto pos3d = view->getPointOnFocalPlane(pos2d); - - collectPoint(pos3d); -} - void InteractiveScale::collectPoint(const SbVec3f& pos3d) { if (points.empty()) { @@ -581,18 +553,13 @@ void InteractiveScale::getMousePosition(void * ud, SoEventCallback * ecb) if (scale->points.size() == 1) { ecb->setHandled(); SbVec3f pos3d; - if (scale->allowOutsideImage) { - auto pos2d = l2e->getPosition(); - pos3d = view->getPointOnFocalPlane(pos2d); + + std::unique_ptr pp(view->getPointOnRay(l2e->getPosition(), scale->viewProv)); + if (pp.get()) { + pos3d = pp->getPoint(); } else { - std::unique_ptr pp(view->getPointOnRay(l2e->getPosition(), scale->viewProv)); - if (pp.get()) { - pos3d = pp->getPoint(); - } - else { - return; - } + return; } Base::Quantity quantity; @@ -630,7 +597,7 @@ void InteractiveScale::soEventFilter(void* ud, SoEventCallback* ecb) if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) { ecb->setHandled(); - scale->findPointOnPlane(ecb); + scale->findPointOnImagePlane(ecb); } if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::DOWN) { diff --git a/src/Gui/TaskView/TaskImage.h b/src/Gui/TaskView/TaskImage.h index 41ffc97b05..5d2d0e5bed 100644 --- a/src/Gui/TaskView/TaskImage.h +++ b/src/Gui/TaskView/TaskImage.h @@ -52,7 +52,7 @@ public: ~InteractiveScale(); bool eventFilter(QObject* object, QEvent* event); - void activate(bool allowOutside); + void activate(); void deactivate(); bool isActive() const { return active; @@ -64,9 +64,7 @@ public: private: static void soEventFilter(void * ud, SoEventCallback * ecb); static void getMousePosition(void * ud, SoEventCallback * ecb); - void findPointOnPlane(SoEventCallback * ecb); void findPointOnImagePlane(SoEventCallback * ecb); - void findPointOnFocalPlane(SoEventCallback * ecb); void collectPoint(const SbVec3f&); void positionWidget(); @@ -80,7 +78,6 @@ Q_SIGNALS: private: bool active; - bool allowOutsideImage; Base::Placement placement; SoSeparator* root; SoDatumLabel* measureLabel; diff --git a/src/Gui/TaskView/TaskImage.ui b/src/Gui/TaskView/TaskImage.ui index 346b2f6520..589d949f81 100644 --- a/src/Gui/TaskView/TaskImage.ui +++ b/src/Gui/TaskView/TaskImage.ui @@ -242,16 +242,13 @@ - + Interactively scale the image by setting a length between two points of the image. Calibrate - - QToolButton::MenuButtonPopup - From b3e1d3dc6a96bea07fed2445a824ac26f7dd69dc Mon Sep 17 00:00:00 2001 From: Paddle Date: Mon, 17 Apr 2023 16:03:11 +0200 Subject: [PATCH 18/18] TaskImage: Fix segfault when doc closed before taskview is dismissed. --- src/Gui/TaskView/TaskImage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index 5fb8cf1448..e99972864e 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -83,7 +83,7 @@ TaskImage::TaskImage(Image::ImagePlane* obj, QWidget* parent) TaskImage::~TaskImage() { - if (scale) { + if (!feature.expired() && scale) { if (scale->isActive()) { scale->deactivate(); }