From 5871c2bb4648f4e02639f6e89569b91d5338adf2 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 20 Mar 2023 17:56:17 +0100 Subject: [PATCH] Gui: add function to scale image --- src/App/ImagePlane.cpp | 22 +++++++ src/App/ImagePlane.h | 8 +++ src/Gui/CMakeLists.txt | 5 ++ src/Gui/TaskView/TaskDialog.cpp | 9 +++ src/Gui/TaskView/TaskDialog.h | 2 + src/Gui/TaskView/TaskImageScale.cpp | 88 +++++++++++++++++++++++++++ src/Gui/TaskView/TaskImageScale.h | 55 +++++++++++++++++ src/Gui/TaskView/TaskImageScale.ui | 94 +++++++++++++++++++++++++++++ src/Gui/ViewProviderImagePlane.cpp | 33 ++++++---- src/Gui/ViewProviderImagePlane.h | 4 +- 10 files changed, 305 insertions(+), 15 deletions(-) create mode 100644 src/Gui/TaskView/TaskImageScale.cpp create mode 100644 src/Gui/TaskView/TaskImageScale.h create mode 100644 src/Gui/TaskView/TaskImageScale.ui diff --git a/src/App/ImagePlane.cpp b/src/App/ImagePlane.cpp index 842fb6fe4f..e60f7200f8 100644 --- a/src/App/ImagePlane.cpp +++ b/src/App/ImagePlane.cpp @@ -31,8 +31,30 @@ PROPERTY_SOURCE(App::ImagePlane, App::GeoFeature) ImagePlane::ImagePlane() + : XPixelsPerMeter{1000.0} + , YPixelsPerMeter{1000.0} { ADD_PROPERTY_TYPE( ImageFile,(nullptr) , "ImagePlane",Prop_None,"File of the image"); ADD_PROPERTY_TYPE( XSize, (100), "ImagePlane",Prop_None,"Size of a pixel in X"); ADD_PROPERTY_TYPE( YSize, (100), "ImagePlane",Prop_None,"Size of a pixel in Y"); } + +int ImagePlane::getXSizeInPixel() +{ + return int(XSize.getValue() * XPixelsPerMeter / 1000); +} + +int ImagePlane::getYSizeInPixel() +{ + return int(YSize.getValue() * YPixelsPerMeter / 1000); +} + +void ImagePlane::setXSizeInPixel(int value) +{ + XSize.setValue(double(value) * 1000.0 / XPixelsPerMeter); +} + +void ImagePlane::setYSizeInPixel(int value) +{ + YSize.setValue(double(value) * 1000.0 / YPixelsPerMeter); +} diff --git a/src/App/ImagePlane.h b/src/App/ImagePlane.h index 5d73a67cc8..0a83ca4302 100644 --- a/src/App/ImagePlane.h +++ b/src/App/ImagePlane.h @@ -43,6 +43,14 @@ public: App::PropertyLength XSize; App::PropertyLength YSize; + int getXSizeInPixel(); + int getYSizeInPixel(); + void setXSizeInPixel(int); + void setYSizeInPixel(int); + + double XPixelsPerMeter; + double YPixelsPerMeter; + /// returns the type name of the ViewProvider const char* getViewProviderName() const override { return "Gui::ViewProviderImagePlane"; diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 9a5342297a..d38d4c8644 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -345,6 +345,7 @@ SET(Gui_UIC_SRCS Placement.ui TextureMapping.ui TaskView/TaskAppearance.ui + TaskView/TaskImageScale.ui TaskView/TaskOrientation.ui TaskView/TaskSelectLinkProperty.ui TaskElementColors.ui @@ -727,6 +728,9 @@ 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 @@ -1239,6 +1243,7 @@ if(MSVC) propertyeditor/PropertyItemDelegate.cpp propertyeditor/PropertyModel.cpp TaskView/TaskAppearance.cpp + TaskView/TaskImageScale.cpp TaskView/TaskOrientation.cpp TaskView/TaskSelectLinkProperty.cpp TaskView/TaskEditControl.cpp diff --git a/src/Gui/TaskView/TaskDialog.cpp b/src/Gui/TaskView/TaskDialog.cpp index 9e8a30abd5..8a9e90847f 100644 --- a/src/Gui/TaskView/TaskDialog.cpp +++ b/src/Gui/TaskView/TaskDialog.cpp @@ -28,6 +28,7 @@ #endif #include "TaskDialog.h" +#include "TaskView.h" using namespace Gui::TaskView; @@ -55,6 +56,14 @@ TaskDialog::~TaskDialog() //==== Slots =============================================================== +void TaskDialog::addTaskBox(QWidget* widget) +{ + Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox( + QPixmap(), widget->windowTitle(), true, nullptr); + taskbox->groupLayout()->addWidget(widget); + Content.push_back(taskbox); +} + const std::vector &TaskDialog::getDialogContent() const { return Content; diff --git a/src/Gui/TaskView/TaskDialog.h b/src/Gui/TaskView/TaskDialog.h index f344f633c6..a2568de24a 100644 --- a/src/Gui/TaskView/TaskDialog.h +++ b/src/Gui/TaskView/TaskDialog.h @@ -57,6 +57,8 @@ public: TaskDialog(); ~TaskDialog() override; + void addTaskBox(QWidget*); + void setButtonPosition(ButtonPosition p) { pos = p; } ButtonPosition buttonPosition() const diff --git a/src/Gui/TaskView/TaskImageScale.cpp b/src/Gui/TaskView/TaskImageScale.cpp new file mode 100644 index 0000000000..a4e097eef1 --- /dev/null +++ b/src/Gui/TaskView/TaskImageScale.cpp @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +/*************************************************************************** + * Copyright (c) 2023 Werner Mayer * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +#endif + +#include +#include +#include +#include +#include + +#include "TaskImageScale.h" +#include "ui_TaskImageScale.h" + + +using namespace Gui; + +TaskImageScale::TaskImageScale(App::ImagePlane* obj, QWidget* parent) + : QWidget(parent) + , ui(new Ui_TaskImageScale) + , feature(obj) + , aspectRatio{1.0} +{ + ui->setupUi(this); + ui->spinBoxWidth->setValue(obj->getXSizeInPixel()); + ui->spinBoxHeight->setValue(obj->getYSizeInPixel()); + + 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); +} + +TaskImageScale::~TaskImageScale() +{ +} + +void TaskImageScale::changeWidth() +{ + if (!feature.expired()) { + int value = ui->spinBoxWidth->value(); + feature->setXSizeInPixel(value); + + if (ui->checkBoxRatio->isChecked()) { + QSignalBlocker block(ui->spinBoxWidth); + ui->spinBoxHeight->setValue(int(double(value) / aspectRatio)); + } + } +} + +void TaskImageScale::changeHeight() +{ + if (!feature.expired()) { + int value = ui->spinBoxHeight->value(); + feature->setYSizeInPixel(value); + + if (ui->checkBoxRatio->isChecked()) { + QSignalBlocker block(ui->spinBoxHeight); + ui->spinBoxWidth->setValue(int(double(value) * aspectRatio)); + } + } +} + +#include "moc_TaskImageScale.cpp" diff --git a/src/Gui/TaskView/TaskImageScale.h b/src/Gui/TaskView/TaskImageScale.h new file mode 100644 index 0000000000..aa03db8969 --- /dev/null +++ b/src/Gui/TaskView/TaskImageScale.h @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +/*************************************************************************** + * Copyright (c) 2023 Werner Mayer * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#ifndef GUI_TASKIMAGESCALE_H +#define GUI_TASKIMAGESCALE_H + +#include +#include +#include +#include + +namespace Gui { + +class Ui_TaskImageScale; +class TaskImageScale : public QWidget +{ + Q_OBJECT + +public: + explicit TaskImageScale(App::ImagePlane* obj, QWidget* parent = nullptr); + ~TaskImageScale() override; + +private: + void changeWidth(); + void changeHeight(); + +private: + std::unique_ptr ui; + App::WeakPtrT feature; + double aspectRatio; +}; + +} + +#endif // GUI_TASKIMAGESCALE_H diff --git a/src/Gui/TaskView/TaskImageScale.ui b/src/Gui/TaskView/TaskImageScale.ui new file mode 100644 index 0000000000..687b281bdc --- /dev/null +++ b/src/Gui/TaskView/TaskImageScale.ui @@ -0,0 +1,94 @@ + + + Gui::TaskImageScale + + + + 0 + 0 + 277 + 178 + + + + Scale image + + + + + + Image size + + + + + + + + Width: + + + + + + + px + + + 1 + + + 100000000 + + + + + + + Height: + + + + + + + px + + + 1 + + + 100000000 + + + + + + + + + Keep aspect ratio + + + + + + + + + + Qt::Vertical + + + + 20 + 18 + + + + + + + + + diff --git a/src/Gui/ViewProviderImagePlane.cpp b/src/Gui/ViewProviderImagePlane.cpp index ab3d89d73a..aefa607083 100644 --- a/src/Gui/ViewProviderImagePlane.cpp +++ b/src/Gui/ViewProviderImagePlane.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include "ViewProviderImagePlane.h" @@ -142,27 +143,30 @@ void ViewProviderImagePlane::onChanged(const App::Property* prop) void ViewProviderImagePlane::setupContextMenu(QMenu* menu, QObject* receiver, const char* member) { - ViewProviderGeometryObject::setupContextMenu(menu, receiver, member); - Gui::ActionFunction* func = new Gui::ActionFunction(menu); - QAction* orient = menu->addAction(QObject::tr("Change orientation...")); - func->trigger(orient, std::bind(&ViewProviderImagePlane::changeOrientation, this)); + QAction* action = menu->addAction(QObject::tr("Change image...")); + action->setIcon(QIcon(QLatin1String("images:image-scaling.svg"))); + func->trigger(action, std::bind(&ViewProviderImagePlane::manipulateImage, this)); - QAction* scale = menu->addAction(QObject::tr("Scale image...")); - scale->setIcon(QIcon(QLatin1String("images:image-scaling.svg"))); - func->trigger(scale, std::bind(&ViewProviderImagePlane::scaleImage, this)); + ViewProviderGeometryObject::setupContextMenu(menu, receiver, member); } -void ViewProviderImagePlane::changeOrientation() +bool ViewProviderImagePlane::doubleClicked() { - Gui::Control().showDialog(new TaskOrientationDialog( + manipulateImage(); + return true; +} + +void ViewProviderImagePlane::manipulateImage() +{ + auto dialog = new TaskOrientationDialog( dynamic_cast(getObject()) + ); + dialog->addTaskBox(new TaskImageScale( + dynamic_cast(getObject()) )); -} - -void ViewProviderImagePlane::scaleImage() -{ + Gui::Control().showDialog(dialog); } void ViewProviderImagePlane::resizePlane(float xsize, float ysize) @@ -188,6 +192,9 @@ void ViewProviderImagePlane::loadImage() if (!impQ.isNull()) { imagePlane->XSize.setValue(size.width()); imagePlane->YSize.setValue(size.height()); + + imagePlane->XPixelsPerMeter = impQ.dotsPerMeterX(); + imagePlane->YPixelsPerMeter = impQ.dotsPerMeterY(); } } diff --git a/src/Gui/ViewProviderImagePlane.h b/src/Gui/ViewProviderImagePlane.h index c4ea652a5d..b0f4bec6fa 100644 --- a/src/Gui/ViewProviderImagePlane.h +++ b/src/Gui/ViewProviderImagePlane.h @@ -50,6 +50,7 @@ public: std::vector getDisplayModes() const override; void updateData(const App::Property*) override; void setupContextMenu(QMenu*, QObject*, const char*) override; + bool doubleClicked() override; void onChanged(const App::Property* prop) override; private: @@ -59,8 +60,7 @@ private: bool loadSvg(const char*, double x, double y, QImage& img); QSizeF loadRaster(const char*, QImage& img); void convertToSFImage(const QImage& img); - void changeOrientation(); - void scaleImage(); + void manipulateImage(); private: SoCoordinate3 * pcCoords;