class PointSelection (QMainWindow) :

    def __init__ (self) :
        QMainWindow.__init__(self)

        # points
        self._points = []
        self._id_gen = IdSetGenerator()
#X         self.version = 2

        self._view = PixmapStackView()

        #QGraphicsScene
        self._scene = QGraphicsScene()

        #QGraphicsPixmapItem
        self._item = QGraphicsPixmapItem()
        self._item.setTransformationMode(Qt.SmoothTransformation)
        self._item.setFlag(self._item.ItemIsSelectable,False)
        self._scene.addItem(self._item)

        #QGraphicsView
        self._widget = ScalableGraphicsView(self._scene)
        self.setCentralWidget(self._widget)

        ################### mouse handling ###################
        self._widget.setMouseTracking(True)
        self._last_mouse_x = 0
        self._last_mouse_y = 0
        self._last_slice = 0

        QObject.connect(self._widget,
                    SIGNAL("mouse_press"),
                    self.mouse_pressed)

        QObject.connect(self._widget,
                    SIGNAL("mouse_move"),
                    self.mouse_moved)

        QObject.connect(self,
                    SIGNAL("mouse_moved"),
                    self.coordinates)

        ################### menubar ###################
        self.menu = self.menuBar()
        self.menu_file = self.menu.addMenu('File')

        # Import Points
        self._load_points = self.menu_file.addAction('Import Points')
        QObject.connect(self._load_points,
                        SIGNAL("triggered(bool)"),
                        self.load_points)

        # Save points
        self._save_points = self.menu_file.addAction('Save Points')
        QObject.connect(self._save_points,
                        SIGNAL("triggered(bool)"),
                        self.save_points)

        ################### toolbar ###################
        self._toolbar = self.addToolBar("tools")
        self._toolgroup = QActionGroup(self)

        # QWidgetAction : "Rotation Left"
        self._action_left = self._toolbar.addAction("left rotation")
        self._action_left.setIcon(QIcon(":/image/rotate_left.png") )
        QObject.connect(self._action_left,
                        SIGNAL("triggered(bool)"),
                        self.rotate_left)

        # QWidgetAction : "Rotation Right"
        self._action_right = self._toolbar.addAction("right rotation")
        self._action_right.setIcon(QIcon(":/image/rotate_right.png") )
        QObject.connect(self._action_right,
                        SIGNAL("triggered(bool)"),
                        self.rotate_right)

        # QWidgetAction : "Add point"
        self._action_add = self._toolbar.addAction("Add point")
        self._action_add.setCheckable(True)
        self._toolgroup.addAction(self._action_add)
        self._action_add.setIcon(QIcon(":/image/add.png") )

        # QWidgetAction : "Delete point"
        self._action_delete = self._toolbar.addAction("Delete point")
        self._action_delete.setCheckable(True)
        self._toolgroup.addAction(self._action_delete)
        self._action_delete.setIcon(QIcon(":/image/delete.png") )

        ################### palette ###################
        self._palette_select = QComboBox()
        self._toolbar.addWidget(self._palette_select)
        for palname in palette_names :
            self._palette_select.addItem(palname)

        QObject.connect(self._palette_select,
                    SIGNAL("currentIndexChanged(int)"),
                    self.palette_name_changed)

        ################### slider ###################
        self._bot_toolbar = QToolBar("slider")
        self._img_slider = QSlider(Qt.Horizontal)
        self._img_slider.setRange(0,self._view.nb_slices() - 1)

        QObject.connect(self._img_slider,
                        SIGNAL("valueChanged(int)"),
                        self.slice_changed)

        self._bot_toolbar.addWidget(self._img_slider)
        self.addToolBar(Qt.BottomToolBarArea,self._bot_toolbar)

        ################### statusbar ###################
        self._lab_coord = QLabel("coords:")
        self._lab_xcoord = QLabel("% 4d" % 0)
        self._lab_ycoord = QLabel("% 4d" % 0)
        self._lab_zcoord = QLabel("% 4d" % 0)
        self._lab_intens = QLabel("intens: None")

        self.statusbar = self.statusBar()
        self.statusbar.addPermanentWidget(self._lab_coord)
        self.statusbar.addPermanentWidget(self._lab_xcoord)
        self.statusbar.addPermanentWidget(self._lab_ycoord)
        self.statusbar.addPermanentWidget(self._lab_zcoord)
        self.statusbar.addPermanentWidget(self._lab_intens)

    ##############################################
    #
    #               update GUI
    #
    ##############################################
    def update_pix (self) :
        """
        """
        pix = self._view.pixmap()

        if pix is not None :
            self._item.setPixmap(pix)
        else:
            print 'None pixmap'
        #update points
        ind = self._view.current_slice()
        for point in self._points :
            if point is not None:
                pid,item, x,y,z,textid = point
                visible = abs(z - ind) < 5
                item.setVisible(visible)
                col = QColor.fromHsv( (pid * 10) % 360,255,255)
                if visible :
                    sca = max(0.,(5 - abs(z - ind) ) / 5.)
                    if z == ind :
                        pen = QPen(QColor(255,255,255) )
                        pen.setWidthF(2.)
                        item.setPen(pen)
                        textid.setVisible(True)
                    else :
                        pen = QPen(QColor(0,0,0) )
                        pen.setWidthF(2.)
                        item.setPen(pen)
                        textid.setVisible(False)
                else :
                    sca = 1.
                tr = QTransform()
                tr.scale(sca,sca)
                item.setTransform(tr)
                item.update()

    def coordinates (self,(i,j,k)) :
        self._last_mouse_x,self._last_mouse_y, self._last_slice = i,j,k
        self.fill_infos()
class ImageStackViewerWidget(QtGui.QWidget):

    """
    Widget based on openalea.image.gui.slide_viewer.PixmapStackView
    """
    valueChanged = QtCore.Signal(object)
    stackChanged = QtCore.Signal(object)

    def __init__(self):
        QtGui.QWidget.__init__(self)
        self._im_view = PixmapStackView()
        self._label = ScalableLabel()

        self._layout = QtGui.QVBoxLayout(self)
        self._layout.addWidget(self._label)

        self._label.setMouseTracking(True)
        self._last_mouse_x = 0
        self._last_mouse_y = 0

        self.connect(self._label, QtCore.SIGNAL("mouse_press"), self.mouse_pressed)
        self.connect(self._label, QtCore.SIGNAL("mouse_move"), self.mouse_pressed)

        self.axis = 2
        self.inc = 1 # index increment
        self._palette_name = None

    ##############################################
    #        Qt Control API
    ##############################################

    def setValue(self, img):
        if img is self.value():
            return
        self._im_view.set_image(img)
        try:
            self.resolution = img.resolution[:]
        except AttributeError:
            pass

        self._im_view._reconstruct_pixmaps()
        self.change_axis(0)
        self.slice_changed((0 + self._im_view.nb_slices() - 1) / 2)

        self.emit_stack_changed()

    def value(self):
        return self._im_view.image()

    ##############################################
    #        slots
    ##############################################

    def emit_stack_changed(self):
        img = self.value()
        if img is None:
            self.stackChanged.emit(None)
        else:
            args = dict(shape=img.shape, axis=self.axis,
                        slice=self._im_view.current_slice(),
                        resolution=self.resolution, inc=self.inc,
                        palette_name=self._palette_name)
            self.stackChanged.emit(args)

    def change_axis(self, ind):
        if self.axis == ind:
            return
        try:
            res = list(self.resolution)
            del res[self.axis]
            tr = self._im_view._transform
            print res
            if tr % 180:
                self._label._resolution = res[1], res[0]
            else:
                self._label.set_resolution(*res[:2])
        except AttributeError:
            pass
        self._im_view._reconstruct_pixmaps(self.axis)
        self.emit_stack_changed()
        self.update_pix()
        #self.fill_infos()

    def mouse_pressed(self, event):
        self._last_mouse_x = event.x()
        self._last_mouse_y = event.y()

    def change_palette(self, palette_name):
        if palette_name == self._palette_name:
            return

        self._palette_name = palette_name
        self.emit_stack_changed()

        img = self._im_view.image()
        if img is None:
            return

        palette = palette_factory(palette_name, img.max())
        self._im_view.set_palette(palette, self.axis)
        self.update_pix()

    def update_pix(self):
        pix = self._im_view.pixmap()
        if pix is not None:
            self._label.setPixmap(pix)

    def get_pixel_value_str(self, img, x, y, z):
        px = img[x, y, z]
        if isinstance(px, np.ndarray):
            return str(px)
        else:
            return "%3d" % px

    def slice_changed(self, ind):
        img = self.value()
        if img is None:
            return

        if ind >= img.shape[self.axis]:
            ind = img.shape[self.axis] - 1
        if ind < 0:
            ind = 0
        if self._im_view.current_slice() == ind:
            return
        self._im_view.set_current_slice(ind)
        self.emit_stack_changed()
        self.update_pix()

    def snapshot(self):
        """write the current image
        """
        pix = self._im_view.pixmap()
        if pix is not None:
            pix.save("slice%.4d.png" % self.panel.img_slider.value())

    def wheelEvent(self, event):
        self.inc = event.delta() / 8 / 15
        idx = self._im_view.current_slice()
        self.slice_changed(idx + self.inc)

    def rotate_left(self):
        res = self._label._resolution
        self._label._resolution = res[1], res[0]
        self._im_view.rotate(-1)
        self.update_pix()

    def rotate_right(self):
        res = self._label._resolution
        self._label._resolution = res[1], res[0]
        self._im_view.rotate(1)
        self.update_pix()
class PointSelection(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        # points
        self._points = []
        self._id_gen = IdSetGenerator()
        #X         self.version = 2

        self._view = PixmapStackView()

        #QGraphicsScene
        self._scene = QGraphicsScene()

        #QGraphicsPixmapItem
        self._item = QGraphicsPixmapItem()
        self._item.setTransformationMode(Qt.SmoothTransformation)
        self._item.setFlag(self._item.ItemIsSelectable, False)
        self._scene.addItem(self._item)

        #QGraphicsView
        self._widget = ScalableGraphicsView(self._scene)
        self.setCentralWidget(self._widget)

        ################### mouse handling ###################
        self._widget.setMouseTracking(True)
        self._last_mouse_x = 0
        self._last_mouse_y = 0
        self._last_slice = 0

        QObject.connect(self._widget, SIGNAL("mouse_press"),
                        self.mouse_pressed)

        QObject.connect(self._widget, SIGNAL("mouse_move"), self.mouse_moved)

        QObject.connect(self, SIGNAL("mouse_moved"), self.coordinates)

        ################### menubar ###################
        self.menu = self.menuBar()
        self.menu_file = self.menu.addMenu('File')

        # Import Points
        self._load_points = self.menu_file.addAction('Import Points')
        QObject.connect(self._load_points, SIGNAL("triggered(bool)"),
                        self.load_points)

        # Save points
        self._save_points = self.menu_file.addAction('Save Points')
        QObject.connect(self._save_points, SIGNAL("triggered(bool)"),
                        self.save_points)

        ################### toolbar ###################
        self._toolbar = self.addToolBar("tools")
        self._toolgroup = QActionGroup(self)

        # QWidgetAction : "Rotation Left"
        self._action_left = self._toolbar.addAction("left rotation")
        self._action_left.setIcon(QIcon(":/image/rotate_left.png"))
        QObject.connect(self._action_left, SIGNAL("triggered(bool)"),
                        self.rotate_left)

        # QWidgetAction : "Rotation Right"
        self._action_right = self._toolbar.addAction("right rotation")
        self._action_right.setIcon(QIcon(":/image/rotate_right.png"))
        QObject.connect(self._action_right, SIGNAL("triggered(bool)"),
                        self.rotate_right)

        # QWidgetAction : "Add point"
        self._action_add = self._toolbar.addAction("Add point")
        self._action_add.setCheckable(True)
        self._toolgroup.addAction(self._action_add)
        self._action_add.setIcon(QIcon(":/image/add.png"))

        # QWidgetAction : "Delete point"
        self._action_delete = self._toolbar.addAction("Delete point")
        self._action_delete.setCheckable(True)
        self._toolgroup.addAction(self._action_delete)
        self._action_delete.setIcon(QIcon(":/image/delete.png"))

        ################### palette ###################
        self._palette_select = QComboBox()
        self._toolbar.addWidget(self._palette_select)
        for palname in palette_names:
            self._palette_select.addItem(palname)

        QObject.connect(self._palette_select,
                        SIGNAL("currentIndexChanged(int)"),
                        self.palette_name_changed)

        ################### slider ###################
        self._bot_toolbar = QToolBar("slider")
        self._img_slider = QSlider(Qt.Horizontal)
        self._img_slider.setRange(0, self._view.nb_slices() - 1)

        QObject.connect(self._img_slider, SIGNAL("valueChanged(int)"),
                        self.slice_changed)

        self._bot_toolbar.addWidget(self._img_slider)
        self.addToolBar(Qt.BottomToolBarArea, self._bot_toolbar)

        ################### statusbar ###################
        self._lab_coord = QLabel("coords:")
        self._lab_xcoord = QLabel("% 4d" % 0)
        self._lab_ycoord = QLabel("% 4d" % 0)
        self._lab_zcoord = QLabel("% 4d" % 0)
        self._lab_intens = QLabel("intens: None")

        self.statusbar = self.statusBar()
        self.statusbar.addPermanentWidget(self._lab_coord)
        self.statusbar.addPermanentWidget(self._lab_xcoord)
        self.statusbar.addPermanentWidget(self._lab_ycoord)
        self.statusbar.addPermanentWidget(self._lab_zcoord)
        self.statusbar.addPermanentWidget(self._lab_intens)

    ##############################################
    #
    #               update GUI
    #
    ##############################################
    def update_pix(self):
        """
        """
        pix = self._view.pixmap()

        if pix is not None:
            self._item.setPixmap(pix)
        else:
            print 'None pixmap'
        #update points
        ind = self._view.current_slice()
        for point in self._points:
            if point is not None:
                pid, item, x, y, z, textid = point
                visible = abs(z - ind) < 5
                item.setVisible(visible)
                col = QColor.fromHsv((pid * 10) % 360, 255, 255)
                if visible:
                    sca = max(0., (5 - abs(z - ind)) / 5.)
                    if z == ind:
                        pen = QPen(QColor(255, 255, 255))
                        pen.setWidthF(2.)
                        item.setPen(pen)
                        textid.setVisible(True)
                    else:
                        pen = QPen(QColor(0, 0, 0))
                        pen.setWidthF(2.)
                        item.setPen(pen)
                        textid.setVisible(False)
                else:
                    sca = 1.
                tr = QTransform()
                tr.scale(sca, sca)
                item.setTransform(tr)
                item.update()

    def coordinates(self, (i, j, k)):
        self._last_mouse_x, self._last_mouse_y, self._last_slice = i, j, k
        self.fill_infos()