Merge pull request #575 from tonysyu/feature/viewer-linking

Linked image viewers and docked plugins
This commit is contained in:
Josh Warner
2013-06-28 08:32:34 -07:00
14 changed files with 304 additions and 63 deletions
+38 -4
View File
@@ -1,9 +1,12 @@
"""
Base class for Plugins that interact with ImageViewer.
"""
from ..qt import QtGui
from ..qt.QtCore import Qt
from warnings import warn
import numpy as np
from ..qt import QtGui
from ..qt.QtCore import Qt, Signal
from ..utils import RequiredAttr, init_qtapp
@@ -71,14 +74,24 @@ class Plugin(QtGui.QDialog):
name = 'Plugin'
image_viewer = RequiredAttr("%s is not attached to ImageViewer" % name)
def __init__(self, image_filter=None, height=0, width=400, useblit=True):
# Signals used when viewers are linked to the Plugin output.
image_changed = Signal(np.ndarray)
_started = Signal(int)
def __init__(self, image_filter=None, height=0, width=400, useblit=True,
dock='bottom'):
init_qtapp()
super(Plugin, self).__init__()
self.dock = dock
self.image_viewer = None
# If subclass defines `image_filter` method ignore input.
if not hasattr(self, 'image_filter'):
self.image_filter = image_filter
elif image_filter is not None:
warn("If the Plugin class defines an `image_filter` method, "
"then the `image_filter` argument is ignored.")
self.setWindowTitle(self.name)
self.layout = QtGui.QGridLayout(self)
@@ -109,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()
@@ -155,12 +168,22 @@ class Plugin(QtGui.QDialog):
kwargs = dict([(name, self._get_value(a))
for name, a in self.keyword_arguments.items()])
filtered = self.image_filter(*arguments, **kwargs)
self.display_filtered_image(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."""
@@ -183,6 +206,17 @@ class Plugin(QtGui.QDialog):
"""
setattr(self, name, value)
def show(self, main_window=True):
"""Show plugin."""
super(Plugin, self).show()
self.activateWindow()
self.raise_()
# 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)
def closeEvent(self, event):
"""On close disconnect all artists and events from ImageViewer.