diff --git a/src/img/img/ImagePropertiesPage.ui b/src/img/img/ImagePropertiesPage.ui index 2ea522bdd..fbb6b8a88 100644 --- a/src/img/img/ImagePropertiesPage.ui +++ b/src/img/img/ImagePropertiesPage.ui @@ -72,7 +72,6 @@ Sans Serif 12 - 75 false true false @@ -108,98 +107,31 @@ 6 - - - - h = - - - - - - - - - - x = - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Perspective - - - - - - - - - - + degree - - - - - - - - + + - Shear angle + h = - - - - Pixel Size - - + + - + degree - - - - micron - - - - - - - Rotation angle - - - - - - - micron - - - - + w = @@ -209,77 +141,8 @@ - - - - micron - - - - - - - Center - - - - - - - x = - - - - - - - Mirrored (at X-axis) - - - - - - - micron - - - - - - - - - - degree - - - - - - - Qt::Vertical - - - - 20 - 5 - - - - - - - - y = - - - - - - - degree - - + + @@ -292,15 +155,135 @@ 507 - 16 + 10 - - - + + + Qt::Vertical + + + + 20 + 5 + + + + + + + + (use them to align the image with the layout) + + + + + + + + + + + + + Rotation angle + + + + + + + x = + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + degree + + + + + + + Landmarks + + + + + + + micron + + + + + + + micron + + + + + + + Perspective + + + + + + + micron + + + + + + + + + + y = + + + + + + + Define + + + + + + + x = + + + + + + + micron + + + + + + + Shear angle + + + + Qt::Vertical @@ -316,32 +299,130 @@ - + + + + + + + Pixel Size + + + + + + + Mirrored (at X-axis) + + + + + + + degree + + + + + + + + + + Center + + + + y = - - + + + + + - Landmarks + Layer binding - - - - Define + + + + Qt::Vertical - + + QSizePolicy::Fixed + + + + 20 + 5 + + + - - - - (use them to align the image with the layout) + + + + + 0 + 0 + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Visibility of the image follows that layer's visibility + + + QComboBox::AdjustToContents + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + @@ -1111,6 +1192,11 @@ p, li { white-space: pre-wrap; }
imgWidgets.h
1 + + lay::LayerSelectionComboBox + QComboBox +
layWidgets.h
+
width_le diff --git a/src/img/img/gsiDeclImg.cc b/src/img/img/gsiDeclImg.cc index 549367b89..13c4e5987 100644 --- a/src/img/img/gsiDeclImg.cc +++ b/src/img/img/gsiDeclImg.cc @@ -811,13 +811,13 @@ gsi::Class decl_Image (decl_BasicImage, "lay", "Image", "@brief Sets the mask from a array of boolean values\n" "The order of the boolean values is line first, from bottom to top and left to right and is the same as the order in the data array.\n" "\n" - "This method has been introduced in version 0.27.\n" + "This attribute has been introduced in version 0.27.\n" ) + gsi::method_ext ("mask_data", &get_mask_data, "@brief Gets the mask from a array of boolean values\n" "See \\set_mask_data for a description of the data field.\n" "\n" - "This method has been introduced in version 0.27.\n" + "This attribute has been introduced in version 0.27.\n" ) + gsi::method_ext ("pixel_width=", &img_set_pixel_width, gsi::arg ("w"), "@brief Sets the pixel width\n" @@ -826,7 +826,7 @@ gsi::Class decl_Image (decl_BasicImage, "lay", "Image", "micron space with the transformation.\n" "\n" "Starting with version 0.22, this property is incorporated into the transformation matrix.\n" - "This property is provided for convenience only." + "This attribute is provided for convenience only." ) + gsi::method_ext ("pixel_width", &img_get_pixel_width, "@brief Gets the pixel width\n" @@ -834,7 +834,7 @@ gsi::Class decl_Image (decl_BasicImage, "lay", "Image", "See \\pixel_width= for a description of that property.\n" "\n" "Starting with version 0.22, this property is incorporated into the transformation matrix.\n" - "This property is provided for convenience only." + "This attribute is provided for convenience only." ) + gsi::method_ext ("pixel_height=", &img_set_pixel_height, gsi::arg ("h"), "@brief Sets the pixel height\n" @@ -843,7 +843,7 @@ gsi::Class decl_Image (decl_BasicImage, "lay", "Image", "micron space with the transformation.\n" "\n" "Starting with version 0.22, this property is incorporated into the transformation matrix.\n" - "This property is provided for convenience only." + "This attribute is provided for convenience only." ) + gsi::method_ext ("pixel_height", &img_get_pixel_height, "@brief Gets the pixel height\n" @@ -851,21 +851,35 @@ gsi::Class decl_Image (decl_BasicImage, "lay", "Image", "See \\pixel_height= for a description of that property.\n" "\n" "Starting with version 0.22, this property is incorporated into the transformation matrix.\n" - "This property is provided for convenience only." + "This attribute is provided for convenience only." ) + gsi::method ("z_position", &ImageRef::z_position, "@brief Gets the z position of the image\n" "Images with a higher z position are painted in front of images with lower z position.\n" "The z value is an integer that controls the position relative to other images.\n" "\n" - "This method was introduced in version 0.25." + "This attribute was introduced in version 0.25." ) + gsi::method ("z_position=", &ImageRef::set_z_position, gsi::arg ("z"), "@brief Sets the z position of the image\n" "\n" "See \\z_position for details about the z position attribute.\n" "\n" - "This method was introduced in version 0.25." + "This attribute was introduced in version 0.25." + ) + + gsi::method ("layer_binding", &ImageRef::layer_binding, + "@brief Gets the layer binding of the image\n" + "If this attribute is set to a non-null layer properties object, the images visibility " + "is associated with that of this layer. If the layer becomes invisible, the image is hidden as well.\n" + "\n" + "This attribute was introduced in version 0.30.4." + ) + + gsi::method ("layer_binding=", &ImageRef::set_layer_binding, gsi::arg ("lp"), + "@brief Sets the layer binding of the image\n" + "\n" + "See \\layer_binding for details about the layer_binding attribute.\n" + "\n" + "This attribute was introduced in version 0.30.4." ) + gsi::method ("matrix=", &ImageRef::set_matrix, gsi::arg ("t"), "@brief Sets the transformation matrix\n" @@ -876,7 +890,7 @@ gsi::Class decl_Image (decl_BasicImage, "lay", "Image", "The matrix is more general than the transformation used before and supports shear and perspective transformation. This property replaces the \\trans property which is " "still functional, but deprecated.\n" "\n" - "This method has been introduced in version 0.22." + "This attribute has been introduced in version 0.22." ) + gsi::method ("matrix", &ImageRef::matrix, "@brief Returns the pixel-to-micron transformation matrix\n" @@ -887,7 +901,7 @@ gsi::Class decl_Image (decl_BasicImage, "lay", "Image", "The matrix is more general than the transformation used before and supports shear and perspective transformation. This property replaces the \\trans property which is " "still functional, but deprecated.\n" "\n" - "This method has been introduced in version 0.22." + "This attribute has been introduced in version 0.22." ) + gsi::method_ext ("trans", &img_get_trans, "@brief Returns the pixel-to-micron transformation\n" @@ -941,14 +955,14 @@ gsi::Class decl_Image (decl_BasicImage, "lay", "Image", "\n" "See the \\is_visible? method for a description of this property.\n" "\n" - "This method has been introduced in version 0.20.\n" + "This attribute has been introduced in version 0.20.\n" ) + gsi::method ("is_visible?", &ImageRef::is_visible, "@brief Gets a flag indicating whether the image object is visible\n" "\n" "An image object can be made invisible by setting the visible property to false.\n" "\n" - "This method has been introduced in version 0.20.\n" + "This attribute has been introduced in version 0.20.\n" ) + gsi::method ("id", (size_t (ImageRef::*) () const) &ImageRef::id, "@brief Gets the Id\n" diff --git a/src/img/img/imgObject.cc b/src/img/img/imgObject.cc index ab76374f3..ae0b508c2 100644 --- a/src/img/img/imgObject.cc +++ b/src/img/img/imgObject.cc @@ -1020,6 +1020,7 @@ Object::operator= (const img::Object &d) m_visible = d.m_visible; m_z_position = d.m_z_position; + m_layer_binding = d.m_layer_binding; m_min_value = d.m_min_value; m_min_value_set = d.m_min_value_set; @@ -1052,6 +1053,10 @@ Object::less (const db::DUserObjectBase *d) const return m_z_position < img_object->m_z_position; } + if (m_layer_binding != img_object->m_layer_binding) { + return m_layer_binding < img_object->m_layer_binding; + } + double epsilon = (std::abs (m_min_value) + std::abs (m_max_value)) * 1e-6; if (std::abs (m_min_value - img_object->m_min_value) > epsilon) { return m_min_value < img_object->m_min_value; @@ -1102,7 +1107,11 @@ Object::operator== (const img::Object &d) const return false; } - // operator== is all fuzzy compare - + if (m_layer_binding != d.m_layer_binding) { + return false; + } + + // operator== is all fuzzy compare - double epsilon = (std::abs (m_min_value) + std::abs (m_max_value)) * 1e-6; if (std::abs (m_min_value - d.m_min_value) > epsilon) { return false; @@ -1424,6 +1433,8 @@ Object::from_string (const char *str, const char *base_dir) ex.read (h); } else if (ex.test ("is_visible=")) { ex.read (m_visible); + } else if (ex.test ("layer_binding=")) { + ex.read (m_layer_binding); } else if (ex.test ("z_position=")) { ex.read (m_z_position); } else if (ex.test ("min_value=")) { @@ -1814,6 +1825,12 @@ Object::to_string () const os << tl::to_string (m_z_position); os << ";"; + if (m_layer_binding != db::LayerProperties ()) { + os << "layer_binding="; + os << m_layer_binding.to_string (); + os << ";"; + } + os << "brightness="; os << tl::to_string (data_mapping ().brightness); os << ";"; @@ -1953,6 +1970,7 @@ Object::swap (Object &other) std::swap (mp_pixel_data, other.mp_pixel_data); m_landmarks.swap (other.m_landmarks); std::swap (m_z_position, other.m_z_position); + std::swap (m_layer_binding, other.m_layer_binding); std::swap (m_updates_enabled, other.m_updates_enabled); } diff --git a/src/img/img/imgObject.h b/src/img/img/imgObject.h index 214ea6c17..db1e719c8 100644 --- a/src/img/img/imgObject.h +++ b/src/img/img/imgObject.h @@ -31,6 +31,7 @@ #include "dbTrans.h" #include "dbMatrix.h" #include "dbPolygon.h" +#include "dbLayerProperties.h" #include "tlDataMapping.h" #include "tlColor.h" #include "tlPixelBuffer.h" @@ -924,6 +925,30 @@ public: return m_z_position; } + /** + * @brief Sets the layer binding + * + * If the image is bound to a layer, it becomes hidden when the layer is hidden + * and visible if the layer is visible too + */ + void set_layer_binding (const db::LayerProperties &lp) + { + if (m_layer_binding != lp) { + m_layer_binding = lp; + if (m_updates_enabled) { + property_changed (); + } + } + } + + /** + * @brief Gets the layer binding + */ + const db::LayerProperties &layer_binding () const + { + return m_layer_binding; + } + /** * @brief Get the RGB pixel data sets obtained by applying the LUT's */ @@ -1021,6 +1046,7 @@ private: mutable const tl::color_t *mp_pixel_data; std::vector m_landmarks; int m_z_position; + db::LayerProperties m_layer_binding; bool m_updates_enabled; void release (); diff --git a/src/img/img/imgPropertiesPage.cc b/src/img/img/imgPropertiesPage.cc index b5663d8aa..945765cf5 100644 --- a/src/img/img/imgPropertiesPage.cc +++ b/src/img/img/imgPropertiesPage.cc @@ -109,6 +109,8 @@ PropertiesPage::init () colors->setEnabled (false); value_le->setEnabled (false); + attach_service (mp_service); + connect (browse_pb, SIGNAL (clicked ()), this, SLOT (browse ())); connect (colors, SIGNAL (color_changed (std::pair)), false_color_control, SLOT (set_current_color (std::pair))); connect (false_color_control, SIGNAL (selection_changed (std::pair)), colors, SLOT (set_color (std::pair))); @@ -147,6 +149,20 @@ PropertiesPage::init () connect (define_landmarks_pb, SIGNAL (clicked ()), this, SLOT (define_landmarks_pressed ())); } +void +PropertiesPage::attach_service (img::Service *service) +{ + layer_binding_cbx->set_new_layer_enabled (false); + layer_binding_cbx->set_no_layer_available (true); + + if (service && service->view ()) { + int cv_index = 0; // TODO: fixed currently + layer_binding_cbx->set_view (service->view (), cv_index, true); + } else { + layer_binding_cbx->set_view (0, -1); + } +} + void PropertiesPage::invalidate () { @@ -195,6 +211,10 @@ PropertiesPage::description () const void PropertiesPage::confine_selection (const std::vector &remaining_entries) { + if (! mp_service) { + return; + } + std::vector org_selection; m_selection.swap (org_selection); for (auto i = remaining_entries.begin (); i != remaining_entries.end (); ++i) { @@ -459,6 +479,8 @@ PropertiesPage::update () to_le->setText (tl::to_qstring (tl::to_string (mp_direct_image->max_value ()))); to_le->setCursorPosition (0); + layer_binding_cbx->set_current_layer (mp_direct_image->layer_binding ()); + false_color_control->set_nodes (mp_direct_image->data_mapping ().false_color_nodes); brightness_slider->setValue (int (floor (mp_direct_image->data_mapping ().brightness * 100 + 0.5))); @@ -908,6 +930,8 @@ PropertiesPage::apply (bool /*commit*/) mp_direct_image->set_min_value (xmin); mp_direct_image->set_max_value (xmax); + mp_direct_image->set_layer_binding (layer_binding_cbx->current_layer_props ()); + img::DataMapping dm (mp_direct_image->data_mapping ()); dm.brightness = brightness_sb->value () * 0.01; dm.contrast = contrast_sb->value () * 0.01; diff --git a/src/img/img/imgPropertiesPage.h b/src/img/img/imgPropertiesPage.h index 32f453a1e..dbfd3525b 100644 --- a/src/img/img/imgPropertiesPage.h +++ b/src/img/img/imgPropertiesPage.h @@ -61,6 +61,7 @@ public: virtual void apply (bool commit); void set_direct_image (img::Object *image); + void attach_service (img::Service *service); private slots: void browse (); diff --git a/src/img/img/imgService.cc b/src/img/img/imgService.cc index 5f23b5892..8dc64c019 100644 --- a/src/img/img/imgService.cc +++ b/src/img/img/imgService.cc @@ -58,10 +58,11 @@ class AddNewImageDialog public Ui::AddNewImageDialog { public: - AddNewImageDialog (QWidget *parent, img::Object *image_object) + AddNewImageDialog (QWidget *parent, img::Service *service, img::Object *image_object) : QDialog (parent), mp_image_object (image_object) { setupUi (this); + properties_frame->attach_service (service); properties_frame->set_direct_image (image_object); properties_frame->update (); } @@ -1606,7 +1607,7 @@ Service::add_image () #if defined(HAVE_QT) img::Object *new_image = new img::Object (); - AddNewImageDialog dialog (QApplication::activeWindow (), new_image); + AddNewImageDialog dialog (QApplication::activeWindow (), this, new_image); if (dialog.exec ()) { clear_selection ();