From cc2f1854b5d1c39ec6b899d902dcf8a762bd814f Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 8 Jun 2013 19:06:23 -0500 Subject: [PATCH] Fix plugin interaction with CollectionViewer * Signal updates to original image when image changed in CollectionViewer. * Update plugin arguments for the filter. * Also fixes image updates when opening a new image from the file menu. --- skimage/viewer/plugins/base.py | 16 +++++++++++++--- skimage/viewer/viewers/core.py | 18 ++++++++++++------ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/skimage/viewer/plugins/base.py b/skimage/viewer/plugins/base.py index f5fbf935..1d655d61 100644 --- a/skimage/viewer/plugins/base.py +++ b/skimage/viewer/plugins/base.py @@ -75,7 +75,7 @@ class Plugin(QtGui.QDialog): image_viewer = RequiredAttr("%s is not attached to ImageViewer" % name) # Signals used when viewers are linked to the Plugin output. - image_updated = Signal(np.ndarray) + image_changed = Signal(np.ndarray) _started = Signal(int) def __init__(self, image_filter=None, height=0, width=400, useblit=True, @@ -122,7 +122,7 @@ class Plugin(QtGui.QDialog): self.image_viewer = image_viewer self.image_viewer.plugins.append(self) #TODO: Always passing image as first argument may be bad assumption. - self.arguments.append(self.image_viewer.original_image) + self.arguments = [self.image_viewer.original_image] # Call filter so that filtered image matches widget values self.filter_image() @@ -170,12 +170,20 @@ class Plugin(QtGui.QDialog): filtered = self.image_filter(*arguments, **kwargs) self.display_filtered_image(filtered) - self.image_updated.emit(filtered) + self.image_changed.emit(filtered) def _get_value(self, param): # If param is a widget, return its `val` attribute. return param if not hasattr(param, 'val') else param.val + def _update_original_image(self, image): + """Update the original image argument passed to the filter function. + + This method is called by the viewer when the original image is updated. + """ + self.arguments[0] = image + self.filter_image() + @property def filtered_image(self): """Return filtered image.""" @@ -201,6 +209,8 @@ class Plugin(QtGui.QDialog): def show(self, main_window=True): """Show plugin.""" super(Plugin, self).show() + + # Emit signal with x-hint so new windows can be displayed w/o overlap. size = self.frameGeometry() x_hint = size.x() + size.width() self._started.emit(x_hint) diff --git a/skimage/viewer/viewers/core.py b/skimage/viewer/viewers/core.py index 91362f47..a054da13 100644 --- a/skimage/viewer/viewers/core.py +++ b/skimage/viewer/viewers/core.py @@ -2,7 +2,7 @@ ImageViewer class for viewing and interacting with images. """ from ..qt import QtGui -from ..qt.QtCore import Qt +from ..qt.QtCore import Qt, Signal from skimage import io, img_as_float from skimage.util.dtype import dtype_range @@ -66,6 +66,9 @@ class ImageViewer(QtGui.QMainWindow): 'left': Qt.LeftDockWidgetArea, 'right': Qt.RightDockWidgetArea} + # Signal that the original image has been changed + original_image_changed = Signal(np.ndarray) + def __init__(self, image): # Start main loop utils.init_qtapp() @@ -91,7 +94,7 @@ class ImageViewer(QtGui.QMainWindow): if isinstance(image, Plugin): plugin = image image = plugin.filtered_image - plugin.image_updated.connect(self._new_original_image) + plugin.image_changed.connect(self._update_original_image) # When plugin is started, start plugin._started.connect(self._show) @@ -102,7 +105,7 @@ class ImageViewer(QtGui.QMainWindow): self.ax.autoscale(enable=False) self._image_plot = self.ax.images[0] - self._new_original_image(image) + self._update_original_image(image) self.plugins = [] self.layout = QtGui.QVBoxLayout(self.main_widget) @@ -119,6 +122,8 @@ class ImageViewer(QtGui.QMainWindow): def __add__(self, plugin): """Add plugin to ImageViewer""" plugin.attach(self) + self.original_image_changed.connect(plugin._update_original_image) + if plugin.dock: location = self.dock_areas[plugin.dock] dock_location = Qt.DockWidgetArea(location) @@ -153,11 +158,12 @@ class ImageViewer(QtGui.QMainWindow): if filename is None: return image = io.imread(filename) - self._new_original_image(image) + self._update_original_image(image) - def _new_original_image(self, image): + def _update_original_image(self, image): self.original_image = image # update saved image self.image = image.copy() # update displayed image + self.original_image_changed.emit(image) def save_to_file(self): """Save current image to file. @@ -330,7 +336,7 @@ class CollectionViewer(ImageViewer): This method can be overridden or extended in subclasses and plugins to react to image changes. """ - self.image = image + self._update_original_image(image) def keyPressEvent(self, event): if type(event) == QtGui.QKeyEvent: