| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include <QDialog> |
| | #include <QPushButton> |
| | #include <QAction> |
| | #include <QKeyEvent> |
| | #include <map> |
| | #include <Inventor/SoPickedPoint.h> |
| | #include <Inventor/events/SoLocation2Event.h> |
| | #include <Inventor/events/SoButtonEvent.h> |
| | #include <Inventor/events/SoMouseButtonEvent.h> |
| | #include <Inventor/events/SoKeyboardEvent.h> |
| |
|
| | #include <Base/Console.h> |
| | #include <Base/Precision.h> |
| | #include <Base/Quantity.h> |
| | #include <Base/Tools.h> |
| | #include <App/Document.h> |
| | #include <Gui/Application.h> |
| | #include <Gui/BitmapFactory.h> |
| | #include <Gui/Camera.h> |
| | #include <Gui/Document.h> |
| | #include <Gui/EditableDatumLabel.h> |
| | #include <Gui/View3DInventor.h> |
| | #include <Gui/View3DInventorViewer.h> |
| | #include <Gui/ViewProviderDocumentObject.h> |
| | #include <Gui/TaskView/TaskView.h> |
| |
|
| | #include "TaskImage.h" |
| | #include "ui_TaskImage.h" |
| |
|
| |
|
| | using namespace Gui; |
| |
|
| | |
| |
|
| | TaskImage::TaskImage(Image::ImagePlane* obj, QWidget* parent) |
| | : QWidget(parent) |
| | , ui(new Ui_TaskImage) |
| | , feature(obj) |
| | , aspectRatio(1.0) |
| | { |
| | ui->setupUi(this); |
| | ui->groupBoxCalibration->hide(); |
| |
|
| | initialiseTransparency(); |
| |
|
| | |
| | aspectRatio = obj->XSize.getValue() / obj->YSize.getValue(); |
| |
|
| | connectSignals(); |
| | } |
| |
|
| | TaskImage::~TaskImage() |
| | { |
| | if (!feature.expired() && scale) { |
| | if (scale->isActive()) { |
| | scale->deactivate(); |
| | } |
| | scale->deleteLater(); |
| | } |
| | } |
| |
|
| | 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<double>(&QuantitySpinBox::valueChanged), |
| | this, &TaskImage::onPreview); |
| | connect(ui->spinBoxX, qOverload<double>(&QuantitySpinBox::valueChanged), |
| | this, &TaskImage::onPreview); |
| | connect(ui->spinBoxY, qOverload<double>(&QuantitySpinBox::valueChanged), |
| | this, &TaskImage::onPreview); |
| | connect(ui->spinBoxRotation, qOverload<double>(&QuantitySpinBox::valueChanged), |
| | this, &TaskImage::onPreview); |
| | connect(ui->spinBoxTransparency, qOverload<int>(&QSpinBox::valueChanged), |
| | this, &TaskImage::changeTransparency); |
| | connect(ui->sliderTransparency, qOverload<int>(&QSlider::valueChanged), |
| | this, &TaskImage::changeTransparency); |
| |
|
| | connect(ui->spinBoxWidth, &QuantitySpinBox::editingFinished, |
| | this, &TaskImage::changeWidth); |
| | connect(ui->spinBoxHeight, &QuantitySpinBox::editingFinished, |
| | 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); |
| | |
| | } |
| |
|
| | void TaskImage::initialiseTransparency() |
| | { |
| | |
| | auto vp = Application::Instance->getViewProvider(feature.get()); |
| | App::Property* prop = vp->getPropertyByName("Transparency"); |
| | if (prop && prop->isDerivedFrom<App::PropertyInteger>()) { |
| | auto Transparency = static_cast<App::PropertyInteger*>(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 (auto Transparency = dynamic_cast<App::PropertyInteger*>(prop)) { |
| | Transparency->setValue(val); |
| |
|
| | QSignalBlocker block(ui->spinBoxTransparency); |
| | QSignalBlocker blocks(ui->sliderTransparency); |
| | ui->spinBoxTransparency->setValue(val); |
| | ui->sliderTransparency->setValue(val); |
| | } |
| | } |
| |
|
| | void TaskImage::changeWidth() |
| | { |
| | if (!feature.expired()) { |
| | double val = ui->spinBoxWidth->value().getValue(); |
| | feature->XSize.setValue(val); |
| |
|
| | if (ui->checkBoxRatio->isChecked()) { |
| | feature->YSize.setValue(val / aspectRatio); |
| | QSignalBlocker block(ui->spinBoxHeight); |
| | ui->spinBoxHeight->setValue(val / aspectRatio); |
| | } |
| | } |
| | } |
| |
|
| | void TaskImage::changeHeight() |
| | { |
| | if (!feature.expired()) { |
| | double val = ui->spinBoxHeight->value().getValue(); |
| | feature->YSize.setValue(val); |
| |
|
| | if (ui->checkBoxRatio->isChecked()) { |
| | feature->XSize.setValue(val * aspectRatio); |
| | QSignalBlocker block(ui->spinBoxWidth); |
| | ui->spinBoxWidth->setValue(val * aspectRatio); |
| | } |
| | } |
| | } |
| |
|
| | View3DInventorViewer* TaskImage::getViewer() const |
| | { |
| | if (!feature.expired()) { |
| | auto vp = Application::Instance->getViewProvider(feature.get()); |
| | auto doc = static_cast<ViewProviderDocumentObject*>(vp)->getDocument(); |
| | auto view = qobject_cast<View3DInventor*>(doc->getViewOfViewProvider(vp)); |
| | if (view) { |
| | return view->getViewer(); |
| | } |
| | } |
| |
|
| | return nullptr; |
| | } |
| |
|
| | 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->XSize.getValue()); |
| | QSignalBlocker blockH(ui->spinBoxHeight); |
| | ui->spinBoxHeight->setValue(feature->YSize.getValue()); |
| | } |
| | } |
| |
|
| | void TaskImage::startScale() |
| | { |
| | if (scale) { |
| | scale->activate(); |
| | ui->pushButtonScale->hide(); |
| | ui->groupBoxCalibration->show(); |
| | ui->pushButtonApply->setEnabled(false); |
| | } |
| | } |
| |
|
| | void TaskImage::acceptScale() |
| | { |
| | if (scale) { |
| | scaleImage(scale->getScaleFactor()); |
| | rejectScale(); |
| | } |
| | } |
| |
|
| | void TaskImage::enableApplyBtn() |
| | { |
| | ui->pushButtonApply->setEnabled(true); |
| | } |
| |
|
| | void TaskImage::rejectScale() |
| | { |
| | if (scale) { |
| | scale->deactivate(); |
| | ui->pushButtonScale->show(); |
| | ui->groupBoxCalibration->hide(); |
| | } |
| | } |
| |
|
| | void TaskImage::onInteractiveScale() |
| | { |
| | if (!feature.expired() && !scale) { |
| | View3DInventorViewer* viewer = getViewer(); |
| | if (viewer) { |
| | auto vp = Application::Instance->getViewProvider(feature.get()); |
| | scale = new InteractiveScale(viewer, vp, feature->globalPlacement()); |
| | connect(scale, &InteractiveScale::scaleRequired, this, &TaskImage::acceptScale); |
| | connect(scale, &InteractiveScale::scaleCanceled, this, &TaskImage::rejectScale); |
| | connect(scale, &InteractiveScale::enableApplyBtn, this, &TaskImage::enableApplyBtn); |
| | } |
| | } |
| |
|
| | startScale(); |
| | } |
| |
|
| | 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::restoreAngles(const Base::Rotation& rot) |
| | { |
| | Base::Vector3d vec(0, 0, 1); |
| | rot.multVec(vec, vec); |
| |
|
| | double yaw {}; |
| | double pitch {}; |
| | double roll {}; |
| | rot.getYawPitchRoll(yaw, pitch, roll); |
| |
|
| | bool reverse = false; |
| |
|
| | const double tol = 1.0e-5; |
| | const double angle1 = 90.0; |
| | const double angle2 = 180.0; |
| |
|
| | auto isTopOrBottom = [=](bool& reverse) { |
| | if (std::fabs(vec.z - 1.0) < tol) { |
| | return true; |
| | } |
| | if (std::fabs(vec.z + 1.0) < tol) { |
| | reverse = true; |
| | return true; |
| | } |
| |
|
| | return false; |
| | }; |
| |
|
| | auto isFrontOrRear = [&](bool& reverse) { |
| | if (std::fabs(vec.y + 1.0) < tol) { |
| | if (std::fabs(yaw - angle2) < tol) { |
| | pitch = -angle2 - pitch; |
| | } |
| | return true; |
| | } |
| | if (std::fabs(vec.y - 1.0) < tol) { |
| | if (std::fabs(yaw) < tol) { |
| | pitch = -angle2 - pitch; |
| | } |
| | reverse = true; |
| | return true; |
| | } |
| |
|
| | return false; |
| | }; |
| |
|
| | auto isRightOrLeft = [&](bool& reverse) { |
| | if (std::fabs(vec.x - 1.0) < tol) { |
| | if (std::fabs(yaw + angle1) < tol) { |
| | pitch = -angle2 - pitch; |
| | } |
| | return true; |
| | } |
| | if (std::fabs(vec.x + 1.0) < tol) { |
| | if (std::fabs(yaw - angle1) < tol) { |
| | pitch = -angle2 - pitch; |
| | } |
| | reverse = true; |
| | return true; |
| | } |
| |
|
| | return false; |
| | }; |
| |
|
| | if (isTopOrBottom(reverse)) { |
| | int inv = reverse ? -1 : 1; |
| | ui->XY_radioButton->setChecked(true); |
| | ui->spinBoxRotation->setValue(yaw * inv); |
| | } |
| | else if (isFrontOrRear(reverse)) { |
| | ui->XZ_radioButton->setChecked(true); |
| | ui->spinBoxRotation->setValue(-pitch); |
| | } |
| | else if (isRightOrLeft(reverse)) { |
| | ui->YZ_radioButton->setChecked(true); |
| | ui->spinBoxRotation->setValue(-pitch); |
| | } |
| | ui->Reverse_checkBox->setChecked(reverse); |
| | } |
| |
|
| | 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(); |
| |
|
| | restoreAngles(rot); |
| |
|
| | Base::Vector3d R0(0, 0, 0); |
| | Base::Vector3d RX(1, 0, 0); |
| | Base::Vector3d 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() |
| | { |
| | 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); |
| | } |
| | else if (ui->XZ_radioButton->isChecked()) { |
| | rot.setYawPitchRoll(dir, -angle, 90.); |
| | } |
| | else if (ui->YZ_radioButton->isChecked()) { |
| | rot.setYawPitchRoll(90. - dir, -angle, 90.); |
| | } |
| | else if (!feature.expired()) { |
| | Base::Placement plm = feature->Placement.getValue(); |
| | rot = plm.getRotation(); |
| | } |
| | |
| |
|
| | 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) { |
| | scale->setPlacement(feature->globalPlacement()); |
| | } |
| | } |
| | } |
| |
|
| | 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, |
| | const Base::Placement& plc |
| | ) |
| | : active(false) |
| | , placement(plc) |
| | , viewer(view) |
| | , viewProv(vp) |
| | , midPoint(SbVec3f(0, 0, 0)) |
| | { |
| | measureLabel = new EditableDatumLabel(viewer, placement, SbColor(1.0F, 0.149F, 0.0F)); |
| | } |
| |
|
| | InteractiveScale::~InteractiveScale() |
| | { |
| | delete measureLabel; |
| | } |
| |
|
| | void InteractiveScale::activate() |
| | { |
| | if (viewer) { |
| | viewer->setEditing(true); |
| | viewer->addEventCallback( |
| | SoLocation2Event::getClassTypeId(), |
| | InteractiveScale::getMousePosition, |
| | this |
| | ); |
| | viewer->addEventCallback(SoButtonEvent::getClassTypeId(), InteractiveScale::soEventFilter, this); |
| | viewer->setSelectionEnabled(false); |
| | viewer->getWidget()->setCursor(QCursor(Qt::CrossCursor)); |
| | active = true; |
| | } |
| | } |
| |
|
| | void InteractiveScale::deactivate() |
| | { |
| | if (viewer) { |
| | points.clear(); |
| | measureLabel->deactivate(); |
| | viewer->setEditing(false); |
| | viewer->removeEventCallback( |
| | SoLocation2Event::getClassTypeId(), |
| | InteractiveScale::getMousePosition, |
| | this |
| | ); |
| | viewer->removeEventCallback( |
| | SoButtonEvent::getClassTypeId(), |
| | InteractiveScale::soEventFilter, |
| | this |
| | ); |
| | viewer->setSelectionEnabled(true); |
| | viewer->getWidget()->setCursor(QCursor(Qt::ArrowCursor)); |
| | active = false; |
| | } |
| | } |
| |
|
| | double InteractiveScale::getScaleFactor() const |
| | { |
| | if ((points[0] - points[1]).length() == 0.) { |
| | return 1.0; |
| | } |
| |
|
| | return measureLabel->getValue() / (points[0] - points[1]).length(); |
| | } |
| |
|
| | double InteractiveScale::getDistance(const SbVec3f& pt) const |
| | { |
| | if (points.empty()) { |
| | return 0.0; |
| | } |
| |
|
| | return (points[0] - pt).length(); |
| | } |
| |
|
| | void InteractiveScale::setDistance(const SbVec3f& pos3d) |
| | { |
| | Base::Quantity quantity; |
| | quantity.setValue(getDistance(pos3d)); |
| | quantity.setUnit(Base::Unit::Length); |
| |
|
| | |
| | double factor {}; |
| | std::string unitStr; |
| | std::string valueStr; |
| | valueStr = quantity.getUserString(factor, unitStr); |
| | measureLabel->label->string = SbString(valueStr.c_str()); |
| | measureLabel->label->setPoints(getCoordsOnImagePlane(points[0]), getCoordsOnImagePlane(pos3d)); |
| | } |
| |
|
| | void InteractiveScale::findPointOnImagePlane(SoEventCallback* ecb) |
| | { |
| | const SoEvent* mbe = ecb->getEvent(); |
| | auto view = static_cast<Gui::View3DInventorViewer*>(ecb->getUserData()); |
| | std::unique_ptr<SoPickedPoint> pp(view->getPointOnRay(mbe->getPosition(), viewProv)); |
| | if (pp) { |
| | auto pos3d = pp->getPoint(); |
| |
|
| | collectPoint(pos3d); |
| | } |
| | } |
| |
|
| | void InteractiveScale::collectPoint(const SbVec3f& pos3d) |
| | { |
| | if (points.empty()) { |
| | points.push_back(pos3d); |
| |
|
| | measureLabel->label->setPoints(getCoordsOnImagePlane(pos3d), getCoordsOnImagePlane(pos3d)); |
| | measureLabel->activate(); |
| | } |
| | else if (points.size() == 1) { |
| | double distance = getDistance(pos3d); |
| | if (distance > Base::Precision::Confusion()) { |
| | points.push_back(pos3d); |
| |
|
| | midPoint = (points[0] + points[1]) / 2; |
| |
|
| | measureLabel->startEdit(getDistance(points[1]), this, true); |
| |
|
| | Q_EMIT enableApplyBtn(); |
| | } |
| | else { |
| | Base::Console().warning( |
| | std::string("Image scale"), |
| | "The second point is too close. Retry!\n" |
| | ); |
| | } |
| | } |
| | } |
| |
|
| | void InteractiveScale::getMousePosition(void* ud, SoEventCallback* ecb) |
| | { |
| | auto scale = static_cast<InteractiveScale*>(ud); |
| | const SoEvent* l2e = ecb->getEvent(); |
| | auto view = static_cast<Gui::View3DInventorViewer*>(ecb->getUserData()); |
| |
|
| | if (scale->points.size() == 1) { |
| | ecb->setHandled(); |
| |
|
| | std::unique_ptr<SoPickedPoint> pp(view->getPointOnRay(l2e->getPosition(), scale->viewProv)); |
| | if (pp) { |
| | SbVec3f pos3d = pp->getPoint(); |
| | scale->setDistance(pos3d); |
| | } |
| | } |
| | } |
| |
|
| | void InteractiveScale::soEventFilter(void* ud, SoEventCallback* ecb) |
| | { |
| | auto scale = static_cast<InteractiveScale*>(ud); |
| |
|
| | const SoEvent* soEvent = ecb->getEvent(); |
| | if (soEvent->isOfType(SoKeyboardEvent::getClassTypeId())) { |
| | |
| | const auto kbe = static_cast<const SoKeyboardEvent*>(soEvent); |
| |
|
| | if (kbe->getKey() == SoKeyboardEvent::ESCAPE && kbe->getState() == SoButtonEvent::UP) { |
| | ecb->setHandled(); |
| | Q_EMIT scale->scaleCanceled(); |
| | } |
| | } |
| | else if (soEvent->isOfType(SoMouseButtonEvent::getClassTypeId())) { |
| | const auto mbe = static_cast<const SoMouseButtonEvent*>(soEvent); |
| |
|
| | if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 |
| | && mbe->getState() == SoButtonEvent::DOWN) { |
| | ecb->setHandled(); |
| | scale->findPointOnImagePlane(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) { |
| | auto keyEvent = static_cast<QKeyEvent*>(event); |
| |
|
| | |
| | if ((keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) |
| | && qobject_cast<QuantitySpinBox*>(object)) { |
| | Q_EMIT scaleRequired(); |
| | } |
| |
|
| | |
| | |
| | if (keyEvent->key() == Qt::Key_Escape) { |
| | Q_EMIT scaleCanceled(); |
| | } |
| | } |
| | return false; |
| | } |
| |
|
| | void InteractiveScale::setPlacement(const Base::Placement& plc) |
| | { |
| | placement = plc; |
| | measureLabel->setPlacement(plc); |
| | } |
| |
|
| | SbVec3f InteractiveScale::getCoordsOnImagePlane(const SbVec3f& point) |
| | { |
| | |
| | Base::Vector3d RX(1, 0, 0); |
| | Base::Vector3d RY(0, 1, 0); |
| |
|
| | |
| | Base::Rotation tmp(placement.getRotation()); |
| | RX = tmp.multVec(RX); |
| | RY = tmp.multVec(RY); |
| | Base::Vector3d pos = placement.getPosition(); |
| |
|
| | |
| | |
| | Base::Vector3d pnt(point[0], point[1], point[2]); |
| | pnt.TransformToCoordinateSystem(pos, RX, RY); |
| |
|
| | return {float(pnt.x), float(pnt.y), 0.0F}; |
| | } |
| |
|
| | |
| |
|
| | TaskImageDialog::TaskImageDialog(Image::ImagePlane* obj) |
| | : widget {new TaskImage(obj)} |
| | { |
| | addTaskBox(Gui::BitmapFactory().pixmap("image-plane"), widget); |
| |
|
| | associateToObject3dView(obj); |
| | } |
| |
|
| | void TaskImageDialog::open() |
| | { |
| | widget->open(); |
| | } |
| |
|
| | bool TaskImageDialog::accept() |
| | { |
| | widget->accept(); |
| | return true; |
| | } |
| |
|
| | bool TaskImageDialog::reject() |
| | { |
| | widget->reject(); |
| | return true; |
| | } |
| |
|
| | #include "moc_TaskImage.cpp" |
| |
|