Esempio n. 1
0
class PointsField_NodeInstance_MainWidget(QWidget):
    def __init__(self, parent_node_instance):
        super(PointsField_NodeInstance_MainWidget, self).__init__()

        # leave these lines ------------------------------
        self.parent_node_instance = parent_node_instance
        # ------------------------------------------------
        self.setStyleSheet('''
            background-color: #333333;
        ''')

        self.setLayout(QVBoxLayout())
        self.label = QLabel()
        pix = QPixmap(200, 200)
        self.label.setPixmap(pix)
        self.layout().addWidget(self.label)
        self.resize(200, 200)

        self.points = []

    def randomize(self, num_points):
        self.points.clear()

        for i in range(num_points):
            x = random.randint(0, self.label.pixmap().width())
            y = random.randint(0, self.label.pixmap().height())
            self.points.append({'x': x, 'y': y})

        self.draw_points(self.points)

        return self.points

    def draw_points(self, points):
        painter = QPainter(self.label.pixmap())
        painter.setRenderHint(QPainter.Antialiasing)

        painter.setPen(QPen('#333333'))
        painter.setBrush(QColor('#333333'))
        painter.drawRect(self.rect())

        pen = QPen(QColor(255, 255, 255))
        painter.setPen(pen)
        painter.setBrush(QBrush(Qt.white))

        for p in points:
            painter.drawEllipse(p['x'], p['y'], 4, 4)

        self.repaint()

    def get_data(self):
        return {'points': self.points}

    def set_data(self, data):
        self.points = data['points']
        self.draw_points(self.points)

    # optional - important for threading - stop everything here
    def removing(self):
        pass
Esempio n. 2
0
    def testReference(self):
        l = QLabel()
        p = QPixmap()
        l.setPixmap(p) # doesn't increment pixmap ref because this makes a copy
        self.assertEqual(sys.getrefcount(p), 2)

        p = l.pixmap() # this increment the reference because this is an internal pointer
        self.assertEqual(sys.getrefcount(p), 3)

        p2 = l.pixmap()
        self.assertEqual(p, p2)
Esempio n. 3
0
    def testReference(self):
        l = QLabel()
        p = QPixmap()
        l.setPixmap(p) # doesn't increment pixmap ref because this makes a copy
        self.assertEqual(sys.getrefcount(p), 2)

        p = l.pixmap() # this increment the reference because this is an internal pointer
        self.assertEqual(sys.getrefcount(p), 3)

        p2 = l.pixmap()
        self.assertEqual(p, p2)
Esempio n. 4
0
class ShowPoints_NodeInstance_MainWidget(QWidget, MWB):
    def __init__(self, params):
        MWB.__init__(self, params)
        QWidget.__init__(self)

        

        self.setStyleSheet('''
background-color: #0C1C23;
border: none;
        ''')

        self.setLayout(QVBoxLayout())
        self.label = QLabel()
        pix = QPixmap(200, 200)
        self.label.setPixmap(pix)
        #self.setContentMargins(0)
        self.layout().addWidget(self.label)
        self.resize(200, 200)


    def show_points(self, points):
        painter = QPainter(self.label.pixmap())
        painter.setRenderHint(QPainter.Antialiasing)

        painter.setPen(Qt.NoPen)
        painter.setBrush(QColor('#0C1C23'))
        painter.drawRect(self.rect())

        pen = QPen(QColor('#ffffff'))
        painter.setPen(pen)
        painter.setBrush(QBrush(QColor('#ffffff')))

        for p in points:
            painter.drawEllipse(p[0]*self.label.pixmap().width(), p[1]*self.label.pixmap().height(), 2, 2)

        self.repaint()


    def get_data(self):
        return {}

    def set_data(self, data):
        pass


    def remove_event(self):
        pass
    def testReference(self):
        l = QLabel()
        p = QPixmap()
        l.setPixmap(
            p)  # doesn't increment pixmap ref because this makes a copy
        self.assertEqual(sys.getrefcount(p), 2)

        p = l.pixmap()
        # this used to increment the reference because this is
        # an internal pointer, but not anymore since we don't create
        # a copy
        # self.assertEqual(sys.getrefcount(p), 3)
        self.assertEqual(sys.getrefcount(p), 2)

        p2 = l.pixmap()
        self.assertEqual(p, p2)
Esempio n. 6
0
class Viewer(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        self.scaleFactor = 1.0

        self.imageLabel = QLabel()
        self.imageLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.imageLabel.setScaledContents(True)
        self.imageLabel.show()

        self.markers = Markers(self.imageLabel, IMG_FILE[:-3] + "json")

        km = KeysManager(self.markers)

        self.scrollArea = MyScrollArea(self.zoom, self.click, km.keyEventKB)
        self.scrollArea.setWidget(self.imageLabel)
        self.scrollArea.setVisible(False)

    def load_image(self):
        self.imageLabel.setPixmap(load_img())

        self.scrollArea.setVisible(True)
        self.imageLabel.adjustSize()

    def zoom(self, scr_x, scr_y, factor):
        #
        # figure out pixel coordinate where mouse pointer is
        #
        hsb = self.scrollArea.horizontalScrollBar()
        cur_pixel_x = (hsb.value() + scr_x) / self.scaleFactor

        vsb = self.scrollArea.verticalScrollBar()
        cur_pixel_y = (vsb.value() + scr_y) / self.scaleFactor

        #
        # rescale the image
        #
        self.scaleFactor *= factor
        self.imageLabel.resize(self.scaleFactor *
                               self.imageLabel.pixmap().size())
        self.markers.zoom(self.scaleFactor)

        #
        # adjust scroll so the we zoom in/out at where we are pointing
        #
        left_pixel_x = cur_pixel_x - (scr_x / self.scaleFactor)
        hsb.setValue(left_pixel_x * self.scaleFactor)

        top_pixel_y = cur_pixel_y - (scr_y / self.scaleFactor)
        vsb.setValue(top_pixel_y * self.scaleFactor)

    def click(self, x, y):
        x /= self.scaleFactor
        y /= self.scaleFactor

        self.markers.add(x, y, self.scaleFactor)

    def save_markers(self):
        self.markers.save()
Esempio n. 7
0
class ShowPoints_NodeInstance_MainWidget(QWidget):
    def __init__(self, parent_node_instance):
        super(ShowPoints_NodeInstance_MainWidget, self).__init__()

        # leave these lines ------------------------------
        self.parent_node_instance = parent_node_instance
        # ------------------------------------------------

        self.setStyleSheet('''
            background-color: #333333;
        ''')

        self.setLayout(QVBoxLayout())
        self.label = QLabel()
        pix = QPixmap(200,200)
        self.label.setPixmap(pix)
        self.layout().addWidget(self.label)
        self.resize(200, 200)


    def show_points(self, points):
        painter = QPainter(self.label.pixmap())
        painter.setRenderHint(QPainter.Antialiasing)

        painter.setPen(QPen('#333333'))
        painter.setBrush(QColor('#333333'))
        painter.drawRect(self.rect())

        pen = QPen(QColor(255, 255, 255))
        painter.setPen(pen)
        painter.setBrush(QBrush(Qt.white))

        for p in points:
            painter.drawEllipse(p['x']*self.label.pixmap().width(), p['y']*self.label.pixmap().height(), 4, 4)

        self.repaint()


    def get_data(self):
        return {}

    def set_data(self, data):
        pass


    def remove_event(self):
        pass
Esempio n. 8
0
class %CLASS%(QWidget, MWB):
    def __init__(self, params):
        MWB.__init__(self, params)
        QWidget.__init__(self)

        

        self.setStyleSheet('''
            background-color: #333333;
        ''')

        self.setLayout(QVBoxLayout())
        self.label = QLabel()
        pix = QPixmap(200,200)
        self.label.setPixmap(pix)
        self.layout().addWidget(self.label)
        self.resize(200, 200)


    def show_points(self, points):
        painter = QPainter(self.label.pixmap())
        painter.setRenderHint(QPainter.Antialiasing)

        painter.setPen(QPen('#333333'))
        painter.setBrush(QColor('#333333'))
        painter.drawRect(self.rect())

        pen = QPen(QColor(255, 255, 255))
        painter.setPen(pen)
        painter.setBrush(QBrush(Qt.white))

        for p in points:
            painter.drawEllipse(p['x']*self.label.pixmap().width(), p['y']*self.label.pixmap().height(), 4, 4)

        self.repaint()


    def get_data(self):
        return {}

    def set_data(self, data):
        pass


    def remove_event(self):
        pass
class QLabelTest(UsesQApplication):
    '''Test case for calling QLabel.setPixmap'''

    def setUp(self):
        super(QLabelTest, self).setUp()
        self.label = QLabel()

    def tearDown(self):
        del self.label
        super(QLabelTest, self).tearDown()

    def testSetPixmap(self):

        p1 = QPixmap(5, 5)
        p2 = QPixmap(10, 10)

        self.label.setPixmap(p1)
        self.assertIsNotNone(self.label.pixmap())


        # PYSIDE-150:
        #   When a new QPixmap is assigned to a QLabel,
        #   the previous one needs to be cleared.
        #   This means we should not keep a copy of the QPixmap
        #   on Python-side.

        # Getting pointer to the QPixmap
        ret_p = self.label.pixmap()
        self.assertIsNot(p1, ret_p)
        # Save the address of the pointer
        ret_p_addr = shiboken.getCppPointer(ret_p)
        # Remove the QPixmap
        del ret_p
        # Set new QPixmap
        self.label.setPixmap(p2)

        # There should be no pointers remaining with the same
        # address that our QPixmap p1 because it was deleted
        # using `del ret_p`
        self.assertTrue(all(shiboken.getCppPointer(o) != ret_p_addr
                   for o in shiboken.getAllValidWrappers()))
Esempio n. 10
0
class ShowPoints_NodeInstance_MainWidget(QWidget):
    def __init__(self, parent_node_instance):
        super(ShowPoints_NodeInstance_MainWidget, self).__init__()

        # leave these lines ------------------------------
        self.parent_node_instance = parent_node_instance
        self.package_path = os.path.join(
            os.path.dirname(os.path.abspath(__file__)), '../../../')
        # ------------------------------------------------

        self.setStyleSheet('''
            background-color: #333333;
        ''')

        self.setLayout(QVBoxLayout())
        self.label = QLabel()
        pix = QPixmap(200, 200)
        self.label.setPixmap(pix)
        self.layout().addWidget(self.label)
        self.resize(200, 200)

        self.points = []

    def show_points(self, points):
        self.points = points

        painter = QPainter(self.label.pixmap())
        painter.setRenderHint(QPainter.Antialiasing)

        painter.setPen(QPen('#333333'))
        painter.setBrush(QColor('#333333'))
        painter.drawRect(self.rect())

        pen = QPen(QColor(255, 255, 255))
        painter.setPen(pen)
        painter.setBrush(QBrush(Qt.white))

        for p in self.points:
            painter.drawEllipse(p['x'], p['y'], 4, 4)

        self.repaint()

    def get_data(self):
        data = {'pints': self.points}
        # ...
        return data

    def set_data(self, data):
        self.points = data['points']

    # optional - important for threading - stop everything here
    def removing(self):
        pass
Esempio n. 11
0
class CameraFeed(QWidget):
    def __init__(self, id, app: QApplication, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.id = id
        self.app = app
        self.box = QHBoxLayout()
        self.setLayout(self.box)
        self.video_frame = QLabel()
        self.video_frame.setScaledContents(True)
        self.video_frame.setMinimumSize(1, 1)
        self.video_frame.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)
        self.setMinimumSize(1, 1)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.box.addWidget(self.video_frame)
        self.box.setContentsMargins(0, 0, 0, 0)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

    def startReceiving(self):
        self.feed_receiver = FeedReceiver(self, self.id, self.app)
        self.setVideoFramePlaceHolder()
        self.feed_receiver.signals.imageReady.connect(self.updateImage)
        self.feed_receiver.start()

    def updateImage(self, data: QImage):
        img = QPixmap()
        img.convertFromImage(data)
        self.video_frame.setPixmap(img)

    def setVideoFramePlaceHolder(self):
        img = QImage(self.feed_receiver.width,
                     self.feed_receiver.width // 16 * 9,
                     QImage.Format_Grayscale8)
        img.fill(2)
        self.updateImage(img)

    def saveImage(self, name=None):
        fn = 'img/' + (name or datetime.datetime.now().isoformat()) + '.jpg'
        print(fn)
        self.video_frame.pixmap().save(fn, 'JPEG', 100)
Esempio n. 12
0
class WidgetTest(QWidget):
    def __init__(self):
        super().__init__()
        self.label = QLabel()
        canvas = QPixmap(400, 300)
        canvas.fill(Qt.white)
        self.label.setPixmap(canvas)

        self.draw_something()


    def draw_something(self):
        painter = QPainter(self.label.pixmap())

        names=["Empty","N","E","EN","S","NS","ES","ENS","W","NW","EW","ENW","SW","NSW","ESW","ENSW"]
        images = [QtGui.QPixmap("images/"+name+".bmp", format="bmp")  for name in names]
        painter.drawPixmap(QtCore.QPoint(0,0) , images[9])
        painter.drawPixmap(QtCore.QPoint(50,0) , images[3])
        painter.drawPixmap(QtCore.QPoint(0,50) , images[13])
        painter.drawPixmap(QtCore.QPoint(50,50) , images[6])
        painter.end()
Esempio n. 13
0
class drawForm (baseForm):
    """
    Drawing form
    """
    @classmethod
    def getNewWindow(cls, targetImage=None, axeSize=200, layer=None, parent=None):
        wdgt = drawForm(targetImage=targetImage, axeSize=axeSize, layer=layer, parent=parent)
        wdgt.setWindowTitle(layer.name)
        return wdgt

    def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None):
        super().__init__(layer=layer, targetImage=targetImage, parent=parent)
        self.options = None
        pushButton1 = QPushButton(' Undo ')
        pushButton1.adjustSize()
        pushButton2 = QPushButton(' Redo ')
        pushButton2.adjustSize()

        pushButton1.clicked.connect(self.undo)
        pushButton2.clicked.connect(self.redo)

        spacingSlider = QSlider(Qt.Horizontal)
        spacingSlider.setObjectName('spacingSlider')
        spacingSlider.setRange(1,60)
        spacingSlider.setTickPosition(QSlider.TicksBelow)
        spacingSlider.setSliderPosition(10)
        spacingSlider.sliderReleased.connect(self.parent().label.brushUpdate)
        self.spacingSlider = spacingSlider

        jitterSlider = QSlider(Qt.Horizontal)
        jitterSlider.setObjectName('jitterSlider')
        jitterSlider.setRange(0, 100)
        jitterSlider.setTickPosition(QSlider.TicksBelow)
        jitterSlider.setSliderPosition(0)
        jitterSlider.sliderReleased.connect(self.parent().label.brushUpdate)
        self.jitterSlider = jitterSlider

        orientationSlider = QSlider(Qt.Horizontal)
        orientationSlider.setObjectName('orientationSlider')
        orientationSlider.setRange(0, 360)
        orientationSlider.setTickPosition(QSlider.TicksBelow)
        orientationSlider.setSliderPosition(180)
        orientationSlider.sliderReleased.connect(self.parent().label.brushUpdate)
        self.orientationSlider = orientationSlider

        # sample
        self.sample = QLabel()
        #self.sample.setMinimumSize(200, 100)
        pxmp = QPixmap(250,100)
        pxmp.fill(QColor(255, 255, 255, 255))
        self.sample.setPixmap(pxmp)
        qpp = QPainterPath()
        qpp.moveTo(QPointF(20, 50))
        qpp.cubicTo(QPointF(80, 25), QPointF(145, 70), QPointF(230, 60))  # c1, c2, endPoint
        self.samplePoly = qpp.toFillPolygon(QTransform())
        # we want an unclosed polygon
        self.samplePoly.removeLast()

        # layout
        l = QVBoxLayout()
        l.setAlignment(Qt.AlignTop)
        hl = QHBoxLayout()
        hl.setAlignment(Qt.AlignHCenter)
        hl.addWidget(pushButton1)
        hl.addWidget(pushButton2)
        l.addLayout(hl)
        l.addWidget(QLabel('Brush Dynamics'))
        hl1 = QHBoxLayout()
        hl1.addWidget(QLabel('Spacing'))
        hl1.addWidget(spacingSlider)
        l.addLayout(hl1)
        hl2 = QHBoxLayout()
        hl2.addWidget(QLabel('Jitter'))
        hl2.addWidget(jitterSlider)
        l.addLayout(hl2)
        hl3 = QHBoxLayout()
        hl3.addWidget(QLabel('Orientation'))
        hl3.addWidget(self.orientationSlider)
        l.addLayout(hl3)
        l.addWidget(self.sample)
        self.setLayout(l)
        self.adjustSize()

        self.setDefaults()
        self.setWhatsThis(
                        """
                        <b>Drawing :</b><br>
                          Choose a brush family, flow, hardness and opacity.
                        """
                        )  # end of setWhatsThis

    def setDefaults(self):
        try:
            self.dataChanged.disconnect()
        except RuntimeError:
            pass
        self.dataChanged.connect(self.updateLayer)
        self.updateSample()

    def updateLayer(self):
        """
        dataChanged slot
        """
        l = self.layer
        # l.tool.setBaseTransform()
        l.applyToStack()
        l.parentImage.onImageChanged()

    def updateSample(self):
        pxmp = self.sample.pixmap()
        pxmp.fill(QColor(0,0,0,0))
        brushFamily.brushStrokePoly(pxmp, self.samplePoly, self.layer.brushDict)
        self.sample.repaint()

    def undo(self):
        try:
            self.layer.sourceImg = self.layer.history.undo(saveitem=self.layer.sourceImg.copy()).copy()  # copy is mandatory
            self.updateLayer()
        except ValueError:
            pass

    def redo(self):
        try:
            self.layer.sourceImg = self.layer.history.redo().copy()  # copy is mandatory
            self.updateLayer()
        except ValueError:
            pass

    def reset(self):
        self.layer.tool.resetTrans()
Esempio n. 14
0
class %CLASS%(QWidget, MWB):
    def __init__(self, params):
        MWB.__init__(self, params)
        QWidget.__init__(self)

        

        self.setStyleSheet('''
            background-color: #333333;
        ''')

        self.setLayout(QVBoxLayout())
        # settings widget
        settings_widget = QWidget()
        settings_widget.setLayout(QHBoxLayout())
        self.connect_lines_check_box = QCheckBox('connect lines linear')
        settings_widget.layout().addWidget(self.connect_lines_check_box)
        self.layout().addWidget(settings_widget)
        # points area
        self.label = QLabel()
        pix = QPixmap(300,200)
        self.label.setPixmap(pix)
        self.layout().addWidget(self.label)

        self.resize(300, 200)

        self.values = []

    def update(self, new_vals):
        self.values = new_vals
        if len(self.values) == 0:
            return

        painter = QPainter(self.label.pixmap())
        painter.setRenderHint(QPainter.Antialiasing)

        painter.setPen(QPen('#333333'))
        painter.setBrush(QColor('#333333'))
        painter.drawRect(self.label.rect())

        pen = QPen(QColor(255, 255, 255))
        pen.setWidth(1)
        painter.setPen(pen)
        painter.setBrush(QBrush(Qt.white))

        x_old = -1
        y_old = -1

        div = max(self.values)

        for i in range(len(self.values)):
            v = self.values[i]
            x = i * (self.label.width()/len(self.values))
            y = self.label.height()-self.label.height()*v/div

            if self.connect_lines_check_box.isChecked() and i>0:
                painter.drawLine(x_old, y_old, x, y)
            else:

                painter.drawEllipse(x-1, y-1, 2, 2)

            x_old = x
            y_old = y

        self.repaint()

    def get_data(self):
        return {'connect lines linear': self.connect_lines_check_box.isChecked()}

    def set_data(self, data):
        self.connect_lines_check_box.setChecked(data['connect lines linear'])


    def remove_event(self):
        pass
Esempio n. 15
0
class Dicom_Browser(QWidget):
    draw_state: bool = False
    erase_state: bool = False
    point_pick: bool = False
    nj_points = []
    nj_points_ready = Signal()
    series_id: str
    mask: np.array

    def __init__(self):
        super().__init__()
        self.initUI()
        self.rubberBand: QRubberBand = QRubberBand(QRubberBand.Line,
                                                   self.image_label)

    def initUI(self):
        self.image = DicomImage()
        self.pixmap = QPixmap()

        self.image_label = QLabel()
        self.image_label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self.image_label.setSizePolicy(QSizePolicy.Preferred,
                                       QSizePolicy.Preferred)
        self.image_label.setPixmap(self.pixmap)

        self.tags_view = Dicom_Tags_Widget([''])
        self.tools = Dicom_ImageToolsWidget()

        self.tabs_widget = self.__inti_tab_widget__(
            [self.tags_view, self.tools])
        self.tabs_widget.setMaximumWidth(600)

        image_layout = QVBoxLayout()
        image_layout.setContentsMargins(0, 0, 0, 0)
        image_layout.addWidget(self.image_label)

        image_group = QGroupBox()
        image_group.setStyleSheet("margin:0; padding: 0; border: 0;")
        image_group.setContentsMargins(0, 0, 0, 0)
        image_group.setLayout(image_layout)

        splitter = QSplitter()
        splitter.addWidget(image_group)
        splitter.addWidget(self.tabs_widget)

        layout = QHBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(splitter)

        self.tools.pen_selected.connect(self.pen_select)
        self.tools.erase_btn.clicked.connect(self.erase_btn_click)
        self.tools.slider.valueChanged.connect(self.slider_changed)
        self.tools.processing_btn.clicked.connect(self.send_nn_segmentation)
        self.tools.load_mask_btn.clicked.connect(self.load_nifti_mask_click)
        self.tools.save_mask_btn.clicked.connect(self.save_nifti_mask_click)
        self.tools.nj_segment_btn.clicked.connect(self.nj_segment_click)
        self.nj_points_ready.connect(self.nj_segment)

    def set_image(self):
        self.pixmap = QPixmap.fromImage(self.image.get_slice_as_QImage())
        self.image_label.setPixmap(self.pixmap)
        self.set_tags()

    def update_mask(self):
        self.mask = np.zeros([
            self.image.get_shape()[0],
            self.image.get_shape()[1],
            self.image.get_slice_amount()
        ], np.int)
        self.draw_mask()

    def load_series(self, path):
        if isinstance(path, list):
            if len(path) == 1:
                path = path[0]
            else:
                path = os.path.dirname(path[0]) + '/'

        self.image.load_dicom(path)
        self.set_image()
        if self.image.is_series():
            self.set_slider_maximum()
            self.tools.slider.setDisabled(False)
        else:
            self.tools.slider.setDisabled(True)
        self.set_tags()
        self.update_tags()
        self.update_mask()

    def set_tags(self):
        result = []
        for elem in self.image.slice().iterall():
            result.append([str(elem.tag), elem.name, str(elem.value)])

        return result

    def update_tags(self):
        self.tags_view.model.update(self.set_tags())
        self.tags_view.model.layoutChanged.emit()

    # MOUSE EVENTS

    def wheelEvent(self, event):

        if self.image_label.underMouse():
            delta = event.delta()
            if delta > 0:
                self.image.next_slice()
            elif delta < 0:
                self.image.pre_slice()

            self.set_image()
            self.tools.slider.setSliderPosition(self.image.get_slice_index())
            self.update_tags()
            self.draw_mask()
            self.update()

    def mousePressEvent(self, e):
        if self.image_label.underMouse():
            if self.draw_state:
                self.pos = self.point_on_image(e)
                self.set_mask_pixels(self.pos)
                self.draw_mask_point(self.pos)
                self.update()
            elif self.erase_state:
                self.pos = self.point_on_image(e)
                self.set_mask_pixels(self.pos, 0)
                self.set_image()
                self.draw_mask()
                self.update()
            elif self.point_pick:
                point = [
                    self.point_on_image(e).x(),
                    self.point_on_image(e).x(),
                    self.image.get_slice_index()
                ]
                self.nj_points.append(point)
                if len(self.nj_points) == 2:
                    self.point_pick = False
                    QApplication.restoreOverrideCursor()
                    self.nj_points_ready.emit()
            else:
                self.origin = e.pos()
                if not self.rubberBand:
                    self.rubberBand = QRubberBand(QRubberBand.Rectangle, self)
                self.rubberBand.setGeometry(QRect(self.origin, QSize()))
                self.rubberBand.show()

    def mouseMoveEvent(self, e):
        if self.image_label.underMouse():
            if self.draw_state:
                self.pos = self.point_on_image(e)
                self.set_mask_pixels(self.pos)
                # self.mask[int(self.pos.y())][int(self.pos.x())][self.image.get_slice_index()] = 255
                self.draw_mask_point(self.pos)
                self.update()
            elif self.erase_state:
                self.pos = self.point_on_image(e)
                self.set_mask_pixels(self.pos, 0)
                # self.mask[int(self.pos.y())][int(self.pos.x())][self.image.get_slice_index()] = 0
                self.set_image()
                self.draw_mask()
                self.update()
            else:
                self.rubberBand.setGeometry(
                    QRect(self.origin, e.pos()).normalized())

    def mouseReleaseEvent(self, event):
        if self.image_label.underMouse():
            if self.draw_state:
                return
            self.rubberBand.hide()

    def keyPressEvent(self, event):
        # Re-direct ESC key to closeEvent
        if event.key() == Qt.Key_Escape:
            if self.point_pick:
                self.point_pick = not self.point_pick
                QApplication.restoreOverrideCursor()

    # IMAGE SLIDER

    def set_slider_maximum(self):
        self.tools.set_slider_maximum(self.image.get_slice_amount() - 1)

    def slider_changed(self):
        self.image.set_slice_index(self.tools.slider.value())
        self.set_image()
        self.update_tags()
        self.draw_mask()
        self.update()

    def pen_select(self):
        self.draw_state = self.tools.pen_btn.isChecked()

    def __init_slider(self) -> QSlider:
        slider = QSlider()
        slider.setOrientation(Qt.Horizontal)
        slider.setMaximumWidth(self.image_label.width())
        slider.setMinimum(0)
        slider.setMaximum(self.image.get_slice_amount())
        slider.setTickInterval(1)
        slider.setSliderPosition(1)
        slider.valueChanged.connect(self.slider_changed)
        if not self.image.is_series():
            slider.setHidden(True)

        return slider

    def __inti_tab_widget__(self, widgets: list) -> object:
        tabs_widget = QTabWidget()
        tabs_widget.setTabPosition(QTabWidget.South)
        tabs_widget.setMinimumWidth(50)
        for wdg in widgets:
            tabs_widget.addTab(wdg, wdg.tab_name)

        return tabs_widget

    # MASKING
    def send_nn_segmentation(self):
        # Dicom_BrowserCtrl.save_mask(self, self.mask, 'res/H-DenseUNet-master_v1/livermask/0.nii')
        ctrl = Dicom_BrowserCtrl()
        head, tail = os.path.split(os.path.split(self.image.dicom_dir)[0])
        ctrl.image_to_nn(tail, self.mask,
                         self.image.get_shape()[0],
                         self.image.get_shape()[1])

    def set_mask(self):
        img = self.__arr_to_QImage(self.mask[:, :,
                                             self.image.get_slice_index()].T())
        self.mask_pixmap = QPixmap.fromImage(img)
        self.mask_label.setPixmap(self.mask_pixmap)

    def draw_mask(self):
        try:
            if not np.array_equal(
                    self.mask[:, :, self.image.get_slice_index()],
                    np.zeros(
                        [self.image.get_shape()[0],
                         self.image.get_shape()[1]])):
                it = np.nditer(self.mask[:, :,
                                         self.image.get_slice_index()],
                               flags=['multi_index'])
                for pixel in it:
                    if pixel != 0:
                        point = QPoint(it.multi_index[1], it.multi_index[0])
                        self.draw_mask_point(point, 1)
        except Exception:
            self.update_mask()

    def set_mask_pixels(self, center_point: QPoint, value=255):
        it = np.nditer(self.mask[:, :, self.image.get_slice_index()],
                       flags=['multi_index'])
        size = int(self.tools.get_size() / 2) - 1
        x = center_point.x()
        y = center_point.y()
        for pixel in it:
            if x - size <= it.multi_index[
                    1] <= x + size and y + size >= it.multi_index[
                        0] >= y - size:
                self.mask[it.multi_index[0]][it.multi_index[1]][
                    self.image.get_slice_index()] = value

    def draw_mask_point(self, point, pen_size: int = None):
        if pen_size is None:
            pen_size = self.tools.get_size()
        painter = QPainter(self.image_label.pixmap())
        painter.setPen(
            QPen(self.tools.mask_color, pen_size, Qt.SolidLine, Qt.SquareCap,
                 Qt.RoundJoin))
        painter.drawPoint(point)

    def erase_btn_click(self):
        self.erase_state = not self.erase_state
        self.tools.erase_btn.setChecked(self.erase_state)
        if self.draw_state:
            self.draw_state = not self.draw_state
            self.tools.pen_btn.setChecked(self.draw_state)

    def load_nifti_mask_click(self):
        ctrl = Dicom_BrowserCtrl()
        self.mask = ctrl.load_nitfit_mask()
        self.draw_mask()
        self.update()

    def save_nifti_mask_click(self):
        Dicom_BrowserCtrl.save_mask(self, self.mask)

    def nj_segment_click(self):
        QApplication.setOverrideCursor(QCursor(Qt.CrossCursor))
        self.point_pick = True

    def nj_segment(self):
        ctrl = Dicom_BrowserCtrl()
        ctrl.nj_segment(self.image.dicom_dir, self.nj_points)
        self.nj_points = []
        self.mask = ctrl.load_nitfit_mask('data/.tmp.nii')
        self.draw_mask()
        self.update()

    def point_on_image(self, e):
        x_offset, y_offset = self.__image_offset()
        pos = QPoint(e.x() - x_offset, e.y() - y_offset)

        return pos

    def __image_offset(self):
        x_offset = (self.image_label.width() - self.pixmap.width()) / 2
        y_offset = (self.image_label.height() - self.pixmap.height()) / 2
        return x_offset, y_offset

    def __arr_to_QImage(self, arr_img):
        img = PIL.Image.fromarray(arr_img)
        img = img.convert("L")
        result = ImageQt(img)

        return result
Esempio n. 16
0
class SandyScreen(QWidget):
    def __init__(self, root):
        QWidget.__init__(self)
        self.root = root

        # Setting state vars
        self.app_running = True
        self.ctrl_down = False
        self.in_fullscreen = False
        self.in_menu = False
        self.on_pause = True

        # Setting animation vars
        self.timer_delay = 10
        self.phase = 1
        self.delta_per_tick = 1 / 30
        self.xpmsz = None
        self.geo = [0, 0, 0, 0]

        # Creating timer and sandpile
        self.timer = QTimer(self)
        self.seed = None
        self.piletype = None
        self.sandpile = None
        self.reroll_pile()

        # Generating pause icon
        self.pause_icon = Image.new('RGBA', size=(60, 60))
        for i in range(60):
            for j in range(60):
                self.pause_icon.putpixel(
                    (j, i), (255, 255, 255, 0 if 20 < j < 40 else 100))

        # Initialising UI and running
        self.init_ui()
        self.show()

    def init_ui(self):
        self.setMinimumSize(600, 400)
        self.setWindowTitle('Sandy Screen')

        # Menu widget
        self.menu = SandyMenu(self)

        # Sandbox container widget and its background and canvas label stack
        self.sandbox = QWidget(self)
        self.sandbox.setGeometry(0, 0, 600, 400)
        self.sandbox_bg = QLabel(self.sandbox)
        self.sandbox_bg.setGeometry(0, 0, 600, 400)
        self.sandbox_bg.setPixmap(
            QPixmap(['1 1 1 1', '1 c #000000',
                     '1']).scaled(self.sandbox_bg.size()))
        self.canvases = [QLabel(self.sandbox), QLabel(self.sandbox)]
        for c in self.canvases:
            c.setAlignment(Qt.AlignCenter)
            c.setGeometry(0, 0, 600, 400)
        self.canvases[1].setPixmap(QPixmap(generate_xpm(self.sandpile)[0]))
        self.sandpile.topple_step()
        self.canvases[0].setPixmap(QPixmap(generate_xpm(self.sandpile)[0]))

        # Opacity effect on the upper frame label
        self.opeff = QGraphicsOpacityEffect(self.canvases[-1])
        self.opeff.setOpacity(1)
        self.canvases[-1].setGraphicsEffect(self.opeff)

        # Main stack layout
        self.layout = QStackedLayout(self)
        self.layout.addWidget(self.sandbox)
        self.layout.addWidget(self.menu)

        # Overlay pause icon label
        self.pause_label = QLabel(self)
        self.pause_label.setAlignment(Qt.AlignCenter)
        self.pause_label.setPixmap(QPixmap(ImageQt.ImageQt(self.pause_icon)))

    def restart_pile(self):
        del self.sandpile
        self.sandpile = self.piletype(copy.deepcopy(self.seed),
                                      frozen=True,
                                      timed=False,
                                      vocal=False)
        print('restart called')

    def reroll_pile(self, piletype=None, seed=None):
        if seed:
            self.seed = seed
        else:
            v = random.randint(8, 33)
            self.seed = [[v for j in range(_X)] for i in range(_Y)]
        if piletype:
            self.piletype = piletype
        else:
            v = random.randint(0, 3)
            self.piletype = [t4f, t6hf, t6vf, t8f][v]
        self.sandpile = self.piletype(copy.deepcopy(self.seed),
                                      frozen=True,
                                      timed=False,
                                      vocal=False)

    def run(self):
        self.root.exec_()

    def closeEvent(self, event):
        self.timer.stop()
        self.app_running = False

    def keyPressEvent(self, event):
        k = event.key()
        if k == 16777236:
            self.update_sandbox(1)  #
        if k == _CTRL:
            self.ctrl_down = True
        if self.ctrl_down:
            if k == _M:
                self.toggle_menu()  # Menu toggled on Ctrl+M
            elif k == _R:
                self.reroll_pile()
        else:
            if k == _F11:
                self.toggle_fullscreen()
            elif k == _SPACE and not self.in_menu:
                self.toggle_pause()

    def keyReleaseEvent(self, event):
        if event.key() == _CTRL:
            self.ctrl_down = False

    def resizeEvent(self, event):
        self.pause_label.setGeometry(self.rect())
        sbg = self.sandbox.geometry()
        sbs = self.sandbox.size()
        self.sandbox_bg.setGeometry(sbg)
        self.sandbox_bg.setPixmap(self.sandbox_bg.pixmap().scaled(
            self.sandbox_bg.size()))
        for c in self.canvases:
            c.setGeometry(sbg)
            c.setPixmap(c.pixmap().scaled(sbs, Qt.KeepAspectRatio))
        ### Fix this.

    def toggle_fullscreen(self):
        self.in_fullscreen = not self.in_fullscreen
        self.showFullScreen() if self.in_fullscreen else self.showNormal()

    def toggle_menu(self):
        self.in_menu = not self.in_menu
        if self.in_menu:
            self.layout.setCurrentIndex(1)
            self.pause_label.setVisible(False)
            self.on_pause = True
            self.root.restoreOverrideCursor()
        else:
            self.layout.setCurrentIndex(0)
            if self.on_pause:
                self.pause_label.raise_()
                self.pause_label.setVisible(True)
            else:
                self.root.setOverrideCursor(Qt.BlankCursor)
        self.resizeEvent(None)

    def toggle_pause(self):
        self.on_pause = not self.on_pause
        if self.on_pause:
            self.timer.stop()
            self.pause_label.raise_()
            self.pause_label.setVisible(True)
            self.root.restoreOverrideCursor()
        else:
            self.pause_label.setVisible(False)
            self.timer.singleShot(self.timer_delay,
                                  lambda: self.update_sandbox(0))
            self.root.setOverrideCursor(Qt.BlankCursor)

    def update_sandbox(self, mode):
        if not self.in_menu:
            if mode == self.on_pause:
                self.phase -= self.delta_per_tick
                if self.phase <= 0:
                    self.canvases[-1].setPixmap(self.canvases[0].pixmap())
                    self.phase = 1
                    self.opeff.setOpacity(self.phase)
                    if not self.sandpile.topple_step() and not self.on_pause:
                        self.toggle_pause()
                    xpm, sz = generate_xpm(self.sandpile)
                    self.canvases[0].setPixmap(
                        QPixmap(xpm).scaled(self.sandbox.size(),
                                            Qt.KeepAspectRatio))
                else:
                    self.opeff.setOpacity(
                        math.pow(math.sin(math.pi * self.phase / 2), 2))
                if mode == 0 and self.app_running:
                    self.timer.singleShot(self.timer_delay,
                                          lambda: self.update_sandbox(0))
Esempio n. 17
0
class Canvas (QWidget):
    def __init__(self):
        QWidget.__init__(self)

        self.file = "mug.webp"

        self.__img = cv2.imread(self.file)
        self.__mask = np.zeros(1)
        self.original = cv2.imread(self.file)
        self.__thirdChannelMask = np.dstack((self.__mask, self.__mask, self.__mask))

        self.__nseg = 1
        self.__sig = 1
        self.__comp = 1

        self.nSlider = QSlider(orientation=Qt.Horizontal)
        self.sigSlider = QSlider(orientation=Qt.Horizontal)
        self.thicSlider = QSlider(orientation=Qt.Horizontal)

        self.resize_spinbox = QSpinBox(self)
        self.resize_spinbox.setRange(1, 100)
        self.resize_spinbox.setValue(100)
        self.resize_spinbox.setSuffix(" %")

        self.double_spin_width = QDoubleSpinBox(self)
        self.double_spin_width.setSuffix(" px")
        self.double_spin_width.setValue(0)
        self.double_spin_width.setRange(1, 2000)

        self.double_spin_height = QDoubleSpinBox(self)
        self.double_spin_height.setSuffix(" px")
        self.double_spin_height.setValue(0)
        self.double_spin_height.setRange(1, 2000)

        self.zeroModeCheck = QCheckBox("Usar SLIC0")

        self.__highlightcolor = QColor(255, 255, 255)

        self.__transparency = 0.5

        self.__AllColors = [self.__highlightcolor.toTuple()[:3]]

        nLabel = QLabel("Numero de segmentos:")
        sigLabel = QLabel("Sigma:")
        thicLabel = QLabel("Compactação:")
        resizeLabel = QLabel("Fator de resize da image:")
        makssizeLabel = QLabel("Dimensão da mascara de saída:")

        self.__label = QLabel()

        nLabel.setToolTip("O número aproximado de labels da imagem segmentada")
        sigLabel.setToolTip("A largura da Gaussiana")
        thicLabel.setToolTip("Equilibra a proximidade das cores e a proximidade do espaço, maiores valores tornam os Superpixels mais quadrados")

        self.nSlider.setMinimum(1)
        self.nSlider.setMaximum(100)

        self.sigSlider.setMinimum(1)
        self.sigSlider.setMaximum(100)

        self.thicSlider.setMinimum(1)
        self.thicSlider.setMaximum(100)

        glayout1 = QGridLayout()
        glayout1.addWidget(nLabel, 0, 0)
        glayout1.addWidget(self.nSlider, 0, 1)
        glayout1.addWidget(sigLabel, 1, 0)
        glayout1.addWidget(self.sigSlider, 1, 1)
        glayout1.addWidget(thicLabel, 2, 0)
        glayout1.addWidget(self.thicSlider, 2, 1)

        glayout2 = QGridLayout()
        glayout2.addWidget(resizeLabel, 0, 0)
        glayout2.addWidget(self.resize_spinbox, 0, 1)
        glayout2.addWidget(self.zeroModeCheck, 0, 2)
        glayout2.addWidget(makssizeLabel, 1, 0)
        glayout2.addWidget(self.double_spin_width, 1, 1)
        glayout2.addWidget(self.double_spin_height, 1, 2)

        glayout2.setColumnStretch(3, 1)

        self.__label.setAlignment(Qt.AlignLeft | Qt.AlignTop)

        mainlayout = QVBoxLayout()
        mainlayout.addLayout(glayout1)
        mainlayout.addLayout(glayout2)
        mainlayout.addStretch(1)
        mainlayout.addWidget(self.__label)
        mainlayout.addStretch(1)
        mainlayout.setAlignment(Qt.AlignCenter)
        self.setLayout(mainlayout)

        self.nSlider.sliderReleased.connect(self.onNsegChange)
        self.sigSlider.sliderReleased.connect(self.onSigChange)
        self.thicSlider.sliderReleased.connect(self.onCompChange)

        self.__label.mousePressEvent = self.Highlight

        self.resize_spinbox.valueChanged.connect(self.Resize)

        self.open_image(self.__img)

    def getBackground(self):
        mask = self.__thirdChannelMask.copy()
        mask_r = mask[:, :, 2]
        mask_g = mask[:, :, 1]
        mask_b = mask[:, :, 0]

        offImage = list()
        for color in self.__AllColors:
            b_off = mask_b != color[2]
            g_off = mask_g != color[1]
            r_off = mask_r != color[0]
            aux = np.logical_and(b_off, g_off)
            offImage.append(np.logical_and(aux, r_off))

        final = offImage[0]
        for cut in offImage:
            final = np.logical_or(final, cut)

        return final

    def changeImage(self):
        self.__mask = slic(self.__img, n_segments=self.__nseg, compactness=self.__comp, sigma=self.__sig, convert2lab=True, slic_zero=self.zeroModeCheck.isChecked())

        mask = self.__mask.copy()
        mask = np.dstack((mask, mask, mask))
        mask = img_as_ubyte(mask)

        self.__thirdChannelMask = mask
        img = cv2.addWeighted(self.__img, 1, mask, 0.5, 0)
        marc_img = mark_boundaries(img, self.__mask)
        self.open_image(marc_img)

    def load_image(self):
        self.__img = cv2.imread(self.file)
        self.original = self.__img
        self.double_spin_width.setValue(self.__img.shape[1])
        self.double_spin_height.setValue(self.__img.shape[0])

        val = self.resize_spinbox.value()
        newDim = int(self.__img.shape[1]*val/100), int(self.__img.shape[0]*val/100)

        self.__img = cv2.resize(self.__img, newDim)

        self.open_image(self.__img)

    def open_image(self, img):
        if img.shape[2] == 4:
            qformat = QImage.Format_RGBA8888
        else:
            qformat = QImage.Format_RGB888

        copy = img_as_ubyte(img)
        qimg = QImage(copy.data, copy.shape[1], copy.shape[0], copy.strides[0], qformat).rgbSwapped()
        pixmap = QPixmap.fromImage(qimg)

        self.__label.setPixmap(pixmap)
        self.__label.adjustSize()

    @Slot()
    def onNsegChange(self):
        self.__nseg = self.nSlider.value()
        self.changeImage()

    @Slot()
    def onSigChange(self):
        self.__sig = self.sigSlider.value()
        self.changeImage()

    @Slot()
    def onCompChange(self):
        self.__comp = self.thicSlider.value()
        self.changeImage()

    @Slot()
    def onFileOpen(self):
        self.thicSlider.setValue(1)
        self.nSlider.setValue(1)
        self.sigSlider.setValue(1)
        diag = QFileDialog()
        file = diag.getOpenFileName()[0]
        if file != "":
            self.file = file
            self.load_image()

    @Slot()
    def onSaveFile(self):
        diag = QFileDialog()
        file = diag.getSaveFileName()[0]
        if self.file != "":
            self.__label.pixmap().save(file)

    @Slot()
    def onSaveMask(self):
        diag = QFileDialog()
        file = diag.getSaveFileName()[0]
        final_img = cv2.resize(self.__mask, (self.double_spin_width.value(), self.double_spin_height.value()))

        if file != "":
            cv2.imwrite(file, final_img)

    @Slot()
    def Highlight(self, e):
        if e.x() < 0 or e.x() > self.__img.shape[1] or e.y() < 0 or e.y() > self.__img.shape[0]:
            return

        self.__mask = flood_fill(self.__mask, (e.y(), e.x()), 255)

        self.__thirdChannelMask[:, :, 2] = flood_fill(self.__thirdChannelMask[:, :, 2], (e.y(), e.x()), self.__highlightcolor.red())
        self.__thirdChannelMask[:, :, 1] = flood_fill(self.__thirdChannelMask[:, :, 1], (e.y(), e.x()), self.__highlightcolor.green())
        self.__thirdChannelMask[:, :, 0] = flood_fill(self.__thirdChannelMask[:, :, 0], (e.y(), e.x()), self.__highlightcolor.blue())

        img = cv2.addWeighted(self.__img, 1, self.__thirdChannelMask, self.__transparency, 0)
        marc_img = mark_boundaries(img, self.__mask)
        self.open_image(marc_img)


    @Slot()
    def exportBinary(self):
        diag = QFileDialog()
        file = diag.getSaveFileName()[0]
        mask = self.__thirdChannelMask.copy()
        final = self.getBackground()
        b = mask[:, :, 0]
        g = mask[:, :, 1]
        r = mask[:, :, 2]
        b[final] = 0
        g[final] = 0
        r[final] = 0

        final_img = cv2.resize(mask, (int(self.double_spin_width.value()), int(self.double_spin_height.value())))
        if file != "":
            cv2.imwrite(file, final_img)

    @Slot()
    def onRemoveBackgroud(self):
        box = QMessageBox()
        box.setText("Selecione a cor do background")
        box.setIcon(QMessageBox.Information)
        box.exec()
        diag = QColorDialog()
        backColor = diag.getColor()

        final = self.getBackground()
        b = self.__img[:, :, 0]
        g = self.__img[:, :, 1]
        r = self.__img[:, :, 2]
        b[final] = backColor.blue()
        g[final] = backColor.green()
        r[final] = backColor.red()

        self.open_image(self.__img)

    @Slot()
    def Resize(self):
        val = self.resize_spinbox.value()
        newDim = int(self.original.shape[1] * val / 100), int(self.original.shape[0] * val / 100)
        self.__img = cv2.resize(self.original, newDim)
        self.open_image(self.__img)

    @Slot()
    def setHighlightColor(self, color):
        self.__highlightcolor = color

    @Slot()
    def getAllColors(self, colors):
        self.__AllColors = colors

    @Slot()
    def setTran(self, value):
        self.__transparency = 1- value/100

    @Slot()
    def onUndo(self):
        self.thicSlider.setValue(1)
        self.nSlider.setValue(1)
        self.sigSlider.setValue(1)
        self.onNsegChange()
        self.onSigChange()
        self.onCompChange()
        self.__img = self.original
        self.open_image(self.__img)
Esempio n. 18
0
class MainWindow(QMainWindow):
    DIMENSION = 560
    placement_aleatoire = True
    nb_robots = 0

    def __init__(self, game):
        """
        La fenêtre principale est initialisée avec l'organisation suivante :

        +--------------------------------------------------------------------------+
        |              self.menu = self.menuBar()                                  |
        |                                                                          |
        +--------------------------------------------------------------------------+
        |       toolbar = QToolBar()  (déplacement/sélection des robots,           |
        |                     boutons annuler, indice et solution)                 |
        +------------------------layout0 = QHBoxLayout()---------------------------+
        |    layout2 = QHBoxLayout()                  +      moves_label           |
        | l                    +                      |                            |
        | a  grid_choice       |  nb_robots_choice    |     (affichage des         |
        +-y--------------------+----------------------+  L                         |
        | o                                           |  a  mouvements effectués)  |
        | u                                           |  y                         |
        | t                                           +--o-------------------------+
        | =          label = QLabel()                 |  u                         |
        | Q                                           |  t     tip_label           |
        | V          contient la grille de jeu        |  3                         |
        | B                                           |      (Affichage de l'indice|
        | o                                           |  =                         |
        | x                                           |      si demandé)           |
        | L                                           |  Q                         |
        | a                                           +--V+------------------------+
        | y                                           |  B     solution_label      |
        | o                                           |  o                         |
        | u                                           |  x   (Affichage de la      |
        | t                                           |                            |
        |                                             |      solution si demandée) |
        +---------------------------------------------+----------------------------+

        """

        super().__init__()
        self.game = game
        self.initial_game_state = self.game.get_state()
        self.number_moves = 0
        self.setWindowTitle("Robot Ricochet")
        self.resize(self.DIMENSION + 150, self.DIMENSION + 100)

        # label contient la grille de jeu
        self.label = QLabel()
        canvas = QPixmap(self.DIMENSION, self.DIMENSION)
        canvas.fill(Qt.white)
        self.label.setPixmap(canvas)

        # layout0 contient, à gauche, les barres d'outils et la grille,
        # et à droite, la liste des états et l'indice affiché par le solveur

        layout0 = QHBoxLayout()
        layout0.setContentsMargins(0, 0, 0, 0)
        layout0.setSpacing(0)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout2 = QHBoxLayout()

        # Choix de la grille
        self.choice_of_grid_menu()

        # choix du nombre de robots
        self.nb_robots_choice_menu()

        # CheckBox placement aléatoire
        widget3 = QCheckBox("Placement aléatoire des robots et de l'objectif")
        widget3.setCheckState(Qt.Checked)
        widget3.stateChanged.connect(self.placer_aleatoirement)

        # layout2 contient les 3 widgets horizontaux de choix de grille, robots et aléa
        layout2.addWidget(self.grid_choice)
        layout2.addWidget(self.nb_robots_choice)
        #layout2.addWidget(widget3)
        layout2.setContentsMargins(0, 0, 0, 0)
        layout2.setSpacing(0)
        widget2 = QWidget()
        widget2.setLayout(layout2)

        layout.addWidget(widget2)
        layout.addWidget(self.label)

        # liste des mouvement effectués, indice et solution:
        layout3 = QVBoxLayout()
        layout3.setContentsMargins(0, 0, 0, 0)
        layout3.setSpacing(0)

        self.moves_label = QLabel()
        self.print_moves_list()
        self.tip_label = QLabel()
        self.solution_label = QLabel()

        layout3.addWidget(self.moves_label)
        layout3.addWidget(self.tip_label)
        layout3.addWidget(self.solution_label)

        layout0.addLayout(layout)
        layout0.addLayout(layout3)
        widget = QWidget()
        widget.setLayout(layout0)
        self.setCentralWidget(widget)

        # Menu
        self.menu = self.menuBar()
        self.file_menu = self.menu.addMenu("File")
        self.help_menu = self.menu.addMenu("Aide et instructions")  # A faire
        self.size_fenetre = self.geometry()

        # Play QAction
        play_action = QAction("Réinitialiser !", self)
        play_action.triggered.connect(self.replay)
        self.file_menu.addAction(play_action)

        # Open_grid QAction
        open_grid_action = QAction("Ouvrir une grille", self)
        open_grid_action.setShortcut('Ctrl+O')
        open_grid_action.triggered.connect(self.open_grid)
        self.file_menu.addAction(open_grid_action)

        # Open_game QAction
        open_game_action = QAction("Ouvrir un jeu", self)
        open_game_action.triggered.connect(self.open_game)
        self.file_menu.addAction(open_game_action)

        # Save_grid QAction
        save_grid_action = QAction("Enregistrer cette grille", self)
        save_grid_action.triggered.connect(self.save_grid)
        self.file_menu.addAction(save_grid_action)

        # Save_game QAction
        save_game_action = QAction("Enregistrer ce jeu", self)
        save_game_action.triggered.connect(self.save_game)
        self.file_menu.addAction(save_game_action)

        # Exit QAction
        exit_action = QAction("Quitter", self)
        exit_action.setShortcut(QKeySequence.Quit)
        exit_action.triggered.connect(self.close)
        self.file_menu.addAction(exit_action)

        # Help QAction
        help_action = QAction("Aide", self)
        help_action.triggered.connect(self.help)
        self.help_menu.addAction(help_action)
        self.toolbar_menus()

        #Le robot rouge est sélectionné par défaut
        self.selected_robot = 'R'

        self.draw_robots_and_goal()

    def replay(self):
        """ on remet l'état initial du jeu """
        self.game.set_state(self.initial_game_state)
        self.game.moves_list = []
        self.game.states_list = deque([self.game.state_start], maxlen=100)
        self.unprint_moves_list()
        self.number_moves = 0
        self.draw_robots_and_goal()

    def help(self):
        """ Ouvre une fenêtre d'aide"""
        self.help_windows = Help_window()
        self.help_windows.exec_()

    def toolbar_menus(self):
        """ Affiche la barre d'icônes permettant de diriger les robots et de les sélectionner"""

        # Toolbar
        toolbar = QToolBar("Game toolbar")
        self.addToolBar(toolbar)

        # Flèche gauche
        button_West = QAction(QIcon(ICON_PATH + "arrow-180.png"), "West", self)
        button_West.setStatusTip("Aller à gauche")
        button_West.triggered.connect(self.onButtonWestClick)
        button_West.setCheckable(False)
        button_West.setShortcut(QKeySequence("Left"))
        toolbar.addAction(button_West)

        # Flèche droite
        button_East = QAction(QIcon(ICON_PATH + "arrow.png"), "Est", self)
        button_East.setStatusTip("Aller à droite")
        button_East.triggered.connect(self.onButtonEastClick)
        button_East.setCheckable(False)
        button_East.setShortcut(QKeySequence("Right"))
        toolbar.addAction(button_East)

        # Flèche Haut
        button_North = QAction(QIcon(ICON_PATH + "arrow-090.png"), "North",
                               self)
        button_North.setStatusTip("Aller vers le haut")
        button_North.triggered.connect(self.onButtonNorthClick)
        button_North.setCheckable(False)
        button_North.setShortcut(QKeySequence("Up"))
        toolbar.addAction(button_North)

        # Flèche Bas
        button_South = QAction(QIcon(ICON_PATH + "arrow-270.png"), "South",
                               self)
        button_South.setStatusTip("Aller vers le Bas")
        button_South.triggered.connect(self.onButtonSouthClick)
        button_South.setCheckable(False)
        button_South.setShortcut(QKeySequence("Down"))
        toolbar.addAction(button_South)

        # Selection robot actif
        button_Red = QPushButton("&Red")
        button_Red.setIcon(QIcon(ICON_PATH + "icon_R.png"))
        button_Red.setAutoExclusive(True)
        button_Red.setCheckable(True)
        button_Red.setShortcut(QKeySequence("R"))
        button_Red.toggled.connect(self.onButtonRedClick)

        button_Green = QPushButton("&Green")
        button_Green.setIcon(QIcon(ICON_PATH + "icon_G.png"))
        button_Green.setAutoExclusive(True)
        button_Green.setCheckable(True)
        button_Green.setShortcut(QKeySequence("G"))
        button_Green.toggled.connect(self.onButtonGreenClick)

        button_Blue = QPushButton("&Blue")
        button_Blue.setIcon(QIcon(ICON_PATH + "icon_B.png"))
        button_Blue.setAutoExclusive(True)
        button_Blue.setCheckable(True)
        button_Blue.setShortcut(QKeySequence("B"))
        button_Blue.toggled.connect(self.onButtonBlueClick)

        button_Yellow = QPushButton("&Yellow")
        button_Yellow.setIcon(QIcon(ICON_PATH + "icon_Y.png"))
        button_Yellow.setAutoExclusive(True)
        button_Yellow.setCheckable(True)
        button_Yellow.setShortcut(QKeySequence("Y"))
        button_Yellow.toggled.connect(self.onButtonYellowClick)

        # Boutton d'annulation (revient en arrière d'un coup)
        button_undo = QPushButton("&Undo")
        button_undo.setIcon(QIcon(ICON_PATH + "undo.jpg"))
        button_undo.setAutoExclusive(False)
        button_undo.setCheckable(False)
        button_undo.setShortcut(QKeySequence("U"))
        button_undo.clicked.connect(self.onButtonUndoClick)

        # Boutton d'indice : lance le solveur pour donner l'indice du prochain coup à effectuer
        button_tip = QPushButton("&Tip")
        button_tip.setIcon(QIcon(ICON_PATH + "icon_tip.png"))
        button_tip.setAutoExclusive(False)
        button_tip.setCheckable(False)
        button_tip.setShortcut(QKeySequence("T"))
        button_tip.clicked.connect(self.onButtonTipClick)

        # Boutton Solution : lance le solveur pour afficher une liste d'actions à effectuer pour résoudre le jeu
        button_solution = QPushButton("&Solution")
        button_solution.setIcon(QIcon(ICON_PATH + "icon_solution.png"))
        button_solution.setAutoExclusive(False)
        button_solution.setCheckable(False)
        button_solution.setShortcut(QKeySequence("S"))
        button_solution.clicked.connect(self.onButtonSolutionClick)

        toolbar.addWidget(button_Red)
        toolbar.addWidget(button_Green)
        toolbar.addWidget(button_Blue)
        toolbar.addWidget(button_Yellow)
        toolbar.addWidget(button_undo)
        toolbar.addWidget(button_tip)
        toolbar.addWidget(button_solution)

    def open_grid(self):
        """ Ouvre une boîte de dialogue permettant de charger une grille existante sur le disque dur"""

        filename, filter = QFileDialog.getOpenFileName(
            self, 'selectionner un fichier contenant une grille', './grids',
            '*.json')
        board, = Board.load_from_json(filename)
        self.game.add_board(board)
        self.number_moves = 0
        self.group = Robot_group()
        self.game = Game(self.game.board, self.group, self.game.goal)
        self.unprint_moves_list()
        self.draw_grid()

    def open_game(self):
        """ Ouvre une boîte de dialogue permettant de charger un jeu existant sur le disque dur"""

        filename, filter = QFileDialog.getOpenFileName(
            self, 'selectionner un fichier contenant un jeu', './games',
            '*.json')
        self.game = Game.load_from_json(filename)
        self.initial_game_state = self.game.get_state()
        self.number_moves = 0
        self.unprint_moves_list()
        self.draw_robots_and_goal()

    def save_grid(self):
        """ Ouvre une boîte de dialogue permettant d'enregistrer la grille affichée sur le disque dur"""

        filename, _ = QFileDialog.getSaveFileName(
            self,
            "Save Grid As",
            "",
            "JSON (*.JSON *.json);;"
            "All files(*.*)",
        )
        if filename:
            self.game.board.save_as_json(filename)

    def save_game(self):
        """ Ouvre une boîte de dialogue permettant d'enregistrer le jeu actuel sur le disque dur
            Si le joueur entre ou sélectionne un nom de fichier, le eju est sauvegardé dans ce fichier
            """

        filename, _ = QFileDialog.getSaveFileName(
            self,
            "Save game As",
            "",
            "JSON (*.JSON *.json);;"
            "All files(*.*)",
        )
        if filename:
            self.game.save_to_json(filename)

    def print_moves_list(self):
        """ Affichage de la liste des mouvements effectués dans le label "moves_label" """

        self.moves_label.setText("Mouvements effectués : \n" +
                                 str(self.game.moves_list).replace(', ', '\n'))
        self.moves_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)

    def unprint_moves_list(self):
        """ réinitialisation du label "moves_label" pour cacher la liste des mouvements effectués. """
        self.moves_label.setText(" ")
        self.moves_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)

    def print_tip(self):
        """ Affichage du conseil généré par le solveur  dans le label "tip_label" """

        self.tip_label.setText("Et si vous essayiez ce mouvement : \n" +
                               str(self.tip) + " ?")
        self.tip_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)

    def unprint_tip(self):
        """ réinitialisation du label "tip_label" pour cacher le conseil généré par le solveur. """
        self.tip_label.setText(" ")
        self.tip_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
        self.solution_label.setText(" ")

    def choice_of_grid_menu(self):

        self.grid_choice = QComboBox()
        self.grid_choice.insertItems(
            0, ("Grille 6x6", "Grille 8x8", "Grille 10x10", "Grille 12x12",
                "Grille 14x14", "Grille 16x16", "Grille aléatoire 16x16"))
        self.grid_choice.setGeometry(0, 0, 180, 40)
        self.grid_choice.activated.connect(self.choix_grille)

    def choix_grille(self, i):
        """
        Lors du choix d'une nouvelle grille, le jeu est réinitialisé et redessiné, les robots et l'objectif sont masqués.
        """

        # pour ouvrir les vieux .txt
        # name_grid = './test' + str(i + 1) + '.txt'
        # fd = open(name_grid,'r')
        # A = Board.load_from_json(fd)

        if i == 0:
            A, = Board.load_from_json(GRIDS_PATH + 'grid 6x6.json')
        elif i == 1:
            A, = Board.load_from_json(GRIDS_PATH + 'grid 8x8.json')
        elif i == 2:
            A, = Board.load_from_json(GRIDS_PATH + 'grid 10x10.json')
        elif i == 3:
            A, = Board.load_from_json(GRIDS_PATH + 'grid 12x12.json')
        elif i == 4:
            A, = Board.load_from_json(GRIDS_PATH + 'grid 14x14.json')
        elif i == 5:
            A, = Board.load_from_json(GRIDS_PATH + 'grid 16x16.json')
        else:
            # Pour ouvrir une grille aléatoire classique
            A = Board.new_classic()

        self.game.add_board(A)
        self.number_moves = 0
        self.group = Robot_group()
        self.game = Game(self.game.board, self.group, self.game.goal)
        self.draw_grid()

        # choix du nombre de robots
    def nb_robots_choice_menu(self):
        self.nb_robots_choice = QComboBox()
        self.nb_robots_choice.insertItems(
            0, ("1 robot", "2 robots", "3 robots", "4 robots"))
        self.nb_robots_choice.setGeometry(0, 0, 40, 40)
        self.nb_robots_choice.activated.connect(self.choix_nb_robots)

    def choix_nb_robots(self, i):
        """
        Les robots et l'objectif sont placés aléatoirement. L'extension
        """

        self.group = Robot_group()
        self.game = Game(self.game.board, self.group, self.game.goal)

        self.nb_robots = i + 1

        robots_pos = [0] * self.nb_robots
        robots_list = [0] * self.nb_robots
        robots_colors = [i for i in RColors]
        if self.placement_aleatoire:

            for i in range(self.nb_robots):
                x = randint(0, self.game.board.width - 1)
                y = randint(0, self.game.board.height - 1)
                while ((x, y) in robots_pos):
                    x = randint(0, self.game.board.width - 1)
                    y = randint(0, self.game.board.height - 1)
                robots_pos[i] = (x, y)
                robots_list[i] = Robot(self.game.robots, robots_colors[i],
                                       (x, y))

            x = randint(0, self.game.board.width - 1)
            y = randint(0, self.game.board.height - 1)
            goal = Goal(RColors(randint(1, self.nb_robots)), (x, y))
            self.game = Game(self.game.board, self.group, self.game.goal)
            self.game.add_goal(goal)
            self.initial_game_state = self.game.get_state()
            self.draw_robots_and_goal()

        else:
            fp = open(GAMES_PATH + DEFAULT_GAME, 'r')
            self.game = Game.load_from_json(fp)
            fp.close()

    def draw_grid(self):
        """
        Dessine la grille de jeu en juxtaposant les images contenant chaque case. Chaque image est redimensionnée et ajustée à la taille de la grille.
        """
        painter = QPainter(self.label.pixmap())
        names = [
            "Empty", "N", "E", "EN", "S", "NS", "ES", "ENS", "W", "NW", "EW",
            "ENW", "SW", "NSW", "ESW", "ENSW"
        ]
        images = [
            QPixmap(IMAGES_PATH + name + ".bmp", format="bmp")
            for name in names
        ]

        for x in range(0, self.game.board.width):
            for y in range(0, self.game.board.height):
                painter.drawPixmap(
                    QPoint(self.DIMENSION / self.game.board.height * y,
                           self.DIMENSION / self.game.board.width * x),
                    images[int(str(self.game.board.grid[x][y]))].scaled(
                        self.DIMENSION / self.game.board.width,
                        self.DIMENSION / self.game.board.height))

        self.update()
        painter.end()

    def draw_robots_and_goal(self):
        self.draw_grid()

        painter = QPainter(self.label.pixmap())

        goal_img_name = ICON_PATH + "/goal_" + str(
            self.game.goal.color) + ".png"
        painter.drawPixmap(
            QPoint(
                self.DIMENSION / self.game.board.height *
                self.game.goal.position[1], self.DIMENSION /
                self.game.board.width * self.game.goal.position[0]),
            QPixmap(goal_img_name, format="png").scaled(
                self.DIMENSION / self.game.board.width * 0.9,
                self.DIMENSION / self.game.board.height * 0.9))

        images = [
            QPixmap(ICON_PATH + "robot_" + str(color) + ".png", format="png")
            for color in self.game.color_keys
        ]

        for i, robot in enumerate(self.game.robots):

            painter.drawPixmap(
                QPoint(
                    self.DIMENSION / self.game.board.height *
                    self.game.robots[robot].position[1],
                    self.DIMENSION / self.game.board.width *
                    self.game.robots[robot].position[0]),
                images[i].scaled(self.DIMENSION / self.game.board.width * 0.8,
                                 self.DIMENSION / self.game.board.height))

        self.update()
        painter.end()

    def onButtonEastClick(self, s):
        self.game.do_action(self.selected_robot + 'E')

        self.draw_robots_and_goal()
        self.number_moves += 1
        self.print_moves_list()
        self.unprint_tip()
        if self.game.is_won():
            self.game_is_won()

    def onButtonWestClick(self, s):
        self.game.do_action(self.selected_robot + 'W')
        self.draw_robots_and_goal()
        self.number_moves += 1
        self.print_moves_list()
        self.unprint_tip()
        if self.game.is_won():
            self.game_is_won()

    def onButtonNorthClick(self, s):
        self.game.do_action(self.selected_robot + 'N')
        self.draw_robots_and_goal()
        self.number_moves += 1
        self.print_moves_list()
        self.unprint_tip()
        if self.game.is_won():
            self.game_is_won()

    def onButtonSouthClick(self, s):
        self.game.do_action(self.selected_robot + 'S')
        self.draw_robots_and_goal()
        self.number_moves += 1
        self.print_moves_list()
        self.unprint_tip()
        if self.game.is_won():
            self.game_is_won()

    def placer_aleatoirement(self):
        """ inverse la sélection de la checkBox """
        self.placement_aleatoire = not (self.placement_aleatoire)

    def onButtonRedClick(self, s):
        if s:
            self.selected_robot = 'R'

    def onButtonGreenClick(self, s):
        if s:
            self.selected_robot = 'G'

    def onButtonBlueClick(self, s):
        if s:
            self.selected_robot = 'B'

    def onButtonYellowClick(self, s):
        if s:
            self.selected_robot = 'Y'

    def onButtonUndoClick(self, s):
        """ Annule le dernier coup effectué """
        if self.number_moves != 0:
            self.game.undo()
            self.number_moves -= 1
            self.print_moves_list()
            self.unprint_tip()
            self.draw_robots_and_goal()

    def solve(self):
        """tip_game contient une copie du jeu courant, pour l'utiliser par le solveur"""

        self.game.save_to_json('tip_game.json')
        self.tip_game = Game.load_from_json('tip_game.json')
        return (solveur(self.tip_game).find_solution())

    def onButtonTipClick(self, s):
        """ La solution renvoyée par le solveur est de la forme (True/False, liste d'actions à effectuer).
        On récupère ici la première action."""
        self.tip = self.solve()[1][0]
        self.print_tip()

    def onButtonSolutionClick(self, s):
        self.solution = self.solve()[1]
        self.solution_label.setText(
            "Pour gagner, vous auriez pu effectuer cette suite de mouvements : \n"
            + str(self.solution) + ".")
        self.solution_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)

    def game_is_won(self):
        """ Fonction lancée quand l'objectif est atteint. On génère une fonction exit_windows dont le code de retour 1, 2 ou 3 valide le choix :
        1 : replay : on remet l'état initial du jeu
        2 : new game : on choisit une grille aleatoire
        3 : exit : on quitte le jeu.
        """
        self.exit_windows = Exit_window(self.number_moves)

        self.exit_windows.exec_()

        if self.exit_windows.retStatus == 1:  #replay : on remet l'état initial du jeu
            self.replay()

        elif self.exit_windows.retStatus == 2:  #new game : on choisit une grille aleatoire
            self.choix_grille(1)
            self.choix_nb_robots(3)
            self.unprint_moves_list()

        elif self.exit_windows.retStatus == 3:  #exit : on quitte le jeu
            exit()
Esempio n. 19
0
class ViewWidget(QScrollArea):
    """Widget providing an interactive viewport."""
    def __init__(self, app):
        QScrollArea.__init__(self)
        self.app = app

        self.image = QLabel()
        self.image.setScaledContents(True)
        self.image.setMouseTracking(True)
        self.image.mouseMoveEvent = self.mouseMoveEvent_over_image
        self.image.mousePressEvent = self.mousePressEvent_over_image
        self.image.mouseReleaseEvent = self.mouseReleaseEvent_over_image

        self.zoom_factor = 1
        """The current zoom factor of the image."""

        self.mouse_action = 0
        """The current action on mouse move.
        Can be *ROI*, *WINDOW* or *PAN*."""

        self.last_position = None
        """The last position, from which mouse events were processed."""

        self.setMouseTracking(True)
        self.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self.setWidget(self.image)

        # Hide scrollbars
        self.horizontalScrollBar().setStyleSheet("QScrollBar { height: 0 }")
        self.verticalScrollBar().setStyleSheet("QScrollBar { width: 0 }")

    def set(self, pixmap):
        """Display the image in *pixmap*."""
        self.image.setPixmap(pixmap)

    def zoom(self, factor, relative=True):
        """Set the zoom level for the displayed image.

        By default, the new zoom factor will be relative to the current
        zoom factor. If *relative* is set to False, *factor* will be used as
        the new zoom factor."""

        if self.app.dataset is None \
                or (relative and (0.1 >= self.zoom_factor * factor >= 100)):
            return

        self.zoom_factor = self.zoom_factor * factor if relative else factor
        self.image.resize(self.zoom_factor * self.image.pixmap().size())

        v_scroll = int(factor * self.verticalScrollBar().value() + (
            (factor - 1) * self.verticalScrollBar().pageStep() / 2))
        self.verticalScrollBar().setValue(v_scroll)

        h_scroll = int(factor * self.horizontalScrollBar().value() + (
            (factor - 1) * self.horizontalScrollBar().pageStep() / 2))
        self.horizontalScrollBar().setValue(h_scroll)

    def zoom_fit(self):
        """Zoom the displayed image to fit the available viewport."""

        image = self.image.pixmap().size()
        viewport = self.size()

        if image.height() == 0 or image.width() == 0:
            return

        v_zoom = viewport.height() / image.height()
        h_zoom = viewport.width() / image.width()
        self.zoom(min(v_zoom, h_zoom) * 0.99, False)

    def mousePressEvent(self, event):  # pylint: disable=C0103
        """Handle pan and window functionality on mouse button down."""

        if event.buttons() == Qt.LeftButton \
                and event.modifiers() == Qt.NoModifier:
            self.mouse_action = "PAN"

        elif event.buttons() == Qt.MiddleButton:
            self.mouse_action = "WINDOW"

        self.last_position = event.screenPos()

    def mouseReleaseEvent(self, event):  # pylint: disable=C0103,W0613
        """Handle RoI functionality on mouse button up."""

        if self.mouse_action == "ROI":
            self.app.recalculate()

        self.last_position = None
        self.mouse_action = 0

    def mouseMoveEvent(self, event):  # pylint: disable=C0103
        """Handle pan, window and RoI functionality on mouse move."""

        self.app.window.show_status("")

        if self.mouse_action == "PAN":
            vertical = self.verticalScrollBar().value() \
                + self.last_position.y() - event.screenPos().y()
            horizontal = self.horizontalScrollBar().value() \
                + self.last_position.x() - event.screenPos().x()

            self.verticalScrollBar().setValue(vertical)
            self.horizontalScrollBar().setValue(horizontal)
            self.last_position = event.screenPos()

        elif self.mouse_action == "WINDOW":
            move = self.last_position.x() - event.screenPos().x()
            scale = self.last_position.y() - event.screenPos().y()
            self.last_position = event.screenPos()
            self.app.mode.adjust_window(move, scale)
            self.app.refresh()

        elif self.mouse_action == "ROI":
            x_pos = event.pos().x() if event.pos().x() <= self.image.width() \
                else self.image.width()
            y_pos = event.pos().y() if event.pos().y() <= self.image.height() \
                else self.image.height()
            if self.app.tool is not None:
                self.app.tool.end_roi(int(x_pos / self.zoom_factor),
                                      int(y_pos / self.zoom_factor))
            self.app.refresh()

    def mousePressEvent_over_image(self, event):  # pylint: disable=C0103
        """Handle RoI functionality on mouse button down over the image.
        Hands off contorl to *mousePressEvent* when appropriate."""
        if event.buttons() == Qt.LeftButton \
                and event.modifiers() == Qt.ControlModifier:
            self.mouse_action = "ROI"
            self.last_position = event.pos()

            if self.app.tool is not None:
                x_pos = event.pos().x()
                y_pos = event.pos().y()
                self.app.tool.start_roi(int(x_pos / self.zoom_factor),
                                        int(y_pos / self.zoom_factor))

        else:
            self.mousePressEvent(event)

    def mouseMoveEvent_over_image(self, event):  # pylint: disable=C0103
        """Handle value display functionality on mouse move over the image.
        Call *mouseMoveEvent* for pan, window and RoI functionality."""

        self.mouseMoveEvent(event)

        x_coord = int((self.horizontalScrollBar().value() + event.pos().x()) //
                      self.zoom_factor)
        y_coord = int((self.verticalScrollBar().value() + event.pos().y()) //
                      self.zoom_factor)
        slice_ = self.app.dataset.get_pixeldata(self.app.slice)
        shape = slice_.shape
        if (x_coord < shape[0] and y_coord < shape[1]):
            value = slice_[x_coord, y_coord]
            self.app.window.show_status("{} x {}  -  {:.4g}".format(
                x_coord, y_coord, value))

    def mouseReleaseEvent_over_image(self, event):  # pylint: disable=C0103
        """Call *mouseReleaseEvent* on mouse button up for RoI
        functionality."""

        self.mouseReleaseEvent(event)

    def wheelEvent(self, event):  # pylint: disable=C0103
        """Handle scroll wheel events in the viewport.
        Scroll - Change current slice up or down.
        Alt+Scroll - Change current scan up or down.
        Strg+Scroll - Zoom the current image in or out."""

        if event.modifiers() == Qt.NoModifier:
            slice_ = int(numpy.sign(event.delta()))
            self.app.select_slice(slice_, True)

        elif event.modifiers() == Qt.ControlModifier:
            self.zoom(0.8 if event.delta() < 0 else 1.25)

        elif event.modifiers() == Qt.AltModifier:
            scan = int(numpy.sign(event.delta()))
            self.app.select_scan(scan, True)
class ShowValHist_NodeInstance_MainWidget(QWidget):
    def __init__(self, parent_node_instance):
        super(ShowValHist_NodeInstance_MainWidget, self).__init__()

        # leave these lines ------------------------------
        self.parent_node_instance = parent_node_instance
        # ------------------------------------------------

        self.setStyleSheet('''
            background-color: #333333;
        ''')

        self.setLayout(QVBoxLayout())
        # settings widget
        settings_widget = QWidget()
        settings_widget.setLayout(QHBoxLayout())
        self.connect_lines_check_box = QCheckBox('connect lines linear')
        settings_widget.layout().addWidget(self.connect_lines_check_box)
        self.layout().addWidget(settings_widget)
        # points area
        self.label = QLabel()
        pix = QPixmap(300, 200)
        self.label.setPixmap(pix)
        self.layout().addWidget(self.label)

        self.resize(300, 200)

        self.values = []

    def update(self, new_vals):
        self.values = new_vals

        painter = QPainter(self.label.pixmap())
        painter.setRenderHint(QPainter.Antialiasing)

        painter.setPen(QPen('#333333'))
        painter.setBrush(QColor('#333333'))
        painter.drawRect(self.label.rect())

        pen = QPen(QColor(255, 255, 255))
        pen.setWidth(1)
        painter.setPen(pen)
        painter.setBrush(QBrush(Qt.white))

        x_old = -1
        y_old = -1

        for i in range(len(self.values)):
            v = self.values[i]
            x = i * (self.label.width() / len(self.values))
            y = self.label.height() - self.label.height() * v

            if self.connect_lines_check_box.isChecked() and i > 0:
                painter.drawLine(x_old, y_old, x, y)
            else:

                painter.drawEllipse(x - 1, y - 1, 2, 2)

            x_old = x
            y_old = y

        self.repaint()

    def get_data(self):
        return {
            'connect lines linear': self.connect_lines_check_box.isChecked()
        }

    def set_data(self, data):
        self.connect_lines_check_box.setChecked(data['connect lines linear'])

    # optional - important for threading - stop everything here
    def removing(self):
        pass
Esempio n. 21
0
class Screenshot(QWidget):
    def __init__(self):
        super().__init__()
        self.init_UI()

    def init_UI(self):
        splitter = QSplitter(Qt.Horizontal)
        splitter.splitterMoved.connect(self.resizeEvent)
        # hor_layout = QHBoxLayout()
        self.original_pixmap = QPixmap()

        self.screenshot_label = QLabel(self)
        self.screenshot_label.setSizePolicy(
            QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.screenshot_label.setAlignment(Qt.AlignCenter)
        self.screenshot_label.resize(
            self.size().width()*0.45, self.screenshot_label.size().height())

        self.text_edit = QTextEdit()

        splitter.addWidget(self.screenshot_label)
        splitter.addWidget(self.text_edit)

        self.save_screenshot_button = QPushButton("Save Screenshot", self)
        self.save_screenshot_button.clicked.connect(self.save_screenshot)

        self.save_text_button = QPushButton("Save Text", self)
        self.save_text_button.setEnabled(False)
        self.save_text_button.clicked.connect(self.save_text)

        self.take_rect_screenshoot_button = QPushButton(
            'Take region screenshoot', self)
        self.take_rect_screenshoot_button.clicked.connect(
            self.create_rect_screenshot)

        self.quit_screenshot_button = QPushButton("Quit", self)
        self.quit_screenshot_button.clicked.connect(QApplication.quit)

        screenshot_buttons_layout = QHBoxLayout()

        screenshot_buttons_layout.addWidget(self.save_screenshot_button)
        screenshot_buttons_layout.addWidget(self.save_text_button)
        screenshot_buttons_layout.addWidget(self.quit_screenshot_button)

        self.lang_combo_box = CheckableComboBox()
        self.lang_combo_box.addItem("eng")
        self.lang_combo_box.addItem("ukr")
        self.lang_combo_box.addItem("rus")
        self.lang_combo_box.set_item_check("eng", True)

        self.recognition_button = QPushButton('Recognize', self)
        self.recognition_button.setEnabled(False)
        self.recognition_button.clicked.connect(self.run_recognition)

        self.negative_check_box = QCheckBox('Negative')
        self.negative_check_box.setToolTip(
            'Make negative picture for better recognition')
        self.grayscale_check_box = QCheckBox('Grayscale')
        self.grayscale_check_box.setChecked(True)
        self.grayscale_check_box.setToolTip(
            'Make grayscale picture for better recognition')

        recognition_buttons_layout = QHBoxLayout()

        recognition_buttons_layout.addWidget(self.take_rect_screenshoot_button)
        recognition_buttons_layout.addWidget(self.recognition_button)
        recognition_buttons_layout.addWidget(self.lang_combo_box)
        recognition_buttons_layout.addWidget(self.negative_check_box)
        recognition_buttons_layout.addWidget(self.grayscale_check_box)

        main_layout = QVBoxLayout(self)

        main_layout.addWidget(splitter)
        main_layout.addLayout(recognition_buttons_layout)
        main_layout.addLayout(screenshot_buttons_layout)

        self.setLayout(main_layout)
        self.shoot_screen()
        self.setWindowTitle("Screenshot recognition")
        self.resize(600, 600)
        self.screenshot_size = []

    @Slot()
    def new_screenshot(self):
        if self.hide_this_window_check_box.isChecked():
            self.hide()
        self.new_screenshot_button.setDisabled(True)
        if self.delay_spin_box.value() != 0:
            QTimer.singleShot(self.delay_spin_box.value()
                              * 1000, self.shoot_screen)
        else:
            QTimer.singleShot(100, self.shoot_screen)

    @Slot()
    def save_screenshot(self):
        frmat = '.png'
        initial_path = QStandardPaths.writableLocation(
            QStandardPaths.PicturesLocation)
        if not initial_path:
            initial_path = QDir.currentPath()
        initial_path += '/Screenshot-' + \
            str(datetime.now()).replace(' ', '_') + frmat
        file_dialog = QFileDialog(self, "Save as", initial_path)
        file_dialog.setAcceptMode(QFileDialog.AcceptSave)
        file_dialog.setFileMode(QFileDialog.AnyFile)
        if file_dialog.exec() != QDialog.Accepted:
            return
        file_name = file_dialog.selectedFiles()[0]
        if not self.original_pixmap.save(file_name):
            logger.error("The image could not be saved to \"{}\".".format(
                QDir.toNativeSeparators(file_name)))
            QMessageBox.warning(self, "Save Error", "The image could not be saved to \"{}\".".format(
                QDir.toNativeSeparators(file_name)))

    @Slot()
    def save_text(self):
        frmat = '.txt'
        initial_path = QStandardPaths.writableLocation(
            QStandardPaths.DocumentsLocation)
        if not initial_path:
            initial_path = QDir.currentPath()
        initial_path += '/Screenshot_Text-' + \
            str(datetime.now()).replace(' ', '_') + frmat
        file_dialog = QFileDialog(self, "Save as", initial_path)
        file_dialog.setAcceptMode(QFileDialog.AcceptSave)
        file_dialog.setFileMode(QFileDialog.AnyFile)
        if file_dialog.exec() != QDialog.Accepted:
            return
        file_name = file_dialog.selectedFiles()[0]
        with open(file_name, 'w') as wf:
            wf.write(self.text_edit.toPlainText())

    @Slot()
    def create_rect_screenshot(self):
        self.recognition_button.setEnabled(True)
        self.new_window = FullScreenDraw(self)

        # if self.hide_this_window_check_box.isChecked():
        self.hide()
        self.new_window.showFullScreen()
        # self.show()

    @Slot()
    def run_recognition(self):
        folder_path = 'temp_img'
        logger.debug("running recognition")
        if not os.path.exists(folder_path):
            os.mkdir(folder_path)
            logger.debug("Directory " + folder_path + " created")
        else:
            logger.debug("Directory " + folder_path + " already yet")
        if self.original_pixmap.save(folder_path + '/img001.png'):
            logger.debug("Picture img001 created")

            logger.debug("List_item_checked: " +
                         str(self.lang_combo_box.list_item_checked()))

            res = self.recognition(
                folder_path + '/img001.png', self.lang_combo_box.list_item_checked())

            self.text_edit.setText(res)
            self.save_text_button.setEnabled(True)
            if not res:
                QMessageBox.information(
                    self, "Recognition failed", "Can't recognize text")
            else:
                QMessageBox.information(
                    self, "Recognition  complete", "Recognition complete")

        try:
            rmtree(folder_path)
            logger.debug("Directory " + folder_path+" deleted")
        except OSError as e:
            logger.error("Error: %s : %s" % (folder_path, e.strerror))

    def recognition(self, path, langs=['eng']):
        try:
            from PIL import Image, ImageOps
        except ImportError:
            import Image
        import pytesseract
        srt_lang = '+'.join(langs)
        im = Image.open(path)
        if self.negative_check_box.isChecked():
            im = ImageOps.invert(im.convert('RGB'))
        if self.grayscale_check_box.isChecked():
            im = im.convert('LA')
        if logger.isEnabledFor(logging.DEBUG):
            if not os.path.exists('debug'):
                os.mkdir('debug')
            im.save('debug/test_' + str(datetime.now()
                                        ).replace(' ', '_') + '.png', 'PNG')
        res = pytesseract.image_to_string(im, lang=srt_lang)
        return res

    @Slot()
    def shoot_screen(self, windo=0):
        screen = QGuiApplication.primaryScreen()
        window = QWindow()
        window = self.windowHandle()
        if window:
            screen = window.screen()
        if not screen:
            return

        if type(windo) in (list, tuple):
            self.original_pixmap = screen.grabWindow(
                QApplication.desktop().winId(), *windo)
        else:
            self.original_pixmap = screen.grabWindow(
                QApplication.desktop().winId(), windo)
        self.update_screenshot_label()

        # self.new_screenshot_button.setDisabled(False)
        # if self.hide_this_window_check_box.isChecked():
        self.show()

    def update_screenshot_label(self):
        self.screenshot_label.setPixmap(self.original_pixmap.scaled(self.screenshot_label.size(),
                                                                    Qt.KeepAspectRatio, Qt.SmoothTransformation))

    def resizeEvent(self, event):
        scaled_size = QSize()
        scaled_size = self.original_pixmap.size()
        scaled_size.scale(self.screenshot_label.size(), Qt.KeepAspectRatio)
        if scaled_size != self.screenshot_label.pixmap().size():
            self.update_screenshot_label()