class SampleImageWidget(QWidget):
    def __init__(self, parent=None):

        super(SampleImageWidget, self).__init__(parent)

        self.graphicsScene = QGraphicsScene(self)
        self.graphicsView = SampleGraphicsView(self.graphicsScene)

    def setSampleImage(self, pathToFile):

        self.graphicsView.hide()

        #clear scene
        self.graphicsScene.clear()

        #load file
        tmpImage = QImage(pathToFile)
        self.originalHeight = tmpImage.height()
        self.originalWidth = tmpImage.width()
        tmpPixmap = QPixmap(1)
        tmpPixmap.convertFromImage(tmpImage.scaledToWidth(300))
        self.scaledHeight = tmpPixmap.height()
        self.scaledWidth = tmpPixmap.width()

        #add to scene and show
        self.graphicsScene.addPixmap(tmpPixmap)
        self.graphicsView.show()
Ejemplo n.º 2
0
class ImageView(QGraphicsView):

    def __init__(self, width=200, height=300):
        super().__init__()
        self.setFixedSize(QSize(width, height))
        self.image = None
        self.scene = QGraphicsScene()
        self.setScene(self.scene)

    """ファイル名より取得した画像表示"""
    def setImage(self, imageName):
        self.setCvImage(cv2.imread(imageName))

    """numpy配列より取得した画像表示"""
    def setCvImage(self, cvImage):
        cvImage = cv2.cvtColor(cvImage, cv2.COLOR_BGR2RGB)
        height, width, channel = cvImage.shape
        bytesPerLine = width * channel
        self.image = QImage(cvImage.data, width, height,
                            bytesPerLine, QImage.Format_RGB888)
        item = QGraphicsPixmapItem(QPixmap.fromImage(self.image))
        self.scene = QGraphicsScene()
        self.scene.addItem(item)
        self.setScene(self.scene)

    """ビューワクリア処理"""
    def clear(self):
        self.scene.clear()
Ejemplo n.º 3
0
class TextView(QGraphicsView):
    def __init__(self) -> None:
        super().__init__()
        self.setObjectName("TextView")
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setTransformationAnchor(self.AnchorViewCenter)
        self.setContentsMargins(0, 0, 0, 0)
        self._scene = QGraphicsScene()
        # need to set Scene size to View size
        self._scene.setSceneRect(QRectF(self.rect()))
        self.setScene(self._scene)

    def add(self, text_item: TextItem) -> None:
        offset = text_item.boundingRect()
        if profile.text.direction == "down":
            text_item.setPos(self.mapToScene(self.width() / 2 - offset.width() / 2, 0))
        else:
            text_item.setPos(
                self.mapToScene(
                    self.width() / 2 - offset.width() / 2,
                    self.height() - offset.height(),
                )
            )
        self._scene.addItem(text_item)

    def clear(self):
        self._scene.clear()
Ejemplo n.º 4
0
class MainWidget(QGraphicsView):
    def __init__(self, parent):
        super().__init__()
        self.parent = parent
        self.scene = QGraphicsScene(self)

        self.setScene(self.scene)

    def _cv2_image_to_pixmap(self):
        if self.cv2_out_image == COLOR_IMAGE:
            cv2_image = cv2.cvtColor(self.cv2_image, cv2.COLOR_BGR2RGB)
        elif self.cv2_out_image == GRAY_IMAGE:
            cv2_image = cv2.cvtColor(self.cv2_image, cv2.COLOR_GRAY2RGB)
        elif self.cv2_out_image == BIN_IMAGE:
            cv2_image = cv2.cvtColor(self.cv2_image, cv2.COLOR_GRAY2RGB)
        height, width, chanels = cv2_image.shape
        return QPixmap.fromImage(
            QImage(cv2_image, width, height, width * chanels,
                   QImage.Format_RGB888))

    def setImage(self, images):
        self.cv2_out_image = images[OUT_IMAGE]
        self.cv2_image = images[self.cv2_out_image]
        self.update_view()

    def update_view(self):
        self.scene.clear()
        self.scene.setSceneRect(0, 0, self.cv2_image.shape[1],
                                self.cv2_image.shape[0])
        self.scene.addPixmap(self._cv2_image_to_pixmap())
        self.fitInView(self.scene.sceneRect(), QtCore.Qt.KeepAspectRatio)

    def resizeEvent(self, event):
        self.fitInView(self.scene.sceneRect(), QtCore.Qt.KeepAspectRatio)
class Widget(QWidget):
    def __init__(self):
        super().__init__()

        self.scene = QGraphicsScene()
        self.scene.addItem(QGraphicsTextItem('loading...'))

        self.view = QGraphicsView()
        self.view.setScene(self.scene)

        self.nam = QNetworkAccessManager()
        self.nam.finished.connect(self.finish_request)

        url = "http://pp.vk.me/c627626/v627626428/be07/wbpWha0RqZ4.jpg"
        self.nam.get(QNetworkRequest(QUrl(url)))

        layout = QVBoxLayout()
        layout.addWidget(self.view)

        self.setLayout(layout)

    def finish_request(self, reply):
        self.scene.clear()

        img = QPixmap()
        img.loadFromData(reply.readAll())

        item = QGraphicsPixmapItem(img)
        self.scene.addItem(item)
class SampleImageWidget(QWidget):

  def __init__(self, parent=None):

    super(SampleImageWidget, self).__init__(parent)

    self.graphicsScene = QGraphicsScene(self)
    self.graphicsView = SampleGraphicsView(self.graphicsScene)

  def setSampleImage(self, pathToFile):

    self.graphicsView.hide()

    #clear scene
    self.graphicsScene.clear()

    #load file
    tmpImage = QImage(pathToFile)
    self.originalHeight = tmpImage.height()
    self.originalWidth = tmpImage.width()
    tmpPixmap = QPixmap(1)
    tmpPixmap.convertFromImage(tmpImage.scaledToWidth(300))
    self.scaledHeight = tmpPixmap.height()
    self.scaledWidth = tmpPixmap.width()

    #add to scene and show
    self.graphicsScene.addPixmap(tmpPixmap)
    self.graphicsView.show()
Ejemplo n.º 7
0
class MainView(QGraphicsView):
    min_scale = 1
    max_scale = 5

    def __init__(self, window=None):
        QGraphicsView.__init__(self)
        self.window = window
        self.scene = QGraphicsScene(self)
        self.setScene(self.scene)

        self.setMouseTracking(True)

        self.image = None
        self.screen_scale = 1

    def create_image(self, image_map, palette_frame):
        colors = [QColor(c).rgb() for c in palette_frame.get_colors()]
        width, height = image_map.width, image_map.height
        image = QImage(width, height, QImage.Format_ARGB32)
        for x in range(width):
            for y in range(height):
                idx = image_map.get(x, y)
                image.setPixel(x, y, colors[idx])
        return QImage(image)

    def set_image(self, image_map, palette_frame):
        self.image = self.create_image(image_map, palette_frame)
        # self.image = self.image.convertToFormat(QImage.Format_ARGB32)
        self.setSceneRect(0, 0, self.image.width(), self.image.height())

    def clear_scene(self):
        self.scene.clear()

    def show_image(self):
        if self.image:
            self.clear_scene()
            self.scene.addPixmap(QPixmap.fromImage(self.image))

    def mousePressEvent(self, event):
        scene_pos = self.mapToScene(event.pos())
        pixmap = self.scene.itemAt(scene_pos)
        if not pixmap:
            return
        image = pixmap.pixmap().toImage()
        pos = int(scene_pos.x()), int(scene_pos.y())

        if event.button() == Qt.LeftButton:
            dlg = QColorDialog()
            dlg.setCurrentColor(QColor(image.pixel(pos[0], pos[1])))
            if dlg.exec_():
                self.window.change_current_palette(pos, dlg.currentColor())

    def wheelEvent(self, event):
        if event.delta() > 0 and self.screen_scale < self.max_scale:
            self.screen_scale += 1
            self.scale(2, 2)
        elif event.delta() < 0 and self.screen_scale > self.min_scale:
            self.screen_scale -= 1
            self.scale(0.5, 0.5)
Ejemplo n.º 8
0
class ImageDocument(DocumentInterface):
    def __init__(self, associated_view):
        super().__init__()

        self._selection = tuple()
        self._assoc_view = associated_view
        self._scene = QGraphicsScene(associated_view)
        self._pixmap = QPixmap()

    @property
    def contents(self):
        return self._scene

    @property
    def raw(self):
        raw_contents = RawContents(image=self._pixmap.toImage())
        return raw_contents('image')

    @property
    def selection(self):
        return self._selection

    @selection.setter
    def selection(self, value):
        self._selection = tuple(value)

    @property
    def has_selection(self):
        # the same as an `if not ...` / etc.
        return bool(self._selection)

    @property
    def associated_view(self):
        return self._assoc_view

    def load_document(self, load_callback):
        load_callback(self._pixmap)

        if self._pixmap.isNull():
            return False

        self._scene.addPixmap(self._pixmap)
        self._scene.setSceneRect(0, 0, self._pixmap.width(),
                                 self._pixmap.height())

        return True

    def reset_document(self):
        self._scene.clear()

    def save_document(self, file_obj, format):
        raise NotImplementedError

    def get_selection_as_image(self):
        if not self.has_selection:
            raise ValueError("No Selection.")

        return self._pixmap.toImage().copy(*self._selection)
Ejemplo n.º 9
0
 def showImageFile(self, imageFile, _QGraphicsView_obj):
     # 显示图片
     # input: image path, QGraphicsView object
     pixmap = QPixmap(imageFile)
     scene = QGraphicsScene()
     pixmap = pixmap.scaled(_QGraphicsView_obj.size(), Qt.KeepAspectRatio)
     scene.clear()
     scene.addPixmap(pixmap)
     _QGraphicsView_obj.setScene(scene)
    def paint(self, painter: QtGui.QPainter, option: QStyleOptionViewItem,
              index: QtCore.QModelIndex) -> None:
        item_size = option.rect.size()
        custom_decoration_w, custom_decoration_h = index.data(
            SlideListModel.DecorationSizeOrRatioRole)
        if option.decorationPosition == QStyleOptionViewItem.Left:
            text_x, text_y = custom_decoration_w + self.icon_and_text_spacing, 0
            text_width = item_size.width(
            ) - custom_decoration_w - self.icon_and_text_spacing
            text_height = custom_decoration_h
        elif option.decorationPosition == QStyleOptionViewItem.Top:
            text_size = super().sizeHint(option, index)
            custom_decoration_h = custom_decoration_h - text_size.height()
            text_x, text_y = 0, custom_decoration_h + self.icon_and_text_spacing
            text_width = custom_decoration_w
            text_height = item_size.height(
            ) - custom_decoration_h - self.icon_and_text_spacing

        slide_view_params: SlideViewParams = index.data(
            SlideListModel.SlideViewParamsRole)
        scene_rect = QRectF(*slide_view_params.level_rect)
        img_key = "{}_{}_{}".format(custom_decoration_w, custom_decoration_h,
                                    slide_view_params.cache_key())
        icon_pixmap = QPixmapCache.find(img_key)
        if icon_pixmap is None:
            slide_helper = SlideHelper(slide_view_params.slide_path)
            # print("read", img_key)
            scene = QGraphicsScene()
            # t1 = elapsed()
            # print("before slide_graphics", t1)
            slide_graphics = SlideGraphicsGroup(slide_view_params)
            # t2 = elapsed()
            # print("slide_graphics", t2 - t1)
            scene.clear()
            scene.invalidate()
            scene.addItem(slide_graphics)
            slide_graphics.update_visible_level(slide_view_params.level)
            scene.setSceneRect(
                slide_helper.get_rect_for_level(slide_view_params.level))
            image = build_screenshot_image(
                scene, QSize(custom_decoration_w, custom_decoration_h),
                scene_rect)
            # t3 = elapsed()
            # print("build_screenshot_image", t3 - t2)
            icon_pixmap = QtGui.QPixmap.fromImage(image)
            QPixmapCache.insert(img_key, icon_pixmap)
        # t4 = elapsed()
        painter.fillRect(option.rect, painter.background())
        painter.drawPixmap(option.rect.topLeft(), icon_pixmap)
        # painter.drawRect(option.rect)
        painter.drawRect(option.rect.topLeft().x(),
                         option.rect.topLeft().y(), icon_pixmap.width(),
                         icon_pixmap.height())

        option.rect = option.rect.translated(text_x, text_y)
        option.rect.setSize(QSize(text_width, text_height))
        super().paint(painter, option, index)
Ejemplo n.º 11
0
class GraphWidget(QtWidgets.QGraphicsView):
    onSelected = pyqtSignal(object)
    showPid = pyqtSignal(int)

    def __init__(self, data):
        super().__init__()
        self.data = data

        self.setDragMode(QGraphicsView.ScrollHandDrag)
        self.setMouseTracking(True)

        self.p = QGraphicsScene(self)
        self.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform | QPainter.HighQualityAntialiasing)

        self.setScene(self.p)

        self.showPid.connect(self.handle_show_pid)
        self.onSelected.connect(self.handle_select)

    def handle_show_pid(self, pid):
        for node in self.p.items():
            if isinstance(node, Process) and node.process.process['pid'] == pid:
                self.onSelected.emit(node)

    def handle_select(self, object):
        for i in self.p.selectedItems():
            i.setSecondFocus(False)
            i.setSelected(False)
            i.update()

        object.setSelected(True)

    def create_graph(self, filter=None):
        self.graph, self.hashes = self.data.create_graph(filter)
        self.p.clear()
        for type in [self.graph.shapes, self.graph.nodes, self.graph.edges]:
            for node in type:
                if isinstance(node, QGraphicsItem):
                    self.p.addItem(node)

    def apply_filter(self, query):
        self.create_graph(filter=query)

    def wheelEvent(self, evt):
        scale = 1.2 if evt.angleDelta().y() > 0 else 0.8

        self.scale(scale, scale)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)

    def mousePressEvent(self, QMouseEvent):
        item = self.itemAt(QMouseEvent.x(), QMouseEvent.y())

        while item and not isinstance(item, Base):
            item = item.parentItem()

        if item:
            self.onSelected.emit(item)
Ejemplo n.º 12
0
class CanvasModel(object):
    def __init__(self):
        self.scene = QGraphicsScene()  # Canvas area
        self.scale_factor = 1  # Scaling factor
        self.current_image = None  # Current image in canvas

    def update(self):
        self.scene.clear()
        self.scene.addItem(
            QGraphicsPixmapItem(QPixmap.fromImage(self.current_image)))
        self.scene.update()
Ejemplo n.º 13
0
 def showImageArray(self, _bgrimg, _QGraphicsView_obj):
     # 显示图片
     # input: image path, QGraphicsView object
     rgbimg = cv2.cvtColor(_bgrimg, cv2.COLOR_BGR2RGB)
     qimg = QImage(rgbimg.data, rgbimg.shape[1], rgbimg.shape[0],
                   QImage.Format_RGB888)
     pixmap = QPixmap(qimg)
     scene = QGraphicsScene()
     pixmap = pixmap.scaled(_QGraphicsView_obj.size(), Qt.KeepAspectRatio)
     scene.clear()
     scene.addPixmap(pixmap)
     _QGraphicsView_obj.setScene(scene)
Ejemplo n.º 14
0
class ImageWidget(QGraphicsView):
    def __init__(self, parent):
        super().__init__()
        self.scene = QGraphicsScene(self)
        self.parent = parent

        self.setScene(self.scene)

    def setImage(self, cv2_image):
        self.cv2_image_orig = cv2_image
        self.transform_image()
        self.update_view()

    def update_view(self, transform=True):
        if transform:
            self.transform_image()
        self.scene.clear()
        self.scene.setSceneRect(0, 0, self.cv2_image.shape[1],
                                self.cv2_image.shape[0])
        self.scene.addPixmap(self._cv2_image_to_pixmap())
        self.fitInView(self.scene.sceneRect(), QtCore.Qt.KeepAspectRatio)

    def _cv2_image_to_pixmap(self):
        if self.cv2_out_image == COLOR_IMAGE:
            cv2_image = cv2.cvtColor(self.cv2_image, cv2.COLOR_BGR2RGB)
        elif self.cv2_out_image == GRAY_IMAGE:
            cv2_image = cv2.cvtColor(self.cv2_image, cv2.COLOR_GRAY2RGB)
        elif self.cv2_out_image == BIN_IMAGE:
            cv2_image = cv2.cvtColor(self.cv2_image, cv2.COLOR_GRAY2RGB)
        self.parent.draw(cv2_image)
        height, width, chanels = cv2_image.shape
        return QPixmap.fromImage(
            QImage(cv2_image, width, height, width * chanels,
                   QImage.Format_RGB888))

    def transform_image(self):
        images = {}
        try:
            with wait_cursor():
                images = self.parent.image_service.transform_image(
                    self.cv2_image_orig, self.parent.model)
            self.cv2_out_image = images[OUT_IMAGE]
            self.cv2_image = images[self.cv2_out_image]
        except TransformationError as e:
            message = QMessageBox(QMessageBox.Warning, "Warning", str(e))
            message.exec_()
        return images

    def resizeEvent(self, event):
        self.fitInView(self.scene.sceneRect(), QtCore.Qt.KeepAspectRatio)
Ejemplo n.º 15
0
class ImageView(QGraphicsView):
    def __init__(self, window=None):
        QGraphicsView.__init__(self)
        self.window = window
        self.scene = QGraphicsScene(self)
        self.setScene(self.scene)
        self.setFixedSize(240, 160)
        # self.fitInView(0, 0, 240, 160, Qt.KeepAspectRatio)

        self.image = QImage(240, 160, QImage.Format_ARGB32)
        self.screen_scale = 1

        # self.image_counter = 0

    def clear_scene(self):
        self.scene.clear()

    def show_image(self):
        if self.image:
            self.clear_scene()
            # bg = QImage(240, 160, QImage.Format_ARGB32)
            # self.scene.addPixmap(QPixmap.fromImage(bg))
            self.scene.addPixmap(QPixmap.fromImage(self.image))

    def new_frame(self, frame, offset):
        self.image = QImage(240, 160, QImage.Format_ARGB32)
        self.image.fill(QColor(128, 160, 128))
        painter = QPainter()
        painter.begin(self.image)
        painter.drawImage(offset[0], offset[1],
                          frame.copy())  # Draw image on top of autotiles
        painter.end()
        # self.image = f
        # self.image.paste(QImage(frame), offset)
        self.setSceneRect(0, 0, 240, 160)
        # self.image.save('image_%d.png' % self.image_counter)
        # self.image_counter += 1
        self.show_image()

    def new_over_frame(self, frame, offset):
        painter = QPainter()
        painter.begin(self.image)
        painter.drawImage(offset[0], offset[1],
                          frame.copy())  # Draw image on top of autotiles
        painter.end()
        self.show_image()
Ejemplo n.º 16
0
class picturezoom(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(picturezoom, self).__init__(parent)
        self.setupUi(self)
        self.zoomscale = 1  # 图片放缩尺度
        self.scene = QGraphicsScene()  # 创建场景
        self.item = 0
        self.train_set_x_orig, self.train_set_y, test_set_x_orig, test_set_y, classes = load_dataset(
        )
        self.pushBtn.clicked.connect(self.on_img_show_clicked)

    @pyqtSlot()
    def on_zoomin_clicked(self):
        self.zoomscale = self.zoomscale - 0.05
        if self.zoomscale <= 0.1:
            self.zoomscale = 0.1
        self.item.setScale(self.zoomscale)  # 缩小图像

    @pyqtSlot()
    def on_zoomout_clicked(self):
        self.zoomscale = self.zoomscale + 0.05
        if self.zoomscale >= 1.2:
            self.zoomscale = 1.2
        self.item.setScale(self.zoomscale)  # 放大图像

    @pyqtSlot()
    def on_img_show_clicked(self):
        index_str = self.line_edit.text()
        self.line_edit.setText(index_str)
        index = int(index_str)
        total_img_num = self.train_set_y.shape[1]
        if index < 0:
            index = 0
        elif index > total_img_num:
            index = total_img_num
        img = self.train_set_x_orig[index]
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 转换图像通道
        x = img.shape[1]  # 获取图像大小
        y = img.shape[0]
        frame = QImage(img, x, y, QImage.Format_RGB888)
        pix = QPixmap.fromImage(frame)
        self.item = QGraphicsPixmapItem(pix)  # 创建像素图元
        self.scene.removeItem(self.item)
        self.scene.clear()
        self.scene.addItem(self.item)
        self.picshow.setScene(self.scene)  # 将场景添加至视图
Ejemplo n.º 17
0
class TmxViewer(QGraphicsView):
    def __init__(self, parent = None):
        super().__init__(parent)
        self.mScene = QGraphicsScene(self)
        self.mMap = None
        self.mRenderer = None
        self.setWindowTitle(self.tr("TMX Viewer"))
        self.setScene(self.mScene)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setDragMode(QGraphicsView.ScrollHandDrag)
        self.setOptimizationFlags(QGraphicsView.DontAdjustForAntialiasing | QGraphicsView.DontSavePainterState)
        self.setBackgroundBrush(Qt.black)
        self.setFrameStyle(QFrame.NoFrame)
        self.viewport().setAttribute(Qt.WA_StaticContents)

    def __del__(self):
        if (self.mMap):
            self.mMap.tilesets().clear()
        del self.mMap
        del self.mRenderer

    def viewMap(self, fileName):
        del self.mRenderer
        self.mRenderer = None
        self.mScene.clear()
        self.centerOn(0, 0)
        reader = MapReader()
        self.mMap = reader.readMap(fileName)
        if (not self.mMap):
            qWarning("Error:"+reader.errorString())
            return False

        x = self.mMap.orientation()
        if x==Map.Orientation.Isometric:
            self.mRenderer = IsometricRenderer(self.mMap)
        elif x==Map.Orientation.Staggered:
            self.mRenderer = StaggeredRenderer(self.mMap)
        elif x==Map.Orientation.Hexagonal:
            self.mRenderer = HexagonalRenderer(self.mMap)
        else:
            self.mRenderer = OrthogonalRenderer(self.mMap)

        self.mScene.addItem(MapItem(self.mMap, self.mRenderer))
        return True
Ejemplo n.º 18
0
def render_drop_shadow_frame(pixmap, shadow_rect, shadow_color, offset, radius,
                             rect_fill_color):
    pixmap.fill(QColor(0, 0, 0, 0))
    scene = QGraphicsScene()
    rect = QGraphicsRectItem(shadow_rect)
    rect.setBrush(QColor(rect_fill_color))
    rect.setPen(QPen(Qt.NoPen))
    scene.addItem(rect)
    effect = QGraphicsDropShadowEffect(color=shadow_color,
                                       blurRadius=radius,
                                       offset=offset)

    rect.setGraphicsEffect(effect)
    scene.setSceneRect(QRectF(QPointF(0, 0), QSizeF(pixmap.size())))
    painter = QPainter(pixmap)
    scene.render(painter)
    painter.end()
    scene.clear()
    scene.deleteLater()
    return pixmap
Ejemplo n.º 19
0
class EasyScaleView(QGraphicsView):
    def __init__(self, parent=None):
        self.__scene = QGraphicsScene(parent)
        super().__init__(self.__scene)
        self.currentScale = 1.0

    def zoom(self, mul):
        self.currentScale *= mul
        self.update_scale()

    def resizeEvent(self, event):
        super().resizeEvent(event)
        # if self.__item is not None:
        self.update_scale()

    def update_scale(self):
        for i in self.items():
            self.update_item_scale(i)

    def update_item_scale(self, item):
        scale = self.width() / (item.pixmap().width() + 1) * self.currentScale
        item.setScale(scale)
        rect = item.boundingRect()
        rect.setSize(rect.size() * scale)
        self.setSceneRect(rect)

    def scroll(self, offset):
        scroll = self.verticalScrollBar()
        scroll.setValue(scroll.value() + offset)

    def display_image(self, image_path):
        print(image_path)
        self.__scene.clear()
        item = QGraphicsPixmapItem(QPixmap(image_path))
        self.__scene.addItem(item)
        self.verticalScrollBar().setValue(0)
        self.update_scale()
Ejemplo n.º 20
0
class CharIdentifierInput(QDialog, Ui_CharIdentifierInput):
    """ Get a character

        A dialog for creating / getting a character

        The followings are the operations in the dialog
        -#  Painting a character
        -#  Set : analyze the character drawn which is composed from the following stages
            -#  Transform the character to the size of the main item
            -#  Draw a network composed from squares
            -#  Decide which squares are occupied by the character
        -#  Save : Saves the character
        -#  Load : Loads the character from file
        -#  Cancel : exit and retrun False
        -#  OK : exit and return True

        Graphical structure of the dialog
        -# Vertical box layout
        -#   Buttons horizontal layout
        -#   GraphicsView which holds a
        -#   Graphics scene which hols a
        -#   CharItem
       
    """
    def __init__(self, parent, filename: str = None):
        """CharIdentifierInput constructor
        
            Args:
                parent : The parent window or dialog
                filename : The character will be loaded from the file
        """
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.setFixedSize(mainItemWidth + 2 * mainItemPadding + 40,
                          mainItemHeight + 2 * mainItemPadding + 60)
        self.createGui()
        self.pushButton_set.clicked.connect(self.pushButton_set_clicked)
        self.pushButton_save.clicked.connect(self.pushButton_save_clicked)
        self.pushButton_load.clicked.connect(self.pushButton_load_clicked)
        self.pushButton_cancel.clicked.connect(self.reject)
        self.pushButton_OK.clicked.connect(self.accept)
        self.pushButton_reset.clicked.connect(self.pushButton_reset_clicked)
        self.pushButton_revertSet.clicked.connect(
            self.pushButton_revertSet_clicked)
        self.dirty = False
        self.filename = filename
        if filename:
            self.pushButton_load_clicked(filename)

    def createGui(self):
        """ Create the scene and the new item
        """
        self.graphicsScene = QGraphicsScene()
        self.graphicsView.setScene(self.graphicsScene)
        self.itemBoundaries = QRectF(0, 0, mainItemWidth, mainItemHeight)
        self.itemPos = QPointF(mainItemPadding + 3, mainItemPadding)
        self.graphicsScene.setSceneRect(0, 0,
                                        mainItemWidth + 2 * mainItemPadding,
                                        mainItemHeight + 2 * mainItemPadding)
        self.newItem()

    def newItem(self):
        """ Create new main item
        """
        self.mainItem = CharItem(self.itemBoundaries, self.itemPos)
        self.graphicsScene.addItem(self.mainItem)

    def pushButton_set_clicked(self):
        """ Activate the set operation of the main item
        """
        self.mainItem.set()

    def pushButton_save_clicked(self):
        """ Slot : Activate the save operation
        """
        # If there where no changes - return
        if not self.mainItem.dirty:
            QMessageBox.critical(None, "Character Identifier - Save",
                                 "Nothing to save")
            return

        # Get the previous filename and path
        path = QFileInfo(
            self.filename).path() if self.filename else os.path.join(
                dataDir, "Chapter 3 - Distance Metrics")
        fname = QFileDialog.getSaveFileName(
            self, "Character Identifier - Save", path,
            "Character Identifier Files (*.chr)")

        # If the user pressed the cancel button in the dialog - return
        if not fname:
            return
        if not fname[0].lower().endswith(".chr"):
            fname[0] += ".chr"
        self.filename = fname[0]

        try:
            # Open the file create the stream and activate the save method of the
            # main item
            fh = QFile(self.filename)
            if not fh.open(QIODevice.WriteOnly):
                raise IOError(fh.errorString())
            stream = QDataStream(fh)
            self.mainItem.save(stream, self.filename)

        except IOError as e:
            QMessageBox.warning(
                self, "Character Identifier -- Save Error",
                "Failed to save {}: {}".format(self.filename, e))
        finally:
            if fh is not None:
                fh.close()

    def pushButton_load_clicked(self, filename: str = None):
        """ Slot : Activate the load from file operation
        """

        # If the character was not loaded from a file and no save was done
        if not self.filename:
            self.save()
            path = QFileInfo(
                self.filename).path() if self.filename else os.path.join(
                    dataDir, "Chapter 3 - Distance Metrics")
            fname = QFileDialog.getOpenFileName(
                self, "Character Identifier - Open", path,
                "Character Identifier Files (*.chr)")
            if not fname:
                return
            self.filename = fname[0]
            fh = None
        else:
            self.filename = filename

        try:
            fh = QFile(self.filename)

            if not fh.open(QIODevice.ReadOnly):
                raise IOError(fh.errorString())
            items = self.graphicsScene.items()
            while items:
                item = items.pop()
                self.graphicsScene.removeItem(item)
                del item

            stream = QDataStream(fh)
            self.mainItem = CharItem(self.itemBoundaries, self.itemPos)
            self.graphicsScene.addItem(self.mainItem)
            self.mainItem.load(stream, self.filename)
            self.dirty = False
        except IOError as e:
            QMessageBox.warning(
                self, "Page Designer -- Open Error",
                "Failed to open {}: {}".format(self.filename, e))
        finally:
            if fh is not None:
                fh.close()

    def accept(self):
        """ Slot : OK exit
        """
        # If the item was not set - set it
        if not self.mainItem.wasSetted:
            self.mainItem.set()

        # Save the item
        self.save()
        return super(CharIdentifierInput, self).accept()

    def save(self):
        """ save operation

            This method is activated before all the operations that cause
            The item to be removed from the screen
        """
        # If the item was changed - ask for saving
        if self.mainItem.dirty:
            if QMessageBox.question(
                    None, "Char Identifier Input",
                    "Do You want to save changes ?",
                    QMessageBox.StandardButtons(
                        QMessageBox.Yes
                        | QMessageBox.No)) == QMessageBox.Yes:
                self.pushButton_save_clicked()

    def reject(self):
        """ Slot : reject operation

            exit the dialog with true
        """
        self.save()
        return super(CharIdentifierInput, self).accept()

    def pushButton_reset_clicked(self):
        """ Slot : clear the presentation
        """
        self.save()
        self.graphicsScene.clear()
        self.graphicsView.viewport().update()
        self.newItem()

    def pushButton_revertSet_clicked(self):
        """ Slot : revert the setting for continue drowning
        """
        self.mainItem.revertTransform()
Ejemplo n.º 21
0
class frameArbol(QGraphicsView):
    def __init__(self):
        super(frameArbol, self).__init__()
        # Inicializar el arbol de entornos
        self.arbolEntornos = None
        # Definir la ubicacion inicial en el cuadro de dibujo
        self.y = 50
        # Definir el cuadro de dibujo haciendo uso de librerias externas
        self.panelDibujo = QGraphicsScene()
        # Asignar el panelDibujo como escena principal del frame del arbol
        self.setScene(self.panelDibujo)

    # Indicar en que momento se debe repintar el canvas principal
    def drawA(self):
        self.panelDibujo.clear()
        self.graficar()

    # Proceso para graficar el arbol, incluyendo sus ambientes(nodos) y sus aristas
    def graficar(self):
        raiz = self.arbolEntornos.getRaiz()
        self.y = 50
        self.graficarArbol(raiz, 10, self.y)
        self.graficarAristas(raiz)

    # Sobrescribir el metodo mousePressEvent de la libreria QGraphicsView
    def mousePressEvent(self, event: eventoRaton) -> None:
        # Capturar las coordenadas sobre las que se realizo el evento
        coordenadaX = event.pos().x()
        coordenadaY = event.pos().y()
        # Ubicar el evento en la escena definida
        ubicacion = self.mapToScene(event.pos())
        # Obtener la reiz del arbol
        raiz = self.arbolEntornos.getRaiz()
        if (raiz != None):
            # Se crea para poder operar el ambiente, tener acceso a el
            ambienteN = QRect(int(ubicacion.x()), int(ubicacion.y()),
                              raiz.dimension, raiz.dimension)
            self.verificarNodo(raiz, ambienteN)

    # Verificar relacion panel-ambiente
    def verificarNodo(self, ambienteActual, ambienteBuscar):
        # Verificar si el ambienteActual buscado es el ambienteActual con el evento mouse
        if ambienteActual.dibujarN.intersects(ambienteBuscar):
            # Informacion del ambienteBuscar (ambienteActual)zz
            mensaje = QMessageBox()
            mensaje.setIcon(QMessageBox.Information)
            mensaje.setText("Ambiente: " + str(ambienteActual.contenido))
            mensaje.exec_()
            return True
        else:
            # Realizar la busqueda en todos los ambientes (nodos) restantes
            for i in ambienteActual.hijos:
                self.verificarNodo(i, ambienteBuscar)

    # Graficar el arbol generado
    def graficarArbol(self, ambiente, posX, posY):
        # Crear los esquemas ara utilizar la libreria
        nodo1 = QPen(Qt.black)
        nodo2 = QPen(Qt.green)
        # Asignar coordenada X y Y al nuevo ambiente
        ambiente.x = posX
        ambiente.y = self.y
        # Crear un modelo de ambiente (nodo)
        ambiente.dibujarN = QRect(ambiente.x, ambiente.y, ambiente.dimension,
                                  ambiente.dimension)
        # Definir si el ambiente esta activo para marcarlo con color diferente a los demas
        if ambiente.nActivo:
            self.panelDibujo.addEllipse(ambiente.x, ambiente.y,
                                        ambiente.dimension, ambiente.dimension,
                                        nodo2)
        else:
            self.panelDibujo.addEllipse(ambiente.x, ambiente.y,
                                        ambiente.dimension, ambiente.dimension,
                                        nodo1)

        # Informacion que tendra el ambiente

        cadena = QGraphicsTextItem()
        cadena.setPlainText(str(ambiente.nombre))
        cadena.setPos(QPointF(ambiente.x + 2, ambiente.y - 3))
        posX += 50

        # Graficar los hijos del ambiente actual
        for i in ambiente.hijos:
            self.y += 40
            self.graficarArbol(i, posX, self.y)

    # Graficar las aristas del arbol
    def graficarAristas(self, ambiente):
        linea1 = QPen(Qt.black)
        puntoIni = ambiente.dimension / 2
        for i in ambiente.hijos:
            posXInicial = ambiente.x + ambiente.dimension + 5
            posYInicial = ambiente.y + ambiente.dimension - 5
            posYFinal = i.y + puntoIni
            self.panelDibujo.addLine(ambiente.x + ambiente.dimension,
                                     posYInicial, posXInicial, posYInicial)
            self.panelDibujo.addLine(posXInicial, posYInicial, posXInicial,
                                     posYFinal, linea1)
            self.panelDibujo.addLine(posXInicial, posYFinal, i.x, posYFinal,
                                     linea1)
            self.graficarAristas(i)
Ejemplo n.º 22
0
class BrushingModel(QObject):
    brushSizeChanged = pyqtSignal(int)
    brushColorChanged = pyqtSignal(QColor)
    brushStrokeAvailable = pyqtSignal(QPointF, object)
    drawnNumberChanged = pyqtSignal(int)

    minBrushSize = 1
    maxBrushSize = 61
    defaultBrushSize = 3
    defaultDrawnNumber = 1
    defaultColor = Qt.white
    erasingColor = Qt.black
    erasingNumber = 100

    def __init__(self, parent=None):
        QObject.__init__(self, parent=parent)
        self.sliceRect = None
        self.bb = QRect()  # bounding box enclosing the drawing
        self.brushSize = self.defaultBrushSize
        self.drawColor = self.defaultColor
        self._temp_color = None
        self._temp_number = None
        self.drawnNumber = self.defaultDrawnNumber

        self.pos = None
        self.erasing = False
        self._hasMoved = False

        self.drawOnto = None

        # an empty scene, where we add all drawn line segments
        # a QGraphicsLineItem, and which we can use to then
        # render to an image
        self.scene = QGraphicsScene()

    def toggleErase(self):
        self.erasing = not (self.erasing)
        if self.erasing:
            self.setErasing()
        else:
            self.disableErasing()

    def setErasing(self):
        self.erasing = True
        self._temp_color = self.drawColor
        self._temp_number = self.drawnNumber
        self.setBrushColor(self.erasingColor)
        self.brushColorChanged.emit(self.erasingColor)
        self.setDrawnNumber(self.erasingNumber)

    def disableErasing(self):
        self.erasing = False
        self.setBrushColor(self._temp_color)
        self.brushColorChanged.emit(self.drawColor)
        self.setDrawnNumber(self._temp_number)

    def setBrushSize(self, size):
        self.brushSize = size
        self.brushSizeChanged.emit(self.brushSize)

    def setDrawnNumber(self, num):
        self.drawnNumber = num
        self.drawnNumberChanged.emit(num)

    def getBrushSize(self):
        return self.brushSize

    def brushSmaller(self):
        b = self.brushSize
        if b > self.minBrushSize:
            self.setBrushSize(b - 1)

    def brushBigger(self):
        b = self.brushSize
        if self.brushSize < self.maxBrushSize:
            self.setBrushSize(b + 1)

    def setBrushColor(self, color):
        self.drawColor = QColor(color)
        self.brushColorChanged.emit(self.drawColor)

    def beginDrawing(self, pos, sliceRect):
        """

        pos -- QPointF-like
        """
        self.sliceRect = sliceRect
        self.scene.clear()
        self.bb = QRect()
        self.pos = QPointF(pos.x(), pos.y())
        self._hasMoved = False

    def endDrawing(self, pos):
        has_moved = self._hasMoved  # _hasMoved will change after calling moveTo
        if has_moved:
            self.moveTo(pos)
        else:
            assert self.pos == pos
            self.moveTo(QPointF(pos.x() + 0.0001, pos.y() + 0.0001))  # move a little

        # Qt seems to use strange rules for determining which pixels to set when rendering a brush stroke to a QImage.
        # We seem to get better results if we do the following:
        # 1) Slightly offset the source window because apparently there is a small shift in the data
        # 2) Render the scene to an image that is MUCH larger than the scene resolution (4x by 4x)
        # 3) Downsample each 4x4 patch from the large image back to a single pixel in the final image,
        #     applying some threshold to determine if the final pixel is on or off.

        tempi = QImage(
            QSize(4 * self.bb.width(), 4 * self.bb.height()), QImage.Format_ARGB32_Premultiplied
        )  # TODO: format
        tempi.fill(0)
        painter = QPainter(tempi)
        # Offset the source window.  At first I thought the right offset was 0.5, because
        #  that would seem to make sure points are rounded to pixel CENTERS, but
        #  experimentation indicates that 0.25 is slightly better for some reason...
        source_rect = QRectF(QPointF(self.bb.x() + 0.25, self.bb.y() + 0.25), QSizeF(self.bb.width(), self.bb.height()))
        target_rect = QRectF(QPointF(0, 0), QSizeF(4 * self.bb.width(), 4 * self.bb.height()))
        self.scene.render(painter, target=target_rect, source=source_rect)
        painter.end()

        # Now downsample: convert each 4x4 patch into a single pixel by summing and dividing
        ndarr = qimage2ndarray.rgb_view(tempi)[:, :, 0].astype(int)
        ndarr = ndarr.reshape((ndarr.shape[0],) + (ndarr.shape[1] // 4,) + (4,))
        ndarr = ndarr.sum(axis=-1)
        ndarr = ndarr.transpose()
        ndarr = ndarr.reshape((ndarr.shape[0],) + (ndarr.shape[1] // 4,) + (4,))
        ndarr = ndarr.sum(axis=-1)
        ndarr = ndarr.transpose()
        ndarr //= 4 * 4

        downsample_threshold = (7.0 / 16) * 255
        labels = numpy.where(ndarr >= downsample_threshold, numpy.uint8(self.drawnNumber), numpy.uint8(0))
        labels = labels.swapaxes(0, 1)
        assert labels.shape[0] == self.bb.width()
        assert labels.shape[1] == self.bb.height()

        ##
        ## ensure that at least one pixel is label when the brush size is 1
        ##
        ## this happens when the user just clicked without moving
        ## in that case the lineitem will be so tiny, that it won't be rendered
        ## into a single pixel by the code above
        if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(labels) == 0:
            labels[labels.shape[0] // 2, labels.shape[1] // 2] = self.drawnNumber

        self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels)

    def dumpDraw(self, pos):
        res = self.endDrawing(pos)
        self.beginDrawing(pos, self.sliceRect)
        return res

    def moveTo(self, pos):
        # data coordinates
        oldX, oldY = self.pos.x(), self.pos.y()
        x, y = pos.x(), pos.y()

        line = QGraphicsLineItem(oldX, oldY, x, y)
        line.setPen(QPen(QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        self.scene.addItem(line)
        self._hasMoved = True

        # update bounding Box
        if not self.bb.isValid():
            self.bb = QRect(QPoint(oldX, oldY), QSize(1, 1))
        # grow bounding box
        self.bb.setLeft(min(self.bb.left(), max(0, x - self.brushSize // 2 - 1)))
        self.bb.setRight(max(self.bb.right(), min(self.sliceRect[0] - 1, x + self.brushSize // 2 + 1)))
        self.bb.setTop(min(self.bb.top(), max(0, y - self.brushSize // 2 - 1)))
        self.bb.setBottom(max(self.bb.bottom(), min(self.sliceRect[1] - 1, y + self.brushSize // 2 + 1)))

        # update/move position
        self.pos = pos
Ejemplo n.º 23
0
class MapPainter(object):
    def __init__(self, parent, view, displayCities, displayConnections,
                 displayBestUnit):
        super().__init__()
        self.view = view
        self.displayCities = displayCities
        self.displayConnections = displayConnections
        self.displayBestUnit = displayBestUnit
        self.problemMap = None
        self.bestUnit = None

        self.scene = QGraphicsScene(parent)
        self.resizeScene()

        self.view.setScene(self.scene)
        self.view.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio)

    def resizeScene(self):
        height = self.view.size().height()
        width = self.view.size().width()
        self.scene.setSceneRect(0.0, 0.0, width, height)

    def setProblemMap(self, problemMap):
        self.problemMap = problemMap

    def setBestUnit(self, unit):
        self.bestUnit = unit

    def setDisplayCities(self, enabled=False):
        self.displayCities = bool(enabled)

    def setDisplayConnections(self, enabled=False):
        self.displayConnections = bool(enabled)

    def setDisplayBestUnit(self, enabled=False):
        self.displayBestUnit = bool(enabled)

    def repaint(self):
        if self.problemMap is None:
            return

        self.scene.clear()
        self.resizeScene()
        height = self.scene.height()
        width = self.scene.width()

        if self.displayCities:
            cityBrush = QBrush(QColor(0, 0, 0), Qt.SolidPattern)
            cityPen = QPen(cityBrush, 5.0)
            for city in self.problemMap.cities:
                x = width * city.positionX
                y = height * city.positionY
                self.scene.addEllipse(x, y, 4, 4, cityPen, cityBrush)

        if self.displayConnections:
            connectionBrush = QBrush(QColor(0, 0, 255), Qt.SolidPattern)
            connectionPen = QPen(connectionBrush, 1.0)
            for city in self.problemMap.cities:
                for neighbour in city.connections:
                    x = width * city.positionX
                    y = height * city.positionY
                    x2 = width * self.problemMap.cities[neighbour].positionX
                    y2 = height * self.problemMap.cities[neighbour].positionY
                    self.scene.addLine(x, y, x2, y2, connectionPen)

        if self.displayBestUnit and self.bestUnit is not None:
            bestUnitBrush = QBrush(QColor(255, 0, 0), Qt.SolidPattern)
            bestUnitPen = QPen(bestUnitBrush, 2.0)
            for i in range(-1, len(self.bestUnit.path) - 1):
                currCity = self.problemMap.cities[self.bestUnit.path[i]]
                nextCity = self.problemMap.cities[self.bestUnit.path[i + 1]]
                x = width * currCity.positionX
                y = height * currCity.positionY
                x2 = width * nextCity.positionX
                y2 = height * nextCity.positionY
                self.scene.addLine(x, y, x2, y2, bestUnitPen)

        self.view.fitInView(self.scene.sceneRect())
Ejemplo n.º 24
0
class MapPainter(object):
    def __init__(self, parent, view, displayCities, displayConnections, displayBestUnit):
        super().__init__()
        self.view = view
        self.displayCities = displayCities
        self.displayConnections = displayConnections
        self.displayBestUnit = displayBestUnit
        self.problemMap = None
        self.bestUnit = None

        self.scene = QGraphicsScene(parent)
        self.resizeScene()

        self.view.setScene(self.scene)
        self.view.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio)

    def resizeScene(self):
        height = self.view.size().height()
        width = self.view.size().width()
        self.scene.setSceneRect(0.0, 0.0, width, height)

    def setProblemMap(self, problemMap):
        self.problemMap = problemMap

    def setBestUnit(self, unit):
        self.bestUnit = unit

    def setDisplayCities(self, enabled = False):
        self.displayCities = bool(enabled)

    def setDisplayConnections(self, enabled = False):
        self.displayConnections = bool(enabled)

    def setDisplayBestUnit(self, enabled = False):
        self.displayBestUnit = bool(enabled)

    def repaint(self):
        if self.problemMap is None:
            return

        self.scene.clear()
        self.resizeScene()
        height = self.scene.height()
        width = self.scene.width()

        if self.displayCities:
            cityBrush = QBrush(QColor(0, 0, 0), Qt.SolidPattern)
            cityPen = QPen(cityBrush, 5.0)
            for city in self.problemMap.cities:
                x = width * city.positionX
                y = height * city.positionY
                self.scene.addEllipse(x, y, 4, 4, cityPen, cityBrush)

        if self.displayConnections:
            connectionBrush = QBrush(QColor(0, 0, 255), Qt.SolidPattern)
            connectionPen = QPen(connectionBrush, 1.0)
            for city in self.problemMap.cities:
                for neighbour in city.connections:
                    x = width * city.positionX
                    y = height * city.positionY
                    x2 = width * self.problemMap.cities[neighbour].positionX
                    y2 = height * self.problemMap.cities[neighbour].positionY
                    self.scene.addLine(x, y, x2, y2, connectionPen)

        if self.displayBestUnit and self.bestUnit is not None:
            bestUnitBrush = QBrush(QColor(255, 0, 0), Qt.SolidPattern)
            bestUnitPen = QPen(bestUnitBrush, 2.0)
            for i in range(-1, len(self.bestUnit.path)-1):
                currCity = self.problemMap.cities[self.bestUnit.path[i]]
                nextCity = self.problemMap.cities[self.bestUnit.path[i+1]]
                x = width * currCity.positionX
                y = height * currCity.positionY
                x2 = width * nextCity.positionX
                y2 = height * nextCity.positionY
                self.scene.addLine(x, y, x2, y2, bestUnitPen)

        self.view.fitInView(self.scene.sceneRect())
Ejemplo n.º 25
0
class GUI(Ui_MainWindow):
    def __init__(self):
        super().setupUi(MainWindow)
        self.initUI()
    #connect widgets with functions
    def initUI(self):
        self.scene1=QGraphicsScene()
        self.scene2=QGraphicsScene()
        self.scene3=QGraphicsScene()
        self.scene4=QGraphicsScene()
        self.actionOpen.triggered.connect(self.imageOpen)
        self.histogram.clicked.connect(self.imageHistogram)
        self.GrayvalueScrollBar.valueChanged.connect(self.sliderval)
        self.OTSU.clicked.connect(self.OTSUThreshold)
        self.MedianFilter.clicked.connect(self.medianfilter)
        self.MeanFilter.clicked.connect(self.meanfilter)
        self.GaussianFilter.clicked.connect(self.gaussianfilter)
        self.CoustomizedFilter.clicked.connect(self.coustomizefilter)
        self.BinaryErosion.clicked.connect(self.binaryerosion)
        self.BinaryDilation.clicked.connect(self.binarydilation)
        self.actionClear_All.triggered.connect(self.clearall)
        self.DistanceTransform.clicked.connect(self.distancetransform)
        self.Skeleton.clicked.connect(self.skeleton)
        self.SkeletonRestoration.clicked.connect(self.skeletonrestoration)
        self.GrayErosion.clicked.connect(self.grayerosion)
        self.GrayDilation.clicked.connect(self.graydilation)
        self.EdgeDetection.clicked.connect(self.edgedetection)
        self.Gradient.clicked.connect(self.gradient)
        self.Reconstraction_Binary.clicked.connect(self.reconstruction_binary)
        self.Reconstraction_Gray.clicked.connect(self.reconstruction_gray)

    #function menubar-file-open: Open image and show it in view1
    def imageOpen(self):
#        filename,_ = QFileDialog.getOpenFileName(MainWindow,'Open a image',os.getenv('HOME'))
        filename,_ = QFileDialog.getOpenFileName(MainWindow,'Open a image','.',"Image Files(*.bmp *jpg *png *jpeg)")
#        filename="/home/lab105/git-sen/python_gui/lena512.bmp"
#        print(filename)
        pix=QtGui.QPixmap(filename)
        pix=pix.scaledToHeight(256)
        self.image=plt.imread(filename)
        Size=self.image.shape
        if (len(Size)==3):
            if (type(self.image[1,1,1]) is np.float32):
                self.image=misc.imread(filename) 
            self.image=self.image[:,:,1]
        self.image_temp=self.image
        self.scene1.addPixmap(QPixmap(pix))
        self.View1.setScene(self.scene1)
        self.clearall()

    #function mainwindow tab histogram-greylevel histogram: compute and show the greyvalue histogram in view 2
    def imageHistogram(self):
        greyimage=self.image
        #greyimage.dtype
        Height, Width=greyimage.shape
        x=np.zeros(Height*Width)
        for h in range(Height):
            for w in range(Width):
                x[h*Height+w]=greyimage[h,w]

        num_bins=255
        plt.figure(figsize=(256,256),dpi=1)
        n,self.bins,patches=plt.hist(x,num_bins,normed=1,facecolor='green',alpha=0.5)
        plt.axis("off")
        plt.gca().set_position([0,0,1,1])
        self.figure=plt.gcf()
        canvas2=FigureCanvas(self.figure)
        self.scene2.addWidget(canvas2)
        self.View2.setScene(self.scene2)


    def sliderval(self):
        Threshold=self.GrayvalueScrollBar.value()
        self.Binarization(Threshold)
#        self.label.setText(str(Threshold))

    #threshlod function 
    def Binarization(self,Threshold):
        #filename="/home/lab105/git-sen/python_gui/lena512.bmp"
        #img=misc.imread(filename)
        img=self.image
        BinaryArray= img >Threshold
        plt.close(3)
        plt.figure(num=3,figsize=(256,256),dpi=1)
        plt.axis("off")
        plt.gca().set_position([0,0,1,1]) 
        plt.imshow(BinaryArray,cmap='binary_r')
        figure3=plt.gcf()
        canvas3=FigureCanvas(figure3)
        self.scene3.clear()
        self.scene3.addWidget(canvas3)
        self.View3.setScene(self.scene3)
        self.label.setText(str(Threshold))

    def OTSUThreshold(self):
        img=self.image
        thresh=threshold_otsu(img)
        binary=img > thresh
        self.showView4(binary)

    def showView4(self,image):
        plt.close(4)
        plt.figure(num=4,figsize=(256,256),dpi=1)
        if (image.max()>1):
            plt.imshow(image,cmap='gray')
        else:
            plt.imshow(image,cmap='binary_r')
        plt.gca().set_position([0,0,1,1])
        plt.axis("off")
        figure4=plt.gcf()
        canvas4=FigureCanvas(figure4)
        self.scene4.clear()
        self.scene4.addWidget(canvas4)
        self.View4.setScene(self.scene4)

    def getmatrixsize(self):
        matrixsize=3
        if (self.radioButton_1.isChecked()):
            matrixsize=3
        if (self.radioButton_2.isChecked()):
            matrixsize=5
        return matrixsize
    
    def medianfilter(self):
        self.image_temp=ndimage.median_filter(self.image_temp,size=int(self.plainTextEdit.toPlainText()))
        self.showView4(self.image_temp)

    def meanfilter(self):
        self.image_temp=ndimage.uniform_filter(self.image_temp,size=int(self.plainTextEdit.toPlainText()))
        self.showView4(self.image_temp)

    def gaussianfilter(self):
        self.image_temp=ndimage.gaussian_filter(self.image_temp,sigma=float(self.plainTextEdit_2.toPlainText()))
        self.showView4(self.image_temp)
    
    def getmatrix(self):
        self.Matrix=[]
        if (self.getmatrixsize()==3):
            matrix=np.zeros((3,3))
            matrix[0,0]=float(self.plainTextEdit1_1.toPlainText())
            matrix[0,1]=float(self.plainTextEdit1_2.toPlainText())
            matrix[0,2]=float(self.plainTextEdit1_3.toPlainText())
            matrix[1,0]=float(self.plainTextEdit2_1.toPlainText())
            matrix[1,1]=float(self.plainTextEdit2_2.toPlainText())
            matrix[1,2]=float(self.plainTextEdit2_3.toPlainText())
            matrix[2,0]=float(self.plainTextEdit3_1.toPlainText())
            matrix[2,1]=float(self.plainTextEdit3_2.toPlainText())
            matrix[2,2]=float(self.plainTextEdit3_3.toPlainText())
            if (matrix.max()==0):
                matrix[:,:]=1
        if (self.getmatrixsize()==5):
            matrix=np.zeros((5,5))
            matrix[0,0]=float(self.plainTextEdit1_1.toPlainText())
            matrix[0,1]=float(self.plainTextEdit1_2.toPlainText())
            matrix[0,2]=float(self.plainTextEdit1_3.toPlainText())
            matrix[0,3]=float(self.plainTextEdit1_4.toPlainText())
            matrix[0,4]=float(self.plainTextEdit1_5.toPlainText())
            matrix[1,0]=float(self.plainTextEdit2_1.toPlainText())
            matrix[1,1]=float(self.plainTextEdit2_2.toPlainText())
            matrix[1,2]=float(self.plainTextEdit2_3.toPlainText())
            matrix[1,3]=float(self.plainTextEdit2_4.toPlainText())
            matrix[1,4]=float(self.plainTextEdit2_5.toPlainText())
            matrix[2,0]=float(self.plainTextEdit3_1.toPlainText())
            matrix[2,1]=float(self.plainTextEdit3_2.toPlainText())
            matrix[2,2]=float(self.plainTextEdit3_3.toPlainText())
            matrix[2,3]=float(self.plainTextEdit3_4.toPlainText())
            matrix[2,4]=float(self.plainTextEdit3_5.toPlainText())
            matrix[3,0]=float(self.plainTextEdit4_1.toPlainText())
            matrix[3,1]=float(self.plainTextEdit4_2.toPlainText())
            matrix[3,2]=float(self.plainTextEdit4_3.toPlainText())
            matrix[3,3]=float(self.plainTextEdit4_4.toPlainText())
            matrix[3,4]=float(self.plainTextEdit4_5.toPlainText())
            matrix[4,0]=float(self.plainTextEdit5_1.toPlainText())
            matrix[4,1]=float(self.plainTextEdit5_2.toPlainText())
            matrix[4,2]=float(self.plainTextEdit5_3.toPlainText())
            matrix[4,3]=float(self.plainTextEdit5_4.toPlainText())
            matrix[4,4]=float(self.plainTextEdit5_5.toPlainText())
            if (matrix.max()==0):
                matrix[:,:]=1
        self.Matrix=matrix

    def coustomizefilter(self):
        self.getmatrix()
        self.image_temp=ndimage.correlate(self.image_temp,self.Matrix)
        self.showView4(self.image_temp)

    def binaryerosion(self):
        self.getmatrix()
        self.image_temp=ndimage.binary_erosion(self.image_temp,self.Matrix)
        self.showView4(self.image_temp)

    def binarydilation(self):
        self.getmatrix()
        self.image_temp=ndimage.binary_dilation(self.image_temp,self.Matrix)
        self.showView4(self.image_temp)

    def distancetransform(self):
        Size=self.image_temp.shape
        distance=np.zeros(Size)
        distance=distance+self.image_temp
        self.getmatrix()
        while (self.image_temp.max()!=0):
            self.image_temp=ndimage.binary_erosion(self.image_temp,self.Matrix)
            distance=distance+self.image_temp
        self.image_temp=self.image
        self.showView4(distance)

    def clearall(self):
        self.scene2.clear()
        self.scene3.clear()
        self.scene4.clear()
        self.image_temp=self.image

    def skeleton(self):
        Size=self.image_temp.shape
        skeleton=np.zeros(Size)
        self.store=np.zeros(Size)
        skeleton_remain=self.image_temp
        i=1
        while (skeleton_remain.max()!=0):
            skeleton_remain=ndimage.binary_erosion(self.image_temp,np.ones([2*i-1,2*i-1]))
            subset=skeleton_remain-ndimage.binary_opening(skeleton_remain,np.ones([3,3]))
            skeleton=np.logical_or(skeleton,subset)
            self.store=self.store+subset*i
            i=i+1
        self.showView4(skeleton)

    def skeletonrestoration(self):
        i=self.store.max()
        Size=self.image_temp.shape
        result=mid_result=np.zeros(Size)
        while (i!=0):
            index= self.store == i
            mid_result=ndimage.binary_dilation(index,np.ones([2*i-1,2*i-1]))
            result=np.logical_or(result,mid_result)
            i=i-1
        self.showView4(result)

    def grayerosion(self):
        self.getmatrix()
        self.image_temp=ndimage.grey_erosion(self.image_temp,footprint=self.Matrix)
        self.showView4(self.image_temp)

    def graydilation(self):
        self.getmatrix()
        self.image_temp=ndimage.grey_dilation(self.image_temp,footprint=self.Matrix)
        self.showView4(self.image_temp)

    def getEdgeType(self):
        Type='S'
        if (self.S.isChecked()):
            Type='S'
        if (self.I.isChecked()):
            Type='I'
        if (self.E.isChecked()):
            Type='E'
        return Type

    def edgedetection(self):
        Type=self.getEdgeType()
        Size=self.image_temp.shape
        EdgeImage=np.zeros(Size)
        if (Type=='S'):
            EdgeImage=ndimage.grey_dilation(self.image_temp,footprint=np.ones([3,3]))-ndimage.grey_erosion(self.image_temp,footprint=np.ones([3,3]))
        if (Type=='I'):
            EdgeImage=self.image_temp-ndimage.grey_erosion(self.image_temp,footprint=np.ones([3,3]))
        if (Type=='E'):
            EdgeImage=ndimage.grey_dilation(self.image_temp,footprint=np.ones([3,3]))-self.image_temp
        self.showView4(EdgeImage)

    def gradient(self):
        Type=self.getEdgeType()
        Size=self.image_temp.shape
        EdgeImage=np.zeros(Size)
        if (Type=='S'):
            EdgeImage=(ndimage.grey_dilation(self.image_temp,footprint=np.ones([3,3]))-ndimage.grey_erosion(self.image_temp,footprint=np.ones([3,3])))/2
        if (Type=='I'):
            EdgeImage=(self.image_temp-ndimage.grey_erosion(self.image_temp,footprint=np.ones([3,3])))/2
        if (Type=='E'):
            EdgeImage=(ndimage.grey_dilation(self.image_temp,footprint=np.ones([3,3]))-self.image_temp)/2
        self.showView4(EdgeImage)

    def reconstruction_binary(self):
        Size=self.image_temp.shape
        Mark_temp=np.zeros(Size)
        Mark=np.zeros(Size)
        Mark[:,112]=1
        while ((not np.array_equal(Mark,Mark_temp))):
            Mark_temp=Mark
            Mark=ndimage.binary_dilation(Mark,np.ones([3,3]))
            Mark=np.logical_and(Mark,self.image_temp)
        self.showView4(Mark)

    def reconstruction_gray(self):
        Size=self.image_temp.shape
        Mark_temp=np.zeros(Size)
        Mark=np.zeros(Size)
        Mark[:,112]=self.image_temp[:,112]
        while ((not np.array_equal(Mark,Mark_temp))):
            Mark_temp=Mark
            Mark=ndimage.grey_dilation(Mark,footprint=np.ones([3,3]))
            logical=Mark >= self.image_temp
            Mark=Mark-Mark*logical+self.image_temp*logical
        self.showView4(Mark)
Ejemplo n.º 26
0
class BrushingModel(QObject):
    brushSizeChanged = pyqtSignal(int)
    brushColorChanged = pyqtSignal(QColor)
    brushStrokeAvailable = pyqtSignal(QPointF, object)
    drawnNumberChanged = pyqtSignal(int)

    minBrushSize = 1
    maxBrushSize = 61
    defaultBrushSize = 3
    defaultDrawnNumber = 1
    defaultColor = Qt.white
    erasingColor = Qt.black
    erasingNumber = 100

    def __init__(self, parent=None):
        QObject.__init__(self, parent=parent)
        self.sliceRect = None
        self.bb = QRect()  #bounding box enclosing the drawing
        self.brushSize = self.defaultBrushSize
        self.drawColor = self.defaultColor
        self._temp_color = None
        self._temp_number = None
        self.drawnNumber = self.defaultDrawnNumber

        self.pos = None
        self.erasing = False
        self._hasMoved = False

        self.drawOnto = None

        #an empty scene, where we add all drawn line segments
        #a QGraphicsLineItem, and which we can use to then
        #render to an image
        self.scene = QGraphicsScene()

    def toggleErase(self):
        self.erasing = not (self.erasing)
        if self.erasing:
            self.setErasing()
        else:
            self.disableErasing()

    def setErasing(self):
        self.erasing = True
        self._temp_color = self.drawColor
        self._temp_number = self.drawnNumber
        self.setBrushColor(self.erasingColor)
        self.brushColorChanged.emit(self.erasingColor)
        self.setDrawnNumber(self.erasingNumber)

    def disableErasing(self):
        self.erasing = False
        self.setBrushColor(self._temp_color)
        self.brushColorChanged.emit(self.drawColor)
        self.setDrawnNumber(self._temp_number)

    def setBrushSize(self, size):
        self.brushSize = size
        self.brushSizeChanged.emit(self.brushSize)

    def setDrawnNumber(self, num):
        self.drawnNumber = num
        self.drawnNumberChanged.emit(num)

    def getBrushSize(self):
        return self.brushSize

    def brushSmaller(self):
        b = self.brushSize
        if b > self.minBrushSize:
            self.setBrushSize(b - 1)

    def brushBigger(self):
        b = self.brushSize
        if self.brushSize < self.maxBrushSize:
            self.setBrushSize(b + 1)

    def setBrushColor(self, color):
        self.drawColor = QColor(color)
        self.brushColorChanged.emit(self.drawColor)

    def beginDrawing(self, pos, sliceRect):
        '''

        pos -- QPointF-like
        '''
        self.sliceRect = sliceRect
        self.scene.clear()
        self.bb = QRect()
        self.pos = QPointF(pos.x(), pos.y())
        self._hasMoved = False

    def endDrawing(self, pos):
        has_moved = self._hasMoved  # _hasMoved will change after calling moveTo
        if has_moved:
            self.moveTo(pos)
        else:
            assert (self.pos == pos)
            self.moveTo(QPointF(pos.x() + 0.0001,
                                pos.y() + 0.0001))  # move a little

        # Qt seems to use strange rules for determining which pixels to set when rendering a brush stroke to a QImage.
        # We seem to get better results if we do the following:
        # 1) Slightly offset the source window because apparently there is a small shift in the data
        # 2) Render the scene to an image that is MUCH larger than the scene resolution (4x by 4x)
        # 3) Downsample each 4x4 patch from the large image back to a single pixel in the final image,
        #     applying some threshold to determine if the final pixel is on or off.

        tempi = QImage(QSize(4 * self.bb.width(), 4 * self.bb.height()),
                       QImage.Format_ARGB32_Premultiplied)  #TODO: format
        tempi.fill(0)
        painter = QPainter(tempi)
        # Offset the source window.  At first I thought the right offset was 0.5, because
        #  that would seem to make sure points are rounded to pixel CENTERS, but
        #  experimentation indicates that 0.25 is slightly better for some reason...
        source_rect = QRectF(QPointF(self.bb.x() + 0.25,
                                     self.bb.y() + 0.25),
                             QSizeF(self.bb.width(), self.bb.height()))
        target_rect = QRectF(QPointF(0, 0),
                             QSizeF(4 * self.bb.width(), 4 * self.bb.height()))
        self.scene.render(painter, target=target_rect, source=source_rect)
        painter.end()

        # Now downsample: convert each 4x4 patch into a single pixel by summing and dividing
        ndarr = qimage2ndarray.rgb_view(tempi)[:, :, 0].astype(int)
        ndarr = ndarr.reshape((ndarr.shape[0], ) + (ndarr.shape[1] // 4, ) +
                              (4, ))
        ndarr = ndarr.sum(axis=-1)
        ndarr = ndarr.transpose()
        ndarr = ndarr.reshape((ndarr.shape[0], ) + (ndarr.shape[1] // 4, ) +
                              (4, ))
        ndarr = ndarr.sum(axis=-1)
        ndarr = ndarr.transpose()
        ndarr //= 4 * 4

        downsample_threshold = (7. / 16) * 255
        labels = numpy.where(ndarr >= downsample_threshold,
                             numpy.uint8(self.drawnNumber), numpy.uint8(0))
        labels = labels.swapaxes(0, 1)
        assert labels.shape[0] == self.bb.width()
        assert labels.shape[1] == self.bb.height()

        ##
        ## ensure that at least one pixel is label when the brush size is 1
        ##
        ## this happens when the user just clicked without moving
        ## in that case the lineitem will be so tiny, that it won't be rendered
        ## into a single pixel by the code above
        if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(
                labels) == 0:
            labels[labels.shape[0] // 2,
                   labels.shape[1] // 2] = self.drawnNumber

        self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()),
                                       labels)

    def dumpDraw(self, pos):
        res = self.endDrawing(pos)
        self.beginDrawing(pos, self.sliceRect)
        return res

    def moveTo(self, pos):
        #data coordinates
        oldX, oldY = self.pos.x(), self.pos.y()
        x, y = pos.x(), pos.y()

        line = QGraphicsLineItem(oldX, oldY, x, y)
        line.setPen(
            QPen(QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap,
                 Qt.RoundJoin))
        self.scene.addItem(line)
        self._hasMoved = True

        #update bounding Box
        if not self.bb.isValid():
            self.bb = QRect(QPoint(oldX, oldY), QSize(1, 1))
        #grow bounding box
        self.bb.setLeft(
            min(self.bb.left(), max(0, x - self.brushSize // 2 - 1)))
        self.bb.setRight(
            max(self.bb.right(),
                min(self.sliceRect[0] - 1, x + self.brushSize // 2 + 1)))
        self.bb.setTop(min(self.bb.top(), max(0, y - self.brushSize // 2 - 1)))
        self.bb.setBottom(
            max(self.bb.bottom(),
                min(self.sliceRect[1] - 1, y + self.brushSize // 2 + 1)))

        #update/move position
        self.pos = pos
Ejemplo n.º 27
0
class Spectrum(QWidget):
    """Plot the power spectrum for a specified channel.

    Attributes
    ----------
    parent : instance of QMainWindow
        the main window.
    x_limit : tuple or list
        2 values specifying the limit on x-axis
    y_limit : tuple or list
        2 values specifying the limit on y-axis
    log : bool
        log-transform the data or not
    idx_chan : instance of QComboBox
        the element with the list of channel names.
    idx_x_min : instance of QLineEdit
        value with min x value
    idx_x_max : instance of QLineEdit
        value with max x value
    idx_y_min : instance of QLineEdit
        value with min y value
    idx_y_max : instance of QLineEdit
        value with max y value
    idx_log : instance of QCheckBox
        widget that defines if log should be used or not
    idx_fig : instance of QGraphicsView
        the view with the power spectrum
    scene : instance of QGraphicsScene
        the scene with GraphicsItems

    Notes
    -----
    If data contains NaN, it doesn't create any spectrum (feature or bug?).
    """
    def __init__(self, parent):
        super().__init__()
        self.parent = parent

        self.config = ConfigSpectrum(self.display_window)

        self.selected_chan = None
        self.idx_chan = None
        self.idx_fig = None
        self.scene = None

        self.create()

    def create(self):
        """Create empty scene for power spectrum."""
        self.idx_chan = QComboBox()
        self.idx_chan.activated.connect(self.display_window)

        self.idx_fig = QGraphicsView(self)
        self.idx_fig.scale(1, -1)

        layout = QVBoxLayout()
        layout.addWidget(self.idx_chan)
        layout.addWidget(self.idx_fig)
        self.setLayout(layout)

        self.resizeEvent(None)

    def show_channame(self, chan_name):
        self.selected_chan = self.idx_chan.currentIndex()

        self.idx_chan.clear()
        self.idx_chan.addItem(chan_name)
        self.idx_chan.setCurrentIndex(0)

    def update(self):
        """Add channel names to the combobox."""
        self.idx_chan.clear()
        for chan_name in self.parent.traces.chan:
            self.idx_chan.addItem(chan_name)

        if self.selected_chan is not None:
            self.idx_chan.setCurrentIndex(self.selected_chan)
            self.selected_chan = None

    def display_window(self):
        """Read the channel name from QComboBox and plot its spectrum.

        This function is necessary it reads the data and it sends it to
        self.display. When the user selects a smaller chunk of data from the
        visible traces, then we don't need to call this function.
        """
        if self.idx_chan.count() == 0:
            self.update()

        chan_name = self.idx_chan.currentText()
        lg.info('Power spectrum for channel ' + chan_name)

        if chan_name:
            trial = 0
            data = self.parent.traces.data(trial=trial, chan=chan_name)
            self.display(data)
        else:
            self.scene.clear()

    def display(self, data):
        """Make graphicsitem for spectrum figure.

        Parameters
        ----------
        data : ndarray
            1D vector containing the data only

        This function can be called by self.display_window (which reads the
        data for the selected channel) or by the mouse-events functions in
        traces (which read chunks of data from the user-made selection).
        """
        value = self.config.value
        self.scene = QGraphicsScene(value['x_min'], value['y_min'],
                                    value['x_max'] - value['x_min'],
                                    value['y_max'] - value['y_min'])
        self.idx_fig.setScene(self.scene)

        self.add_grid()
        self.resizeEvent(None)

        s_freq = self.parent.traces.data.s_freq
        f, Pxx = welch(data, fs=s_freq,
                       nperseg=int(min((s_freq, len(data)))))  # force int

        freq_limit = (value['x_min'] <= f) & (f <= value['x_max'])

        if self.config.value['log']:
            Pxx_to_plot = log(Pxx[freq_limit])
        else:
            Pxx_to_plot = Pxx[freq_limit]

        self.scene.addPath(Path(f[freq_limit], Pxx_to_plot),
                           QPen(QColor(LINE_COLOR), LINE_WIDTH))

    def add_grid(self):
        """Add axis and ticks to figure.

        Notes
        -----
        I know that visvis and pyqtgraphs can do this in much simpler way, but
        those packages create too large a padding around the figure and this is
        pretty fast.

        """
        value = self.config.value

        # X-AXIS
        # x-bottom
        self.scene.addLine(value['x_min'], value['y_min'],
                           value['x_min'], value['y_max'],
                           QPen(QColor(LINE_COLOR), LINE_WIDTH))
        # at y = 0, dashed
        self.scene.addLine(value['x_min'], 0,
                           value['x_max'], 0,
                           QPen(QColor(LINE_COLOR), LINE_WIDTH, Qt.DashLine))
        # ticks on y-axis
        y_high = int(floor(value['y_max']))
        y_low = int(ceil(value['y_min']))
        x_length = (value['x_max'] - value['x_min']) / value['x_tick']
        for y in range(y_low, y_high):
            self.scene.addLine(value['x_min'], y,
                               value['x_min'] + x_length, y,
                               QPen(QColor(LINE_COLOR), LINE_WIDTH))
        # Y-AXIS
        # left axis
        self.scene.addLine(value['x_min'], value['y_min'],
                           value['x_max'], value['y_min'],
                           QPen(QColor(LINE_COLOR), LINE_WIDTH))
        # larger ticks on x-axis every 10 Hz
        x_high = int(floor(value['x_max']))
        x_low = int(ceil(value['x_min']))
        y_length = (value['y_max'] - value['y_min']) / value['y_tick']
        for x in range(x_low, x_high, 10):
            self.scene.addLine(x, value['y_min'],
                               x, value['y_min'] + y_length,
                               QPen(QColor(LINE_COLOR), LINE_WIDTH))
        # smaller ticks on x-axis every 10 Hz
        y_length = (value['y_max'] - value['y_min']) / value['y_tick'] / 2
        for x in range(x_low, x_high, 5):
            self.scene.addLine(x, value['y_min'],
                               x, value['y_min'] + y_length,
                               QPen(QColor(LINE_COLOR), LINE_WIDTH))

    def resizeEvent(self, event):
        """Fit the whole scene in view.

        Parameters
        ----------
        event : instance of Qt.Event
            not important

        """
        value = self.config.value
        self.idx_fig.fitInView(value['x_min'],
                               value['y_min'],
                               value['x_max'] - value['x_min'],
                               value['y_max'] - value['y_min'])

    def reset(self):
        """Reset widget as new"""
        self.idx_chan.clear()
        if self.scene is not None:
            self.scene.clear()
        self.scene = None
Ejemplo n.º 28
0
class TrainerDialog(QDialog, Ui_Trainer):
    scene = None
    data_manager = None
    tooth1 = None
    tooth2 = None
    align_step = 0

    pca = None

    trained = pyqtSignal(PCA)

    def __init__(self, data_manager):
        super(TrainerDialog, self).__init__()
        self.setupUi(self)

        self.setAttribute(Qt.WA_DeleteOnClose)
        self.scene = QGraphicsScene()
        self.scene.setBackgroundBrush(QBrush(QColor.fromRgb(50, 50, 50)))
        self.graphicsView.setScene(self.scene)

        self.alignButton.clicked.connect(self.make_step)
        self.trainButton.clicked.connect(self.train)

        assert isinstance(data_manager, DataManager)
        self.data_manager = data_manager

        self.change_teeth(1)
        teeth = data_manager.get_all_teeth(False)
        self.choiceSlider.setRange(1, len(teeth) - 1)
        self.choiceSlider.valueChanged.connect(self.change_teeth)

    def change_teeth(self, idx):
        teeth = self.data_manager.get_all_teeth(True)
        self.tooth1 = teeth[0]
        self.tooth2 = teeth[idx]

        self.tooth1.outline_pen = QPen(QColor.fromRgb(255, 0, 0))
        self.tooth2.outline_pen = QPen(QColor.fromRgb(0, 255, 0))

        self.scene.clear()
        self.tooth1.draw(self.scene, True, False, False)
        self.tooth2.draw(self.scene, True, False, False)
        self._focus_view()
        self.align_step = 0

    def make_step(self):
        if self.align_step == 3:
            return

        if self.align_step == 0:
            self.tooth1.move_to_origin()
            self.tooth2.move_to_origin()

        if self.align_step == 1:
            self.tooth1.normalize_shape()
            self.tooth2.normalize_shape()
            self.tooth1.outline_pen.setWidthF(0.02)
            self.tooth2.outline_pen.setWidthF(0.02)

        if self.align_step == 2:
            self.tooth2.align(self.tooth1)

        self.scene.clear()
        self.tooth1.draw(self.scene, True, False, False)
        self.tooth2.draw(self.scene, True, False, False)
        self._focus_view()
        self.align_step += 1

    def _focus_view(self):
        rect = self.scene.itemsBoundingRect()
        self.scene.setSceneRect(rect)
        self.graphicsView.fitInView(rect, Qt.KeepAspectRatio)

    def train(self):
        self.pca = StatisticalShapeModel.create(self.data_manager)
        self.pca.threshold(self.thresholdSpinBox.value())
        self._show_training_result()

        self.trained.emit(self.pca)

    def _show_training_result(self):
        mean_tooth = Tooth(to_landmarks_format(self.pca.mean))
        test_tooth = self.data_manager.get_tooth(0, 0, True)
        test_tooth.align(mean_tooth)

        tooth_data = test_tooth.landmarks.flatten()
        projection = self.pca.project(tooth_data)
        reconstructed_data = self.pca.reconstruct(projection)

        shapes = [self.pca.mean, tooth_data, reconstructed_data]
        colors = [[255, 0, 0], [0, 255, 255], [255, 255, 0]]

        self.scene.clear()
        for i, shape in enumerate(shapes):
            tooth = Tooth(to_landmarks_format(shape))
            r, g, b = colors[i]
            tooth.outline_pen = QPen(QColor.fromRgb(r, g, b))
            tooth.outline_pen.setWidthF(0.02)
            tooth.draw(self.scene, True, False, False)

        self._focus_view()
        self.compCountLabel.setText(str(len(self.pca.eigen_values)))
Ejemplo n.º 29
0
class qfi_VSI (QGraphicsView):

    viewUpdate = pyqtSignal()


    def __init__(self,winParent):
        QGraphicsView.__init__(self)

        self.winParent=winParent

        self.viewUpdate.connect(self.update)
        
        self.m_climbRate = 0

        self.m_scaleX = 0
        self.m_scaleY = 0

        self.m_originalHeight = 240
        self.m_originalWidth = 240

        self.m_originalVsiCtr = QPointF(120,120)


        self.m_faceZ = -20
        self.m_handZ = -10
        self.m_caseZ = 10

        self.m_itemHand = None
        self.m_itemFace = None
        self.m_itemCase = None

        self.setStyleSheet("background: transparent; border: none");
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.setInteractive(False)
        self.setEnabled(False)


        self.m_scene = QGraphicsScene(self)
        
        self.setScene(self.m_scene)

        self.init()

        

    def init (self):
        self.m_scaleX = self.width() / self.m_originalWidth
        self.m_scaleY = self.height() / self.m_originalHeight


        self.m_itemHand = QGraphicsSvgItem(":/qfi/images/vsi/vsi_hand.svg")
        self.m_itemHand.setCacheMode (QGraphicsItem.NoCache)
        self.m_itemHand.setZValue( self.m_handZ )
        self.m_itemHand.setTransform( QTransform.fromScale( self.m_scaleX, self.m_scaleY ), True )
        self.m_itemHand.setTransformOriginPoint( self.m_originalVsiCtr )
        self.m_scene.addItem (self.m_itemHand)

        self.m_itemFace = QGraphicsSvgItem(":/qfi/images/vsi/vsi_face.svg")
        self.m_itemFace.setCacheMode (QGraphicsItem.NoCache)
        self.m_itemFace.setZValue( self.m_faceZ )
        self.m_itemFace.setTransform( QTransform.fromScale( self.m_scaleX, self.m_scaleY ), True )
        self.m_itemFace.setTransformOriginPoint( self.m_originalVsiCtr )
        self.m_scene.addItem (self.m_itemFace)


        self.m_itemCase = QGraphicsSvgItem(":/qfi/images/vsi/vsi_case.svg")
        self.m_itemCase.setCacheMode (QGraphicsItem.NoCache)
        self.m_itemCase.setZValue( self.m_caseZ )
        self.m_itemCase.setTransform( QTransform.fromScale( self.m_scaleX, self.m_scaleY ), True )
        self.m_itemCase.setTransformOriginPoint( self.m_originalVsiCtr )
        self.m_scene.addItem (self.m_itemCase)

        self.centerOn (self.width()/2, self.height()/2)

        self.updateView()

    def reinit(self):
        if (self.m_scene):
            self.m_scene.clear()
            self.init()


    def update(self):
        self.updateView()


    def setClimbRate (self, climbRate):
        self.m_climbRate = climbRate

        if (self.m_climbRate < -2000):
            self.m_climbRate = -2000
        if (self.m_climbRate > 2000):
            self.m_climbRate = 2000


    def resizeEvent (self, event):
        QGraphicsView.resizeEvent (self,event)
        self.reinit()

    def reset (self):
        self.m_itemHand = None
        self.m_itemFace = None
        self.m_itemCase   = None

        self.m_climbRate =  0.0


    def updateView(self):

        self.m_itemHand.setRotation( self.m_climbRate * 0.086 )

        self.m_scene.update()
class CircuitDiagramView(QGraphicsView):
	mousePress = pyqtSignal(tuple, tuple, name='mousePress')
	mouseMove = pyqtSignal(tuple, tuple, name='mouseMove')
	mouseRelease = pyqtSignal(tuple, tuple, name='mouseRelease')

	def __init__(self, parent=None):
		QGraphicsView.__init__(self, parent)

		self._model = None
		self.controller = None

		self.setAcceptDrops(True)

		# setup & render circuit diagram grid
		self.scene = QGraphicsScene()
		self.setScene(self.scene)

		self._shouldShowSelection = False
		self._selection = None
		self._dragging = False
		self.mousePosition = None
		self.draggingStart = None

		self.render()

	@property
	def shouldShowSelection(self):
		return self._shouldShowSelection

	@shouldShowSelection.setter
	def shouldShowSelection(self, value):
		if self.shouldShowSelection is not value and value is not None:
			self._shouldShowSelection = value
			self.render()		

	@property
	def model(self):
		return self._model

	@model.setter
	def model(self, value):
		self._model = value
		self.model.modelChanged.connect(self.render)

	@property
	def selection(self):
		return self._selection

	@selection.setter
	def selection(self, value):
		if self.selection is not value:
			self._selection = value
			self.render()	

	@property
	def dragging(self):
		return self._dragging

	@dragging.setter
	def dragging(self, value):
		self._dragging = value
		self.render()

	def componentTypeToImageName(self, componentType):
		dictionary = {
			ComponentType.Battery: "assets/battery.png",
			ComponentType.Resistor: "assets/resistor.png",
			ComponentType.Voltmeter: "assets/voltmeter.png",
			ComponentType.Ammeter: "assets/ammeter.png",
			ComponentType.Switch: "assets/switch-off.png",
			ComponentType.Bulb: "assets/bulb-off.png",
			ComponentType.Button: "assets/button-off.png",
		}

		return dictionary[componentType]

	def componentToImage(self, component):
		if component.type == ComponentType.Wire:
			image = QPixmap("assets/icon.png").scaled(self.blockSideLength, self.blockSideLength)
			if component.numberOfConnections() == 1:
				image = QPixmap("assets/wire-top.png").scaled(self.blockSideLength, self.blockSideLength)
				if component.connections[Direction.Right] is not None:
					image = image.transformed(QtGui.QTransform().rotate(90))
				elif component.connections[Direction.Bottom] is not None:
					image = image.transformed(QtGui.QTransform().rotate(180))
				elif component.connections[Direction.Left] is not None:
					image = image.transformed(QtGui.QTransform().rotate(270))
			elif component.numberOfConnections() == 2:
				if component.connections[Direction.Left] is not None and component.connections[Direction.Right] is not None:
					image = QPixmap("assets/wire-left-right.png").scaled(self.blockSideLength, self.blockSideLength)
				elif component.connections[Direction.Top] is not None and component.connections[Direction.Bottom] is not None:
					image = QPixmap("assets/wire-left-right.png").scaled(self.blockSideLength, self.blockSideLength).transformed(QtGui.QTransform().rotate(90))
				elif component.connections[Direction.Top] is not None and component.connections[Direction.Right] is not None:
					image = QPixmap("assets/wire-top-right.png").scaled(self.blockSideLength, self.blockSideLength)
				elif component.connections[Direction.Top] is not None and component.connections[Direction.Left] is not None:
					image = QPixmap("assets/wire-top-right.png").scaled(self.blockSideLength, self.blockSideLength).transformed(QtGui.QTransform().rotate(270))
				elif component.connections[Direction.Bottom] is not None and component.connections[Direction.Right] is not None:
					image = QPixmap("assets/wire-top-right.png").scaled(self.blockSideLength, self.blockSideLength).transformed(QtGui.QTransform().rotate(90))
				elif component.connections[Direction.Bottom] is not None and component.connections[Direction.Left] is not None:
					image = QPixmap("assets/wire-top-right.png").scaled(self.blockSideLength, self.blockSideLength).transformed(QtGui.QTransform().rotate(180))
			elif component.numberOfConnections() == 3:
				image = QPixmap("assets/wire-left-top-right.png").scaled(self.blockSideLength, self.blockSideLength)
				if component.connections[Direction.Left] is None:
					image = image.transformed(QtGui.QTransform().rotate(90))
				elif component.connections[Direction.Top] is None:
					image = image.transformed(QtGui.QTransform().rotate(180))
				elif component.connections[Direction.Right] is None:
					image = image.transformed(QtGui.QTransform().rotate(270))
			return image
		else:
			imageName = "assets/wire-right.png"
		
			if component.type == ComponentType.Bulb:
				if component.isOn():
					imageName = "assets/bulb-on.png"
				else:
					imageName = "assets/bulb-off.png"
			elif component.type == ComponentType.Switch:
				if component.closed:
					imageName = "assets/switch-on.png"
				else:
					imageName = "assets/switch-off.png"
			elif component.type == ComponentType.Button:
				if component.closed:
					imageName = "assets/button-on.png"
				else:
					imageName = "assets/button-off.png"
			else:
				imageName = self.componentTypeToImageName(component.type)
			
			return QPixmap(imageName).scaled(self.blockSideLength, self.blockSideLength)

	def mouseCoordinatesToBlockIndex(self, x, y):
		if self.model is None or x < self.startingX or y < self.startingY or x > self.startingX + self.model.gridSize * self.blockSideLength or y > self.startingY + self.model.gridSize * self.blockSideLength:
			return (-1, -1)
		else:
			return (int((x - self.startingX) / self.blockSideLength), int((y - self.startingY) / self.blockSideLength))

	def blockIndexToCoordinate(self, x, y):
		return (self.startingX + self.blockSideLength * x, self.startingY + self.blockSideLength * y)

	def mousePressEvent(self, event):
		index = self.mouseCoordinatesToBlockIndex(event.x(), event.y())
		self.mousePress.emit(index, (event.x(), event.y()))

	def dragEnterEvent(self, event):
		event.acceptProposedAction()

	def dragMoveEvent(self, event):
		index = self.mouseCoordinatesToBlockIndex(event.pos().x(), event.pos().y())
		self.mouseMove.emit(index, (event.pos().x(), event.pos().y()))

	def dropEvent(self, event):
		event.acceptProposedAction()
		index = self.mouseCoordinatesToBlockIndex(event.pos().x(), event.pos().y())
		self.mouseRelease.emit(index, (event.pos().x(), event.pos().y()))
		
	def mouseMoveEvent(self, event):
		self.mousePosition = (event.x(), event.y())
		if self.dragging:
			self.render()
		index = self.mouseCoordinatesToBlockIndex(event.x(), event.y())
		self.mouseMove.emit(index, (event.pos().x(), event.pos().y()))

	def mouseReleaseEvent(self, event):
		index = self.mouseCoordinatesToBlockIndex(event.x(), event.y())
		self.mouseRelease.emit(index, (event.pos().x(), event.pos().y()))

	def resizeEvent(self, event):
		self.render()

	def render(self):
		if self.model is not None:
			self.scene.clear()
			self.renderCircuitDiagramGrid() 
			self.renderComponents() 

	def renderComponents(self):
		if self.model is not None:
			for component in self.model.components:
				pixmap = self.componentToImage(component)
				pixmapItem = self.scene.addPixmap(pixmap)
				offset = self.blockIndexToCoordinate(component.position[0],component.position[1])
				pixmapItem.setOffset(offset[0],offset[1])
				pixmapItem.setTransformationMode(Qt.SmoothTransformation)
		
				if component is self.selection:
					if self.dragging:
						renderPosition = (self.startingX + self.selection.position[0] * self.blockSideLength + self.mousePosition[0] - self.draggingStart[0], self.startingY + self.selection.position[1] * self.blockSideLength + self.mousePosition[1] - self.draggingStart[1])
						pixmapItem.setOffset(renderPosition[0], renderPosition[1])
					elif self.shouldShowSelection:
						pen = QPen(QBrush(QColor(0,0,255,100)), 2, Qt.DashLine)
						self.scene.addRect(self.startingX + component.position[0] * self.blockSideLength, self.startingY + component.position[1] * self.blockSideLength, self.blockSideLength, self.blockSideLength, pen)
				if component.type is ComponentType.Ammeter:
					font = QFont("Arial", self.blockSideLength/3.5)
					reading = self.scene.addText(str("%.2f" % component.current) + "A", font)
					offset = self.blockIndexToCoordinate(component.position[0],component.position[1])
					reading.setPos(offset[0]+self.blockSideLength/20,offset[1]+self.blockSideLength/4)
				elif component.type is ComponentType.Voltmeter:
					font = QFont("Arial", self.blockSideLength/3.5)
					reading = self.scene.addText(str("%.2f" % component.voltage) + "V", font)
					offset = self.blockIndexToCoordinate(component.position[0],component.position[1])
					reading.setPos(offset[0]+self.blockSideLength/20,offset[1]+self.blockSideLength/4)

	def renderCircuitDiagramGrid(self):
		pen = QPen(QBrush(QColor(200,200,200,255)), 1)
		pen2 = QPen(QBrush(QColor(100,100,100,255)), 3)
		width = self.width()
		height = self.height()
		self.blockSideLength = width / (self.model.gridSize + 2) if width < height else height / (self.model.gridSize + 2)

		# draw vertical lines
		currentX = width / 2
		self.startingX = currentX - (self.model.gridSize / 2) * self.blockSideLength
		while currentX - self.blockSideLength >= 0:
			currentX -= self.blockSideLength
		
		while currentX < width:
			self.scene.addLine(currentX, 1, currentX, height - 1, pen)
			
			currentX += self.blockSideLength

		# draw horizontal lines
		currentY = height / 2
		self.startingY = currentY - (self.model.gridSize / 2) * self.blockSideLength
		while currentY - self.blockSideLength >= 0:
			currentY -= self.blockSideLength
		while currentY < height:
			self.scene.addLine(1, currentY, width - 1, currentY, pen)
			currentY += self.blockSideLength

		self.scene.addLine(self.startingX, self.startingY, self.startingX + self.model.gridSize * self.blockSideLength, self.startingY, pen2)
		self.scene.addLine(self.startingX, self.startingY + self.model.gridSize * self.blockSideLength, self.startingX + self.model.gridSize * self.blockSideLength, self.startingY + 10 * self.blockSideLength, pen2)
		self.scene.addLine(self.startingX, self.startingY, self.startingX, self.startingY + self.model.gridSize * self.blockSideLength, pen2)
		self.scene.addLine(self.startingX + self.model.gridSize * self.blockSideLength, self.startingY, self.startingX + self.model.gridSize * self.blockSideLength, self.startingY + 10 * self.blockSideLength, pen2)
Ejemplo n.º 31
0
class CanvasModel(object):
    def __init__(self):
        self.scene = QGraphicsScene() # Canvas area
        self.scale_factor = 1 # Scaling factor
        self.original_image = None # Original image, used for scaling
        self.image = None # Image viewable in our canvas
        self.c_width = 0 # Container width
        self.c_height = 0 # Container height
        
    def set_image(self, image):
        self.original_image = image

    def setGeometry(self, container_width, container_height):
        self.c_width = container_width
        self.c_height = container_height
        self.scene.setSceneRect(0, 0, self.c_width, self.c_height)

    def update_image(self, selection):
        # Check for container width to prevent behaviour when container is not initialized yet (ex. passing an image as argument)
        if self.original_image is not None and self.c_width != 0:
            # Selection defines the viewport behaviour
            # 0: Ratio scaling (uses canvas/image-size)
            # 1: Scale to container width
            # 2: Scale to container height
            # 3: Scale to original size
            if selection == 0:
                ratio = [self.original_image.width() / self.c_width, self.original_image.height() / self.c_height]
                if ratio[0] > 1 and ratio[0] > ratio[1]:
                    self.image = self.original_image.scaledToWidth(self.c_width, Qt.SmoothTransformation)
                elif ratio[1] > 1 and ratio[1] > ratio[0]:
                    self.image = self.original_image.scaledToHeight(self.c_height, Qt.SmoothTransformation)
                else: # Small image, show in original size
                    self.image = self.original_image
            elif selection == 1:
                self.image = self.original_image.scaledToWidth(self.c_width, Qt.SmoothTransformation)
            elif selection == 2:
                self.image = self.original_image.scaledToHeight(self.c_height, Qt.SmoothTransformation)
            elif selection == 3:
                self.image = self.original_image

            # Update scene
            self.scene.clear()
            self.scene.addItem(CustomQGraphicsPixmapItem(QPixmap.fromImage(self.image), self.c_width, self.c_height))
            self.scene.update()

    def scale_image(self, factor):
        if self.original_image is not None:
            self.scale_factor *= factor
            self.image = self.original_image.scaled(self.image.width() * self.scale_factor, self.image.height() * self.scale_factor, Qt.KeepAspectRatio, Qt.SmoothTransformation)
            # Reset scale factor
            self.scale_factor = 1
 
            self.scene.clear()
            self.scene.addItem(CustomQGraphicsPixmapItem(QPixmap.fromImage(self.image), self.c_width, self.c_height))
            self.scene.update()

    def rotate_image(self, rotation):
        if self.original_image is not None:
            print(rotation)
            # Rotate the original and viewable image to ensure a constant workflow when modifying from canvas
            matrix = QTransform()
            matrix.translate(self.image.width() / 2, self.image.height() / 2)
            matrix.rotate(rotation)
            matrix.translate(-self.image.width() / 2, -self.image.height() / 2)
            
            # Save transformed image
            self.image = self.image.transformed(matrix)
           
            original_matrix = QTransform()
            original_matrix.translate(self.original_image.width() / 2, self.original_image.height() / 2)
            original_matrix.rotate(rotation)
            original_matrix.translate(-self.original_image.width() / 2, -self.original_image.height() / 2)
            
            # Save transformed image
            self.original_image = self.original_image.transformed(original_matrix)

            self.scene.clear()
            self.scene.addItem(CustomQGraphicsPixmapItem(QPixmap.fromImage(self.image), self.c_width, self.c_height))
            self.scene.update()

    def flip_image(self, direction):
        if self.original_image is not None:
            if direction == 0:
                self.image = self.image.mirrored(True, False)
                self.original_image = self.original_image.mirrored(True, False)
            else:
                self.image = self.image.mirrored(False, True)
                self.original_image = self.original_image.mirrored(False, True)

            self.scene.clear()
            self.scene.addItem(CustomQGraphicsPixmapItem(QPixmap.fromImage(self.image), self.c_width, self.c_height))
            self.scene.update()    
Ejemplo n.º 32
0
class Shufti(ShuftiWindow):
    
    def __init__(self):
        super(Shufti,self).__init__()
        try:
            self.key = sys.argv[1]
        except IndexError:
            print('\nshufti 2.2\n\nTo use shufti from the terminal, you must specify the full path to an image as a parameter.\n')
            sys.exit(1)
        self.dbSanitise()
        self.formats = ('.png', '.jpg', '.jpeg', '.gif', '.bmp', '.pbm', '.pgm', '.ppm',
         '.xbm', '.xpm', '.dds', '.icns', '.jp2', '.mng', '.tga', '.tiff', '.wbmp', '.webp')
        try:
            open(self.key, 'r')
        except IOError:
            print('There was an error opening the file')
            sys.exit(1)
        
        if self.key.lower().endswith(self.formats):
            # If inshuft = 0, the image is not in shufti's image database
            self.inshuft = 0
            self.rotval = 0
            self.rotvals = (0,-90,-180,-270)
            self.dbfile = expanduser("~/.config/shufti/shufti.db")
            self.dbdir = os.path.dirname(self.dbfile)
            if not os.path.isfile(self.dbfile):
                self.createDB()
            self.db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
            self.db.setDatabaseName(self.dbfile)
            self.db.open()
            self.query = QtSql.QSqlQuery()
            self.dbSearch(self.dbkey)
            # Set common window attributes
            self.path, self.title = os.path.split(self.key)
            self.setWindowTitle(str(self.title))
            self.img = QPixmap(self.key)
            self.scene = QGraphicsScene()
            self.scene.addPixmap(self.img)
            self.view = ShuftiView(self.scene, self)
            self.view.setDragMode(QGraphicsView.ScrollHandDrag)
            self.view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
            self.view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
            # Create array of images in current image dir
            self.imgfiles = []
            for filename in glob.glob(str(self.path) + '/*'):
                base, ext = os.path.splitext(filename)
                if ext.lower() in self.formats:
                    self.imgfiles.append(filename)
            # Find location of current image in imgfiles array
            self.dirpos = 0
            while self.dirpos < len(self.imgfiles) and self.imgfiles[self.dirpos] != self.key:
                self.dirpos += 1
            # If we have no inshuftery, we use the defaults
            if self.inshuft == 0:
                self.newImage()
            else:
                self.oldImage()
        else:
            print("Unsupported file format")
            sys.exit(1)
        
    def newImage(self):               
        
        self.zoom = 1
        self.rotate = 0
        self.resize(self.img.size())
        self.view.resize(self.img.width() + 2, self.img.height() + 2)
        self.show()
        self.view.verticalScrollBar().setValue(0)
        self.view.horizontalScrollBar().setValue(0)
        
    def oldImage(self):
        
        if self.rotate == -90:
            self.rotval = 1
        elif self.rotate == -180:
            self.rotval = 2
        elif self.rotate == -270:
            self.rotval = 3
        self.resize(self.img.size())
        self.updateView()
        self.show()
        self.setGeometry(self.winposx, self.winposy, self.winsizex, self.winsizey)
        self.view.verticalScrollBar().setValue(self.vscroll)
        self.view.horizontalScrollBar().setValue(self.hscroll)
        
    def toggleFullscreen(self):
        
        if self.isFullScreen():
            self.showNormal()
        else:
            self.showFullScreen()
            
    def keyPressEvent(self, event):
        
        if event.key() == QtCore.Qt.Key_F11:
            self.toggleFullscreen()
        elif event.key() == QtCore.Qt.Key_Equal or event.key() == QtCore.Qt.Key_E:
            self.zoomIn()
        elif event.key() == QtCore.Qt.Key_Minus or event.key() == QtCore.Qt.Key_D:
            self.zoomOut()
        elif event.key() == QtCore.Qt.Key_1:
            self.zoomReset()
        elif event.key() == QtCore.Qt.Key_S:
            self.rotateImg(-1)
        elif event.key() == QtCore.Qt.Key_R:
            self.rotateImg(1)
        elif event.key() == QtCore.Qt.Key_F:
            self.fitView()
        elif event.key() == QtCore.Qt.Key_Space:
            self.dirBrowse(1)
        elif event.key() == QtCore.Qt.Key_Backspace:
            self.dirBrowse(-1)
        elif event.key() == QtCore.Qt.Key_V:
            self.vertMax()
        elif event.key() == QtCore.Qt.Key_Z:
            self.horizMax()
        elif event.key() == QtCore.Qt.Key_Q:
            self.close()
            
    def mouseDoubleClickEvent(self, event):
        
        self.toggleFullscreen()
            
    def createDB(self):
        
        if not os.path.exists(self.dbdir):
            os.makedirs(self.dbdir)
        self.db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
        self.db.setDatabaseName(self.dbfile)
        self.query = QtSql.QSqlQuery()
        self.db.open()
        self.query.exec_("create table shuftery(filename text primary key, "
        "zoom real, winposx int, winposy int, winsizex int, winsizey int, "
        "hscroll int, vscroll int, rotate int)")
        return True
        
    def zoomIn(self):
        
        self.zoom *= 1.05
        self.updateView()
        
    def zoomOut(self):
        
        self.zoom /= 1.05
        self.updateView()
        
    def zoomReset(self):
        
        self.zoom = 1
        self.updateView()
        
    def rotateImg(self, clock):
        
        self.rotval += clock
        if self.rotval == 4:
            self.rotval = 0
        elif self.rotval < 0:
            self.rotval = 3
        self.rotate = self.rotvals[self.rotval]
        self.updateView()
        
    def fitView(self):
        
        self.view.fitInView(self.scene.sceneRect(), QtCore.Qt.KeepAspectRatio)
        if self.rotate == 0:
            self.zoom = self.view.transform().m11()
        elif self.rotate == -90:
            self.zoom = (self.view.transform().m12()) * -1
        elif self.rotate == -180:
            self.zoom = (self.view.transform().m11()) * -1
        else:
            self.zoom = self.view.transform().m12()
        
    def updateView(self):
        
        self.view.setTransform(QTransform().scale(self.zoom, self.zoom).rotate(self.rotate))
        
    def winState(self):
        
        self.winsizex = self.geometry().width()
        self.winsizey = self.geometry().height()
        self.vscroll = self.view.verticalScrollBar().value()
        self.hscroll = self.view.horizontalScrollBar().value()
        self.winposx = self.pos().x()
        self.winposy = self.pos().y()
        
    def dbInsert(self):
        
        self.query.exec_("insert into shuftery values('%s" % self.dbkey + 
        "', " + str(self.zoom) + ", " + str(self.winposx) + ", " + str(self.winposy) + 
        ", " + str(self.winsizex) + ", " + str(self.winsizey) + ", " + str(self.hscroll) + 
        ", " + str(self.vscroll) + ", " + str(self.rotate) + ")")
        
    def dbUpdate(self):
        
        self.query.exec_("update shuftery set zoom=" + str(self.zoom) + 
        ", winposx=" + str(self.winposx) + ", winposy=" + str(self.winposy) + 
        ", winsizex=" + str(self.winsizex) + ", winsizey=" + str(self.winsizey) + 
        ", hscroll=" + str(self.hscroll) + ", vscroll=" + str(self.vscroll) + 
        ", rotate=" + str(self.rotate) + " where filename='%s'" % self.dbkey)
        
    def dbSearch(self, field):
        
        self.query.exec_("SELECT * FROM shuftery WHERE filename='%s'" % field)
        # If the image is found in shufti.db, load the previous view settings
        while self.query.next() and self.inshuft == 0:
            self.zoom = self.query.value(1)
            self.winposx = self.query.value(2)
            self.winposy = self.query.value(3)
            self.winsizex = self.query.value(4)
            self.winsizey = self.query.value(5)
            self.hscroll = self.query.value(6)
            self.vscroll = self.query.value(7)
            self.rotate = self.query.value(8)
            self.inshuft = 1
    
    def dbSanitise(self):
        
        self.dbkey = self.key.replace("\"", "\"\"")
        self.dbkey = self.dbkey.replace("\'", "\'\'")
        self.dbkey = self.dbkey.replace("\\", "\\\\")
        
    def dirBrowse(self, direc):
        
        if len(self.imgfiles) > 1:
            self.dirpos += direc
            if self.dirpos > (len(self.imgfiles) - 1):
                self.dirpos = 0
            elif self.dirpos < 0:
                self.dirpos = (len(self.imgfiles) - 1)
            shufti.winState()
            if self.inshuft == 0:
                shufti.dbInsert()
            else:
                shufti.dbUpdate()
            self.key = self.imgfiles[self.dirpos]
            self.dbSanitise()
            self.path, self.title = os.path.split(self.key)
            self.setWindowTitle(str(self.title) + " - shufti")
            self.inshuft = 0
            self.dbSearch(self.dbkey)
            self.scene.clear()
            self.view.resetTransform()
            self.img = QPixmap(self.key)
            self.scene.addPixmap(self.img)
            if self.inshuft == 0:
                self.newImage()
            else:
                self.oldImage()
                
    def vertMax(self):
        
        self.screen_res = app.desktop().availableGeometry(shufti)
        self.screenh = self.screen_res.height()
        self.winsizex = self.geometry().width()
        self.winposx = self.pos().x()
        self.setGeometry(self.winposx, 0, self.winsizex, self.screenh)
        
    def horizMax(self):
        
        self.screen_res = app.desktop().availableGeometry(shufti)
        self.screenw = self.screen_res.width()
        self.winsizey = self.geometry().height()
        self.winposy = self.pos().y()
        self.setGeometry(0, self.winposy, self.screenw, self.winsizey)
        
    def about(self):
        
        self.pop = AboutShufti()
        self.pop.resize(450, 200)
        self.pop.setWindowTitle("About shufti")
        self.pop.show()
Ejemplo n.º 33
0
class ExportDialog(QMainWindow, Ui_MainWindow):
    """
    Окно экспорта
    """
    def __init__(self, parent, settings: str):
        super().__init__()
        self.setupUi(self)

        self.parent = parent
        self.image_format = 4
        self.file = ''
        self.export_dir_template = os.path.sep
        self.export_file_template = ""

        self.bg_item = None

        self.settings = json.loads(settings)
        self.csv_headers = []

        self.links = dict()
        self.test_row = dict()

        self.openFileBtn.clicked.connect(self.open_file)

        self.nextPushButton.clicked.connect(self.next_slide)
        self.prevPushButton.clicked.connect(self.prev_slide)
        self.toolButtonChangeDir.clicked.connect(self.open_dir)
        self.startGen.clicked.connect(self.export)

        self.stackedWidget.currentChanged.connect(self.slide_change)

        self.scene = QGraphicsScene()
        self.graphicsView = QGraphicsView()
        self.graphicsView.setObjectName("graphicsView")
        self.graphicsView.setFocus()
        self.linkSettinghorizontalLayout.insertWidget(0, self.graphicsView, 0)

        self.graphicsView.setScene(self.scene)

        self.spinBoxRow.valueChanged.connect(self.reload_row)

        self.encodingComboBox.currentTextChanged.connect(self.render_table)
        self.haveHeaderCheckBox.stateChanged.connect(self.render_table)
        self.delimiterLineEdit.editingFinished.connect(self.render_table)
        self.lineEditDir.editingFinished.connect(self.edit_path)
        self.lineEditFileMask.editingFinished.connect(self.edit_file)
        self.strDelimiterLineEdit.editingFinished.connect(self.render_table)

        self.textBrowserDirs.anchorClicked.connect(self.dir_link_click)
        self.textBrowserFileName.anchorClicked.connect(self.file_link_click)

    def reload_row(self, i):
        self.test_row = self.get_csv_row(i)
        self.render_items()

    def get_csv_row(self, row=1):
        data = dict()
        for i, name in enumerate(self.csv_headers):
            itm = self.csvTable.item(row, i)
            if itm:
                data[name] = itm.text()
            else:
                data[name] = ''
        return data

    def get_links_dict(self):
        data = dict()
        for row in range(self.tableLinkSettings.rowCount()):
            itm_name = self.tableLinkSettings.item(row, 0)
            itm_data = self.tableLinkSettings.cellWidget(row, 1)
            if itm_name and itm_data:
                name = itm_name.text()
                data[name] = self.tableLinkSettings.cellWidget(
                    row, 1).currentText()
        return data

    def render_preview(self):
        if self.settings['bg']:
            if self.bg_item:
                for item in self.scene.items():
                    if item != self.bg_item:
                        self.scene.removeItem(item)
            else:
                self.scene.clear()
                img = QPixmap(self.settings['bg'])
                self.image_format = img.toImage().format()
                self.bg_item = QGraphicsPixmapItem(img)
                self.scene.addItem(self.bg_item)
            self.scene.update()

    def render_items(self, event=None):
        self.links = self.get_links_dict()
        self.render_preview()
        for item in self.settings['items']:
            text = QGraphicsTextItem()
            font_color = QColor('black')

            text.setPos(QPointF(item['x'], item['y']))

            font = QFont()
            font_name = item['params'].get(const.ITEM_DATA_KEY_FONT)
            if font_name:
                font.fromString(font_name)
                font_size = item['params'].get(const.ITEM_DATA_KEY_FONT_SIZE)
                if font_size:
                    font.setPointSize(font_size)
                else:
                    font.setPointSize(12)
                font_color_list = item['params'].get(
                    const.ITEM_DATA_KEY_FONT_COLOR)
                if font_color_list:
                    font_color.setRgb(*font_color_list)
                text.setFont(font)
            text_align = item['params'].get(const.ITEM_DATA_KEY_FONT_ALIGN)

            text.setFont(font)
            text.setTextWidth(item['w'])
            text.setDefaultTextColor(font_color)

            text.setHtml(
                f"<div align='{text_align}'>{self.test_row[self.links[item['name']]]}</div>"
            )

            self.scene.addItem(text)

    def edit_path(self, *args):
        self.export_dir_template = self.lineEditDir.text()
        self.build_path(self.test_row)

    def edit_file(self, *args):
        self.export_file_template = self.lineEditFileMask.text()
        self.build_path(self.test_row)

    def build_path(self, row: dict, preview=True):
        path = self.export_dir_template
        selected_path = self.lineEditSaveDir.text()
        if selected_path:
            path = selected_path + path

        for k, v in row.items():
            path = path.replace(f'#{k}#', v)

        path = os.path.abspath(os.path.normpath(path))

        if self.export_file_template:
            path = path + os.path.sep + self.export_file_template + '.png'

        for k, v in row.items():
            path = path.replace(f'#{k}#', v)

        if preview:
            self.dirPreview.setText(path)
        else:
            return path

    def dir_link_click(self, url):
        sep = ''
        if self.export_dir_template:
            if self.export_dir_template[-1] != os.path.sep:
                sep = os.path.sep
        else:
            sep = os.path.sep

        self.export_dir_template = self.export_dir_template + sep + url.toString(
        ) + '#'
        self.lineEditDir.setText(self.export_dir_template)
        self.build_path(self.test_row)

    def file_link_click(self, url):
        self.export_file_template = self.export_file_template + url.toString(
        ) + '#'
        self.lineEditFileMask.setText(self.export_file_template)
        self.build_path(self.test_row)

    def update_buttons(self):
        html = ['<ul>']
        for h in self.csv_headers:
            li = f"<li><a href='#{h}'>#{h}#</a></li>"
            html.append(li)
        html.append('</ul>')
        self.textBrowserDirs.setHtml(const.DIRS_HTML + "\n".join(html))
        self.textBrowserFileName.setHtml(const.FILE_MASK_HTML +
                                         "\n".join(html))

    def update_settings_table(self):
        self.tableLinkSettings.setRowCount(0)

        fields = [itm['name'] for itm in self.settings['items']]
        fields.sort()

        self.update_buttons()

        for i, field in enumerate(fields):
            field_item = QtWidgets.QTableWidgetItem(field)
            field_item.setFlags(field_item.flags() ^ Qt.ItemIsEditable)

            self.tableLinkSettings.setRowCount(
                self.tableLinkSettings.rowCount() + 1)
            self.tableLinkSettings.setItem(i, 0, field_item)

            combo_box = QtWidgets.QComboBox(self)
            combo_box.addItems(self.csv_headers)
            combo_box.currentTextChanged.connect(self.render_items)

            self.tableLinkSettings.setCellWidget(i, 1, combo_box)

        self.test_row = self.get_csv_row()
        self.render_items()

    def slide_change(self, index):
        cnt = self.stackedWidget.count() - 1

        if index == 0:
            self.prevPushButton.setEnabled(False)
        else:
            self.prevPushButton.setEnabled(True)

        if index == cnt:
            self.nextPushButton.setEnabled(False)
        else:
            self.nextPushButton.setEnabled(True)

    def next_slide(self):
        cnt = self.stackedWidget.count() - 1
        current = self.stackedWidget.currentIndex()
        if current + 1 <= cnt:
            self.stackedWidget.setCurrentIndex(current + 1)

    def prev_slide(self):
        current = self.stackedWidget.currentIndex()
        if current - 1 >= 0:
            self.stackedWidget.setCurrentIndex(current - 1)

    def open_file(self):
        self.file = QFileDialog.getOpenFileName(self,
                                                'Открыть файл',
                                                filter="CSV (*.csv)")[0]
        self.lineEditSaveDir.setText(
            os.path.dirname(os.path.abspath(self.file)))
        self.selectedFile.setText("Файл: " + self.file)
        self.render_table()
        self.nextPushButton.setEnabled(True)

    def open_dir(self):
        dir = QFileDialog.getExistingDirectory(self, 'Выбор директории')
        if dir:
            self.lineEditSaveDir.setText(dir)
            self.build_path(self.test_row)

    def render_table(self):
        if not self.file:
            return
        self.csvTable.clear()

        self.csv.setCursor(QCursor(Qt.WaitCursor))
        have_head = self.haveHeaderCheckBox.checkState() != 0
        with open(self.file,
                  encoding=self.encodingComboBox.currentText()) as csv_file:
            reader = csv.reader(csv_file,
                                delimiter=self.delimiterLineEdit.text(),
                                quotechar=self.strDelimiterLineEdit.text())
            if have_head:
                title = next(reader)
                self.csv_headers = title
                self.csvTable.setColumnCount(len(title))
                self.csvTable.setHorizontalHeaderLabels(title)
            else:
                title_len = len(next(reader))
                self.csvTable.setColumnCount(title_len)
                self.csv_headers = list(
                    map(lambda x: str(x + 1), range(title_len)))
                csv_file.seek(0)

            self.csvTable.setRowCount(0)
            for i, row in enumerate(reader):
                self.csvTable.setRowCount(self.csvTable.rowCount() + 1)
                for j, elem in enumerate(row):
                    self.csvTable.setItem(i, j, QTableWidgetItem(elem))
            self.spinBoxRow.setMaximum(i)
            self.progressBar.setMaximum(i)
            self.csvTable.resizeColumnsToContents()

        self.csv.setCursor(QCursor(Qt.ArrowCursor))
        self.update_settings_table()

    def export(self):
        for i in range(self.csvTable.rowCount()):
            self.progressBar.setValue(i)
            self.reload_row(i)

            file_name = self.build_path(self.test_row, preview=False)
            path = os.path.dirname(file_name)
            if not os.path.exists(path):
                os.makedirs(path)

            img = QImage(self.scene.sceneRect().size().toSize(),
                         self.image_format)
            img.fill(Qt.transparent)

            painter = QPainter(img)
            painter.setRenderHint(QPainter.Antialiasing)
            self.scene.render(painter)

            if not img.save(file_name, quality=100):
                print('fail', file_name)
            else:
                del painter  # нужно дропать обязательно, иначе в памяти остается связь и оно ложится
                del img  # что бы это понять я потратил 3 часа
class qfi_TC(QGraphicsView):

    viewUpdate = pyqtSignal()

    def __init__(self, winParent):
        QGraphicsView.__init__(self)

        self.winParent = winParent

        self.viewUpdate.connect(self.updateView)

        self.m_itemBack = None
        self.m_itemBall = None
        self.m_itemFace_1 = None
        self.m_itemFace_2 = None
        self.m_itemMark = None
        self.m_itemCase = None

        self.m_turnRate = 0
        self.m_slipSkid = 0

        self.m_scaleX = 0
        self.m_scaleY = 0

        self.m_originalHeight = 240
        self.m_originalWidth = 240

        self.m_originalMarkCtr = QPointF(120, 120)
        self.m_originalBallCtr = QPointF(120, -36)

        self.m_backZ = -70
        self.m_ballZ = -60
        self.m_face1Z = -50
        self.m_face2Z = -40
        self.m_markZ = -30
        self.m_caseZ = 10

        self.setStyleSheet("background: transparent; border: none")
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.setInteractive(False)
        self.setEnabled(False)

        self.reset()

        self.m_scene = QGraphicsScene(self)
        self.setScene(self.m_scene)

        self.m_scene.clear()
        self.init()

    def init(self):
        self.m_scaleX = self.width() / self.m_originalWidth
        self.m_scaleY = self.height() / self.m_originalHeight

        self.reset()

        self.m_itemBack = QGraphicsSvgItem(":/qfi/images/tc/tc_back.svg")
        self.m_itemBack.setCacheMode(QGraphicsItem.NoCache)
        self.m_itemBack.setZValue(self.m_backZ)
        self.m_itemBack.setTransform(
            QTransform.fromScale(self.m_scaleX, self.m_scaleY), True)
        self.m_scene.addItem(self.m_itemBack)

        self.m_itemBall = QGraphicsSvgItem(":/qfi/images/tc/tc_ball.svg")
        self.m_itemBall.setCacheMode(QGraphicsItem.NoCache)
        self.m_itemBall.setZValue(self.m_ballZ)
        self.m_itemBall.setTransform(
            QTransform.fromScale(self.m_scaleX, self.m_scaleY), True)
        self.m_itemBall.setTransformOriginPoint(self.m_originalBallCtr)
        self.m_scene.addItem(self.m_itemBall)

        self.m_itemFace_1 = QGraphicsSvgItem(":/qfi/images/tc/tc_face_1.svg")
        self.m_itemFace_1.setCacheMode(QGraphicsItem.NoCache)
        self.m_itemFace_1.setZValue(self.m_face1Z)
        self.m_itemFace_1.setTransform(
            QTransform.fromScale(self.m_scaleX, self.m_scaleY), True)
        self.m_scene.addItem(self.m_itemFace_1)

        self.m_itemFace_2 = QGraphicsSvgItem(":/qfi/images/tc/tc_face_2.svg")
        self.m_itemFace_2.setCacheMode(QGraphicsItem.NoCache)
        self.m_itemFace_2.setZValue(self.m_face2Z)
        self.m_itemFace_2.setTransform(
            QTransform.fromScale(self.m_scaleX, self.m_scaleY), True)
        self.m_scene.addItem(self.m_itemFace_2)

        self.m_itemMark = QGraphicsSvgItem(":/qfi/images/tc/tc_mark.svg")
        self.m_itemMark.setCacheMode(QGraphicsItem.NoCache)
        self.m_itemMark.setZValue(self.m_markZ)
        self.m_itemMark.setTransform(
            QTransform.fromScale(self.m_scaleX, self.m_scaleY), True)
        self.m_itemMark.setTransformOriginPoint(self.m_originalMarkCtr)
        self.m_scene.addItem(self.m_itemMark)

        self.m_itemCase = QGraphicsSvgItem(":/qfi/images/tc/tc_case.svg")
        self.m_itemCase.setCacheMode(QGraphicsItem.NoCache)
        self.m_itemCase.setZValue(self.m_caseZ)
        self.m_itemCase.setTransform(
            QTransform.fromScale(self.m_scaleX, self.m_scaleY), True)
        self.m_scene.addItem(self.m_itemCase)

        self.centerOn(self.width() / 2, self.height() / 2)

        self.updateView()

    def reinit(self):
        if (self.m_scene):
            self.m_scene.clear()
            self.init()

    def update(self):
        self.updateView()

    def setTurnRate(self, turnRate):
        self.m_turnRate = turnRate
        if (self.m_turnRate < -6):
            self.m_turnRate = -6
        if (self.m_turnRate > 6):
            self.m_turnRate = 6

    def setSlipSkid(self, slipSkid):
        self.m_slipSkid = slipSkid
        if (self.m_slipSkid < -15):
            self.m_slipSkid = -15
        if (self.m_slipSkid > 15):
            self.m_slipSkid = 15

    def resizeEvent(self, event):
        QGraphicsView.resizeEvent(self, event)
        self.reinit()

    def reset(self):
        self.m_itemCase = None

        self.m_turnRate = 0
        self.m_slipSkid = 0

    def updateView(self):
        self.m_scaleX = self.width() / self.m_originalWidth
        self.m_scaleY = self.height() / self.m_originalHeight

        self.m_itemBall.setRotation(-self.m_slipSkid)

        angle = (self.m_turnRate / 3) * 20

        self.m_itemMark.setRotation(angle)
        self.m_scene.update()
class StaticPhotos(QGraphicsView):
    def __init__(self, photoBaseDir, validPhotoFileExts, photoDeltas, picChangeMs, parent=None):
        QGraphicsView.__init__(self, parent)
        self.setAlignment(Qt.AlignLeft | Qt.AlignTop)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) 
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) 
        # Vars
        self.picChangeMs = picChangeMs
        self.photoBaseDir = photoBaseDir
        # Widget
        self.scene = QGraphicsScene()
        self.setScene(self.scene)
        self.setBackgroundBrush(QColor("black"))
        self.setLineWidth(0)
        self.setFrameShape(QtWidgets.QFrame.NoFrame)
        # Class vars
        self.picChgTimer = None
        self.photoFileManager = PhotoFileManager(validPhotoFileExts, self.photoBaseDir, 7200.00, photoDeltas)
        self.photoFileManager.startPhotoListUpdate()
        self.userMovedBack = False

    # def sizeHint(self):
    #     return QSize(600, 400)

    def resizeEvent(self, evt=None):
        xWindowSize = self.width()
        yWindowSize = self.height()
        pass

    def start(self):
        self.picChgTimer = QTimer()
        self.picChgTimer.setInterval(self.picChangeMs)
        self.picChgTimer.setSingleShot(True)
        self.picChgTimer.timeout.connect(self.picChangeFn)
        self.picChgTimer.start()
        # self.picChangeFn()
        print("Static Photos - starting")

    def stop(self):
        if self.picChgTimer is not None:
            self.picChgTimer.stop()
            print("Static Photos - stopping")
            # self.picChgTimer.disconnect(self.picChangeFn)
        self.photoFileManager.stop()

    def moveNext(self):
        self.nextPicItem()

    def movePrev(self):
        self.prevPicItem()
        self.userMovedBack = True

    def reshow(self):
        self.showImage()

    def getCurPhotoFilename(self):
        return self.photoFileManager.getCurPhotoFilename()

    def picChangeFn(self):
        # pass
        if self.userMovedBack:
            # Skip this update
            self.userMovedBack = False
        else:
            self.nextPicItem()
        self.picChgTimer.setInterval(self.picChangeMs)
        self.picChgTimer.start()

    def loadImage(self):
        self.newImg = QImage()
        self.newImg.load(self.photoFileManager.getCurPhotoFilename())
        self.newImgInfo = self.photoFileManager.getCurPhotoInfo()
        transform = QTransform()
        transform.rotate(self.newImgInfo.rotationAngle)
        self.interImg = self.newImg.transformed(transform, Qt.SmoothTransformation)
        # xReqdSize = self.cellSize.width() * xFactor + self.xBetweenPics * (xFactor-1)
        # yReqdSize = self.cellSize.height() * yFactor + self.yBetweenPics * (yFactor-1)
        self.inter2Img = self.interImg.scaled(QSize(self.width(),self.height()),
                                                    Qt.KeepAspectRatio, Qt.SmoothTransformation)
        # finalImg = interImg.copy(0,0,xReqdSize,yReqdSize)
        # print("XY Size", xFactor, yFactor, xReqdSize,yReqdSize)
        return self.inter2Img, self.newImgInfo

    def showImage(self):
        (newImg, newImgInfo) = self.loadImage()
        # return PicItem(Pixmap(QPixmap(newImg)), -1, -1, xFactor, yFactor, newImgInfo)
        self.scene.clear()
        imgSz = newImgInfo.imgSize
        self.setSceneRect(QRectF(0,0,imgSz.width(), imgSz.height()))
        pixMap = QPixmap.fromImage(newImg)
        # # pixMap.setWidth(self.width())
        pixMapItem = self.scene.addPixmap(pixMap)
        # pixMapItem.setPos(50,50)
        # self.fitInView(QRectF(0, 0, self.width(), self.height()), Qt.KeepAspectRatio)
        # Add caption
        caption = QGraphicsTextItem()
        caption.setDefaultTextColor(QColor(255,255,255))
        caption.setPos(0, self.height()*0.94)
        caption.setFont(QFont("Segoe UI", 30))
        caption.setTextWidth(self.width())
        # caption.setPos(100, 100)
        # caption.setTextWidth(1500)
        # if newImgInfo.createDate is not None:
        #     caption.setPlainText(newImgInfo.createDate.format());
        # else:
        #     caption.setPlainText("Image is called bananas");
        # print("Tags", newImgInfo.tags)
        # tagStr = ""
        # for tag in newImgInfo.tags:
        #     if tag != "Duplicate":
        #         tagStr += (", " if len(tagStr) != 0 else "") + tag
        # if tagStr == "":
        #     tagStr = "NO TAGS"
        # captionStr = '<h1 style="text-align:center;width:100%">' + tagStr + '</h1>'
        # if newImgInfo.createDate is not None:
        #     print(newImgInfo.createDate.format())
        #     captionStr += '<BR><h2>' + newImgInfo.createDate.format() + '</h2>'

        captionStr = ""
        try:
            if newImgInfo.rating is not None:
                for i in range(newImgInfo.rating):
                    captionStr += "&#x2605;"
                for i in range(5-newImgInfo.rating):
                    captionStr += "&#x2606;"
            if newImgInfo.mainDate is not None:
                if len(captionStr) != 0:
                    captionStr += "  "
                captionStr += newImgInfo.mainDate.strftime("%d %b %Y")
        except Exception as excp:
            print("StaticPhotos: Cannot set caption")
        captionStr = '<div style="background-color:#000000;text-align: right;padding-right:10dp;">' + captionStr + "</div>"
        print(captionStr)
        caption.setHtml(captionStr)
        self.scene.addItem(caption)
        self.scene.update()

    def prevPicItem(self):
        if self.photoFileManager.getNumPhotos() == 0:
            return None
        self.photoFileManager.movePrev()
        # print ("Loaded photo", self.sourcePhotoList[self.curPhotoIdx], " w", finalImg.width(), " h", finalImg.height(), " facs", xFactor, yFactor)
        self.showImage()

    def nextPicItem(self):
        if self.photoFileManager.getNumPhotos() == 0:
            return None
        # print ("Loaded photo", self.sourcePhotoList[self.curPhotoIdx], " w", finalImg.width(), " h", finalImg.height(), " facs", xFactor, yFactor)
        self.photoFileManager.moveNext()
        self.showImage()

    def keyPressEvent(self, event): #QKeyEvent
        event.ignore()
Ejemplo n.º 36
0
class ImageView(QGraphicsView):

    rightMouseButtonPressed = pyqtSignal(float, float)

    def __init__(self, parent=None):
        super(ImageView, self).__init__(parent)

        self.scene = QGraphicsScene()
        self.setScene(self.scene)
        self._pixmapHandle = None
        self.aspectRatioMode = Qt.KeepAspectRatio

        # self.setDragMode(QGraphicsView.ScrollHandDrag)

        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.rightMouseButtonPressed.connect(self.handleRightClick)

        self.zoom = -1

    def hasImage(self):
        return self._pixmapHandle is not None

    def clearImage(self):
        """ Removes the current image pixmap from the scene if it exists.
        """
        if self.hasImage():
            self.scene.removeItem(self._pixmapHandle)
            self._pixmapHandle = None
            self.zoom = -1
            self.scene.clear()

    def pixmap(self):
        """ Returns the scene's current image pixmap as a QPixmap, or else None if no image exists.
        :rtype: QPixmap | None
        """
        if self.hasImage():
            return self._pixmapHandle.pixmap()
        return None

    def image(self):
        """ Returns the scene's current image pixmap as a QImage, or else None if no image exists.
        :rtype: QImage | None
        """
        if self.hasImage():
            return self._pixmapHandle.pixmap().toImage()
        return None

    def setImage(self, image):
        """ Set the scene's current image pixmap to the input QImage or QPixmap.
        Raises a RuntimeError if the input image has type other than QImage or QPixmap.
        :type image: QImage | QPixmap
            """
        if type(image) is QPixmap:
            pixmap = image
        elif type(image) is QImage:
            pixmap = QPixmap.fromImage(image)
        else:
            raise RuntimeError(
                "ImageViewer.setImage: Argument must be a QImage or QPixmap.")
        if self.hasImage():
            self._pixmapHandle.setPixmap(pixmap)
        else:
            self._pixmapHandle = self.scene.addPixmap(pixmap)
        self.setSceneRect(QRectF(
            pixmap.rect()))  # Set scene size to image size.
        self.updateViewer()

    def updateViewer(self):
        """ Show current zoom (if showing entire image, apply current aspect ratio mode).
        """
        if not self.hasImage():
            return
        if self.zoom < 0:
            self.fitInView(self.sceneRect(), self.aspectRatioMode)
            self.zoom = self.size().width() / self.scene.width()
        else:
            self.setTransform(QTransform().scale(self.zoom, self.zoom))

    def wheelEvent(self, event):
        moose = event.angleDelta().y()

        if moose > 0:
            self.zoomIn()
        elif moose < 0:
            self.zoomOut()

    def zoomIn(self):
        self.zoom *= 1.05
        self.updateViewer()

    def zoomOut(self):
        self.zoom /= 1.05
        self.updateViewer()

    def mousePressEvent(self, event):

        if event.button() == Qt.RightButton:

            scenePos = self.mapToScene(event.pos())
            self.rightMouseButtonPressed.emit(scenePos.x(), scenePos.y())

        elif event.button() == Qt.LeftButton:
            self.setDragMode(QGraphicsView.ScrollHandDrag)

        QGraphicsView.mousePressEvent(self, event)

    def mouseReleaseEvent(self, event):

        QGraphicsView.mouseReleaseEvent(self, event)

        if event.button() == Qt.LeftButton:
            self.setDragMode(QGraphicsView.NoDrag)

    def handleRightClick(self, x, y):
        # row = int(y)
        # col = int(x)
        # print("Clicked on image pixel (row="+str(row)+", column="+str(col)+")")
        pass
Ejemplo n.º 37
0
class CharIdentifierInput(QDialog, Ui_CharIdentifierInput):
    """ Get a character

        A dialog for creating / getting a character

        The followings are the operations in the dialog
        -#  Painting a character
        -#  Set : analyze the character drawn which is composed from the following stages
            -#  Transform the character to the size of the main item
            -#  Draw a network composed from squares
            -#  Decide which squares are occupied by the character
        -#  Save : Saves the character
        -#  Load : Loads the character from file
        -#  Cancel : exit and retrun False
        -#  OK : exit and return True

        Graphical structure of the dialog
        -# Vertical box layout
        -#   Buttons horizontal layout
        -#   GraphicsView which holds a
        -#   Graphics scene which hols a
        -#   CharItem
       
    """

    def __init__(self, parent, filename: str=None):
        """CharIdentifierInput constructor
        
            Args:
                parent : The parent window or dialog
                filename : The character will be loaded from the file
        """
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.setFixedSize(mainItemWidth + 2 * mainItemPadding + 40, mainItemHeight + 2 * mainItemPadding + 60)
        self.createGui()
        self.pushButton_set.clicked.connect(self.pushButton_set_clicked)
        self.pushButton_save.clicked.connect(self.pushButton_save_clicked)
        self.pushButton_load.clicked.connect(self.pushButton_load_clicked)
        self.pushButton_cancel.clicked.connect(self.reject)
        self.pushButton_OK.clicked.connect(self.accept)
        self.pushButton_reset.clicked.connect(self.pushButton_reset_clicked)
        self.pushButton_revertSet.clicked.connect(self.pushButton_revertSet_clicked)
        self.dirty = False
        self.filename = filename
        if filename:
            self.pushButton_load_clicked(filename)

    def createGui(self):
        """ Create the scene and the new item
        """
        self.graphicsScene = QGraphicsScene()
        self.graphicsView.setScene(self.graphicsScene)
        self.itemBoundaries = QRectF(0, 0, mainItemWidth, mainItemHeight)
        self.itemPos = QPointF(mainItemPadding + 3, mainItemPadding)
        self.graphicsScene.setSceneRect(0, 0, mainItemWidth + 2 * mainItemPadding, mainItemHeight + 2 * mainItemPadding)
        self.newItem()

    def newItem(self):
        """ Create new main item
        """
        self.mainItem = CharItem(self.itemBoundaries, self.itemPos)
        self.graphicsScene.addItem(self.mainItem)

    def pushButton_set_clicked(self):
        """ Activate the set operation of the main item
        """
        self.mainItem.set()

    def pushButton_save_clicked(self):
        """ Slot : Activate the save operation
        """
        # If there where no changes - return
        if not self.mainItem.dirty:
            QMessageBox.critical(None, "Character Identifier - Save", "Nothing to save")
            return

        # Get the previous filename and path
        path = QFileInfo(self.filename).path() if self.filename else os.path.join(dataDir,
                                                                                  "Chapter 3 - Distance Metrics")
        fname = QFileDialog.getSaveFileName(self, "Character Identifier - Save", path,
                                            "Character Identifier Files (*.chr)")

        # If the user pressed the cancel button in the dialog - return
        if not fname:
            return
        if not fname[0].lower().endswith(".chr"):
            fname[0] += ".chr"
        self.filename = fname[0]

        try:
            # Open the file create the stream and activate the save method of the
            # main item
            fh = QFile(self.filename)
            if not fh.open(QIODevice.WriteOnly):
                raise IOError(fh.errorString())
            stream = QDataStream(fh)
            self.mainItem.save(stream, self.filename)

        except IOError as e:
            QMessageBox.warning(self, "Character Identifier -- Save Error", "Failed to save {}: {}".format(
                self.filename, e))
        finally:
            if fh is not None:
                fh.close()

    def pushButton_load_clicked(self, filename: str=None):
        """ Slot : Activate the load from file operation
        """

        # If the character was not loaded from a file and no save was done
        if not self.filename:
            self.save()
            path = QFileInfo(self.filename).path() if self.filename else os.path.join(
                dataDir, "Chapter 3 - Distance Metrics")
            fname = QFileDialog.getOpenFileName(self, "Character Identifier - Open", path,
                                                "Character Identifier Files (*.chr)")
            if not fname:
                return
            self.filename = fname[0]
            fh = None
        else:
            self.filename = filename

        try:
            fh = QFile(self.filename)

            if not fh.open(QIODevice.ReadOnly):
                raise IOError(fh.errorString())
            items = self.graphicsScene.items()
            while items:
                item = items.pop()
                self.graphicsScene.removeItem(item)
                del item

            stream = QDataStream(fh)
            self.mainItem = CharItem(self.itemBoundaries, self.itemPos)
            self.graphicsScene.addItem(self.mainItem)
            self.mainItem.load(stream, self.filename)
            self.dirty = False
        except IOError as e:
            QMessageBox.warning(self, "Page Designer -- Open Error", "Failed to open {}: {}".format(self.filename, e))
        finally:
            if fh is not None:
                fh.close()

    def accept(self):
        """ Slot : OK exit
        """
        # If the item was not set - set it
        if not self.mainItem.wasSetted:
            self.mainItem.set()

        # Save the item
        self.save()
        return super(CharIdentifierInput, self).accept()

    def save(self):
        """ save operation

            This method is activated before all the operations that cause
            The item to be removed from the screen
        """
        # If the item was changed - ask for saving
        if self.mainItem.dirty:
            if QMessageBox.question(None, "Char Identifier Input", "Do You want to save changes ?",
                                    QMessageBox.StandardButtons(QMessageBox.Yes
                                                                | QMessageBox.No)) == QMessageBox.Yes:
                self.pushButton_save_clicked()

    def reject(self):
        """ Slot : reject operation

            exit the dialog with true
        """
        self.save()
        return super(CharIdentifierInput, self).accept()

    def pushButton_reset_clicked(self):
        """ Slot : clear the presentation
        """
        self.save()
        self.graphicsScene.clear()
        self.graphicsView.viewport().update()
        self.newItem()

    def pushButton_revertSet_clicked(self):
        """ Slot : revert the setting for continue drowning
        """
        self.mainItem.revertTransform()
Ejemplo n.º 38
0
class Ui_MainWindow(QMainWindow, Ui_MainWindowBase):
    def __init__(self):
        super(Ui_MainWindow, self).__init__()
        self.setupUi(self)

        self.videoPlaybackInit()
        self.blocklyInit()
        self.imgInit()
        self.menuInit()

    def videoPlaybackInit(self):
        self.videoPlaybackWidget.hide()
        self.videoPlaybackWidget.frameChanged.connect(self.setFrame, type=Qt.QueuedConnection)
        self.filePath = None

    def blocklyInit(self):
        self.blocklyWebView.setUrl(QtCore.QUrl(blocklyURL))
        self.blocklyEvaluationTimer = QtCore.QTimer(parent=self.blocklyWebView)
        self.blocklyEvaluationTimer.setInterval(1*100)
        self.blocklyEvaluationTimer.timeout.connect(self.evaluateSelectedBlock)
        self.blocklyEvaluationTimer.start()

        self.filterClassHash = None
        self.filter = None
        self.selectedBlockID = None
        self.fgbg = None

    def imgInit(self):
        self.cv_img = cv2.imread(os.path.join(sampleDataPath,"color_filter_test.png"))
        self.im_output = None

        self.inputScene = QGraphicsScene()
        self.inputGraphicsView.setScene(self.inputScene)
        self.inputGraphicsView.resizeEvent = self.inputGraphicsViewResized

        self.outputPixmap = None
        self.outputScene = QGraphicsScene()
        self.outputGraphicsView.setScene(self.outputScene)
        self.outputGraphicsView.resizeEvent = self.outputGraphicsViewResized

        qimg = misc.cvMatToQImage(self.cv_img)
        self.inputPixmap = QPixmap.fromImage(qimg)
        self.inputPixmapItem = QGraphicsPixmapItem(self.inputPixmap)
        self.inputPixmapItem.mousePressEvent = self.getPixmapItemClickedPos
        self.inputScene.addItem(self.inputPixmapItem)

    def menuInit(self):
        self.actionOpenVideo.triggered.connect(self.openVideoFile)
        self.actionOpenImage.triggered.connect(self.openImageFile)
        self.actionSaveVideo.triggered.connect(self.saveVideoFile)

        self.actionSaveFilterData.triggered.connect(self.saveFilterFile)
        self.actionOpenFilterData.triggered.connect(self.openFilterFile)

        self.actionCreateBackground.triggered.connect(self.createBackground)

    def dragEnterEvent(self,event):
        event.acceptProposedAction()

    def dropEvent(self,event):
        mime = event.mimeData()
        if mime.hasUrls():
            urls = mime.urls()
            if len(urls) > 0:
                self.processDropedFile(urls[0].toLocalFile())

        event.acceptProposedAction()

    def closeEvent(self,event):
        pass

    def processDropedFile(self,filePath):
        root,ext = os.path.splitext(filePath)
        if ext == ".filter":
            # Read Filter
            self.openFilterFile(filePath=filePath)
            return
        elif self.openImageFile(filePath=filePath):
            return
        elif self.openVideoFile(filePath=filePath):
            return

    def setFrame(self, frame):
        if frame is not None:
            self.cv_img = frame
            self.updateInputGraphicsView()
            self.evaluateSelectedBlock()

    def setRectangleParameterToBlock(self, topLeft, bottomRight):
        height, width, dim = self.cv_img.shape

        array = [
                [topLeft.x()/width, topLeft.y()/height],
                [bottomRight.x()/width, bottomRight.y()/height]
                ]
        parameters = {'array': '{0}'.format(array)}
        string = json.dumps({k: str(v) for k, v in parameters.items()})
        webFrame = self.blocklyWebView.page().mainFrame()
        webFrame.evaluateJavaScript("Apps.setValueToSelectedBlock({0});".format(string))

    def setArrayParameterToBlock(self, array):
        height, width, dim = self.cv_img.shape

        array = [[x[0]/width, x[1]/height] for x in array]
        parameters = {'array': '{0}'.format(array)}
        string = json.dumps({k: str(v) for k, v in parameters.items()})
        webFrame = self.blocklyWebView.page().mainFrame()
        webFrame.evaluateJavaScript("Apps.setValueToSelectedBlock({0});".format(string))

    def createBackground(self, activated=False):
        if self.videoPlaybackWidget.isOpened():
            self.videoPlaybackWidget.stop()

            bg_dialog = BackgroundGeneratorDialog(self)
            bg_dialog.setWindowModality(Qt.WindowModal)
            bg_dialog.videoPlaybackWidget.copySource(self.videoPlaybackWidget)

            res = bg_dialog.exec()

            if res == QDialog.Accepted:
                if bg_dialog.fgbg is not None:
                    self.fgbg = bg_dialog.fgbg.getBackgroundImage()

    def openVideoFile(self, activated=False, filePath = None):
        if filePath is None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open Video File', userDir)

        if len(filePath) is not 0:
            self.filePath = filePath
            self.fgbg = None

            ret = self.videoPlaybackWidget.openVideo(filePath)
            if ret == False:
                return False

            self.videoPlaybackWidget.show()
            self.filterClassHash = None

            return True

    def openImageFile(self, activated=False, filePath = None):
        if filePath == None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open Image File', userDir)

        if len(filePath) is not 0:
            self.filePath = filePath
            img = cv2.imread(filePath)
            if img is None:
                return False

            self.cv_img = img
            self.fgbg = None

            self.videoPlaybackWidget.hide()
            self.updateInputGraphicsView()

            # Initialize Filter when opening new file.
            self.filterClassHash = None

            return True
        else:
            return False

    def updateInputGraphicsView(self):
        self.inputScene.removeItem(self.inputPixmapItem)
        qimg = misc.cvMatToQImage(self.cv_img)
        self.inputPixmap = QPixmap.fromImage(qimg)

        rect = QtCore.QRectF(self.inputPixmap.rect())
        self.inputScene.setSceneRect(rect)

        self.inputPixmapItem = QGraphicsPixmapItem(self.inputPixmap)
        self.inputScene.addItem(self.inputPixmapItem)

        self.inputGraphicsView.viewport().update()
        self.inputGraphicsViewResized()

    def getPixmapItemClickedPos(self, event):
        pos = event.scenePos().toPoint()
        print(pos)

    def inputPixmapItemClicked(self, event):
        pos = event.scenePos().toPoint()

        img = self.inputPixmap.toImage()
        pix = img.pixel(pos)
        rgb = QColor(pix).name()
        logger.debug("Selected pixel color: {0}".format(rgb))

        parameters = {
                'Color': rgb,
                }
        string = json.dumps(parameters)
        webFrame = self.blocklyWebView.page().mainFrame()
        webFrame.evaluateJavaScript("Apps.setValueToSelectedBlock({0});".format(string))

    def openFilterFile(self, activated=False, filePath = None):
        if filePath is None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open Block File', userDir, "Block files (*.filter)")

        if len(filePath) is not 0:
            logger.debug("Open Filter file: {0}".format(filePath))

            filterIO = FilterIO(filePath)
            self.fgbg = filterIO.getBackgroundImg()

            exec(filterIO.getFilterCode(), globals())

            blockXML = re.sub(r"[\n\r]",'', filterIO.getBlockXMLData())
            frame = self.blocklyWebView.page().mainFrame()
            frame.evaluateJavaScript("Apps.setBlockData('{0}');".format(blockXML))

    def saveFilterFile(self):
        self.blocklyEvaluationTimer.stop()
        if self.filePath is not None:
            candidateFilePath = os.path.splitext(self.filePath)[0] + '.filter'
        else:
            candidateFilePath = userDir
        filePath, _ = QFileDialog.getSaveFileName(None, 'Save Filter File', candidateFilePath, "Filter files (*.filter)")

        if len(filePath) is not 0:
            logger.debug("Saving Filter file: {0}".format(filePath))

            frame = self.blocklyWebView.page().mainFrame()

            filterIO = FilterIO()
            filterIO.setBlockXMLData(frame.evaluateJavaScript("Apps.getBlockData();"))

            filterClassText = self.parseToClass(frame.evaluateJavaScript("Apps.getCodeFromWorkspace();"))
            filterIO.setFilterCode(filterClassText)

            filterIO.setBackgroundImg(self.fgbg)

            filterIO.save(filePath)

        self.blocklyEvaluationTimer.start()

    def inputGraphicsViewResized(self, event=None):
        self.inputGraphicsView.fitInView(QtCore.QRectF(self.inputPixmap.rect()), QtCore.Qt.KeepAspectRatio)

    def outputGraphicsViewResized(self, event=None):
        if self.outputPixmap is None:
            self.outputGraphicsView.fitInView(self.outputScene.sceneRect(), QtCore.Qt.KeepAspectRatio)
        else:
            self.outputGraphicsView.fitInView(QtCore.QRectF(self.outputPixmap.rect()), QtCore.Qt.KeepAspectRatio)

    def parseToClass(self, text):
        additionalText = """#self.fgbg = None
#self.resize_flag = {resize_flag}
#if self.resize_flag:
#    im_input = cv2.pyrDown(im_input)
if self.resize_flag:
    {input} = cv2.pyrDown({input})
if self.fgbg is not None:
    {input} = cv2.absdiff({input}, self.fgbg)
""".format(resize_flag=self.actionResize.isChecked(), input="{input}")
        text = additionalText + text

        lines = text.split("\n")
        classMemberPattern = r"^#"

        classMembers = []
        filterOperations = []

        for line in lines:
            if re.match(classMemberPattern, line):
                classMembers.append(line.lstrip("#"))
            else:
                filterOperations.append(line)

        generator = ClassTextGenerator('filterOperation')
        generator.functions['__init__']['lines'] = classMembers
        generator.functions['__init__']['args'] = ['im_input']

        filterOperations.append('return {output}')
        generator.addFunction('filterFunc', filterOperations, args=['im_input'], returnVal=True)

        return generator.generate().format(input="im_input", output="im_output")

    def reflectSelectedBlockStateIntoUI(self):
        webFrame = self.blocklyWebView.page().mainFrame()

        data = webFrame.evaluateJavaScript("Apps.getBlockTypeFromSelectedBlock();")
        if data is None:
            self.resetSceneAction(self.selectedBlockID)
            self.selectedBlockID = None
            return

        blockType = data['type']
        blockID = data['id']
        blockAttributes = data['attributes']
        if self.selectedBlockID != blockID:
            self.resetSceneAction(self.selectedBlockID)
            self.selectedBlockID = blockID

        if 'regionSelector' in blockAttributes:
            parameters = webFrame.evaluateJavaScript("Apps.getValueFromSelectedBlock();")

            graphicsItem = self.getGrphicsItemFromInputScene(blockID)

            if graphicsItem is not None:
                if graphicsItem.isVisible() is False:
                    graphicsItem.show()
            else:
                height, width, dim = self.cv_img.shape
                array = [[x[0]*width, x[1]*height] for x in eval(parameters['array'])]

                if blockType == "rectRegionSelector":
                    graphicsItem = ResizableRect()
                elif blockType == "ellipseRegionSelector":
                    graphicsItem = ResizableEllipse()
                elif blockType == "polyRegionSelector":
                    graphicsItem = MovablePolygon()
                self.inputScene.addItem(graphicsItem)
                graphicsItem.setPoints(array)

                graphicsItem.setObjectName(blockID)
                graphicsItem.geometryChange.connect(self.setArrayParameterToBlock)

            self.updateInputGraphicsView()

        elif 'colorSelector' in blockAttributes:
            self.inputPixmapItem.mousePressEvent = self.inputPixmapItemClicked
        else:
            self.inputPixmapItem.mousePressEvent = self.getPixmapItemClickedPos

    def resetSceneAction(self, blockID):
        graphicsItem = self.getGrphicsItemFromInputScene(blockID)
        if graphicsItem is not None:
            graphicsItem.hide()
        self.inputPixmapItem.mousePressEvent = QGraphicsPixmapItem(self.inputPixmapItem).mousePressEvent

    def getGrphicsItemFromInputScene(self, blockID):
        try:
            int(blockID)
        except:
            return None

        for item in self.inputScene.items():
            # QGraphicsObjectをSceneから取り出そうとすると,
            # 親クラスであるQGraphicsItem(QPixmapGraphicsItem)にダウンキャスト
            # されて返ってくるためtryが必要.
            try:
                if blockID == item.objectName():
                    return item
            except:
                pass
        return None

    def evaluateSelectedBlock(self, update=True):
        self.im_output = None

        frame = self.blocklyWebView.page().mainFrame()

        text = frame.evaluateJavaScript("Apps.getCodeFromSelectedBlock();")
        self.reflectSelectedBlockStateIntoUI()
        if text == "" or text is None:
            text = frame.evaluateJavaScript("Apps.getCodeFromWorkspace();")

        if text is None:
            return False

        xmlText = frame.evaluateJavaScript("Apps.getBlockData();")

        text = self.parseToClass(text)

        logger.debug("Generated Code: {0}".format(text))

        textHash = hashlib.md5(text.encode())
        if self.filterClassHash != textHash:
            self.filterClassHash = textHash
            try:
                exec(text, globals())
                self.filter = filterOperation(self.cv_img)
                self.filter.fgbg = self.fgbg
            except Exception as e:
                logger.debug("Block Evaluation Error: {0}".format(e))
                return False

        try:
            self.im_output = self.filter.filterFunc(self.cv_img)
        except Exception as e:
            logger.debug("Filter execution Error: {0}".format(e))
            return False

        if update:
            self.outputScene.clear()

            try:
                qimg = misc.cvMatToQImage(self.im_output)
                self.outputPixmap = QPixmap.fromImage(qimg)
            except:
                pass

            rect = QtCore.QRectF(self.outputPixmap.rect())
            self.outputScene.setSceneRect(rect)

            self.outputScene.addPixmap(self.outputPixmap)

            self.outputGraphicsView.viewport().update()
            self.outputGraphicsViewResized()

        return True

    def saveVideoFile(self, activated=False):
        self.blocklyEvaluationTimer.stop()

        if self.evaluateSelectedBlock(False):
            if self.filePath is not None:
                candidateFilePath = os.path.splitext(self.filePath)[0] + '_processed.avi'
            else:
                candidateFilePath = userDir + '_processed.avi'
            filePath, _ = QFileDialog.getSaveFileName(None, 'Save Video', candidateFilePath, "AVI files (*.avi)")

            if len(filePath) is not 0:
                logger.debug("Saving Video: {0}".format(filePath))

                self.videoPlaybackWidget.stop()

                fourcc = cv2.VideoWriter_fourcc(*'X264')
                out = cv2.VideoWriter(filePath, fourcc, self.videoPlaybackWidget.getFPS(), self.im_output.shape[1::-1])

                numFrames = self.videoPlaybackWidget.getMaxFramePos()+1
                progress = QProgressDialog("Running...\nOpenH264 Video Codec provided by Cisco Systems, Inc.", "Abort", 0, numFrames, self)
                progress.setWindowModality(Qt.WindowModal)

                currentFrameNo = self.videoPlaybackWidget.getFramePos()
                for i in range(numFrames):
                    progress.setValue(i)
                    if progress.wasCanceled():
                        break

                    ret, input_frame = self.videoPlaybackWidget.readFrame(i)
                    output_frame = self.filter.filterFunc(input_frame)
                    if len(output_frame.shape)==2:
                        output_frame = cv2.cvtColor(output_frame, cv2.COLOR_GRAY2BGR)
                    out.write(output_frame)

                out.release()

                self.videoPlaybackWidget.moveToFrame(currentFrameNo)
                progress.setValue(numFrames)

        self.blocklyEvaluationTimer.start()
Ejemplo n.º 39
0
class InitialPoseDialog(QDialog, Ui_PoseDialog):
    data_manager = None
    image = None
    y_line = 0
    y_top_line = 0
    y_lower_line = 0
    landmark_size = 2
    lines = None
    middle_idx = 0
    pose_model = None

    def __init__(self, data_manager):
        super(InitialPoseDialog, self).__init__()
        self.setupUi(self)
        self.setAttribute(Qt.WA_DeleteOnClose)

        assert isinstance(data_manager, DataManager)
        self.data_manager = data_manager
        self.pose_model = InitialPoseModel(data_manager)

        self.scene = QGraphicsScene()
        self.graphicsView.setScene(self.scene)

        self.image = Filter.crop_image(self.data_manager.radiographs[0].image)

        self.findButton.clicked.connect(self.find_jaw_divider)
        self.openButton.clicked.connect(self._open_radiograph)

        self._redraw()

    def find_jaw_divider(self):
        self.y_top_line, self.y_lower_line = self.pose_model._find_jaw_separation_line(self.pose_model._crop_image_sides(self.image))

        upper_jaw_image = self.pose_model.crop_upper_jaw(self.image, self.y_top_line)
        lower_jaw_image = self.pose_model.crop_lower_jaw(self.image, self.y_lower_line)

        # Filter the image
        upper_jaw_image = Filter.process_image(upper_jaw_image, median_kernel=5, bilateral_kernel=17, bilateral_color=6)
        lower_jaw_image = Filter.process_image(lower_jaw_image, median_kernel=5, bilateral_kernel=17, bilateral_color=6)

        upper_jaw_image = self.pose_model._convert_to_binary_image(upper_jaw_image)
        lower_jaw_image = self.pose_model._convert_to_binary_image(lower_jaw_image)

        upper_lines = self.pose_model._find_hough_lines(upper_jaw_image, threshold=15)
        lower_lines = self.pose_model._find_hough_lines(lower_jaw_image, threshold=15)

        # Filter out lines
        upper_lines = self.pose_model._filter_lines(upper_lines, upper_jaw_image.shape, line_offset=6, max_line_gap=90)
        lower_lines = self.pose_model._filter_lines(lower_lines, lower_jaw_image.shape, line_offset=2, max_line_gap=60)

        self.image = lower_jaw_image
        self.lines = lower_lines
        self._redraw()

    def _open_radiograph(self):
        file_dialog = QFileDialog(self)
        file_dialog.setDirectory("./data/Radiographs")
        file_dialog.setFileMode(QFileDialog.ExistingFile)
        file_dialog.setNameFilter("Radiograph (*.tif)")
        if file_dialog.exec_() and len(file_dialog.selectedFiles()) == 1:
            radiograph = Radiograph()
            radiograph.path_to_img = file_dialog.selectedFiles()[0]
            #self.image = radiograph.image
            #crop_translation = -Filter.get_cropping_region(radiograph.image).left_top
            self.image = Filter.crop_image(radiograph.image)
            self.lines = None
            self._redraw()

    def _redraw(self, normalize=False):
        self.scene.clear()

        img = self.image.copy()

        if normalize:
            img = (img / img.max()) * 255

        # Draw image
        qimg = toQImage(img.astype(np.uint8))
        self.scene.addPixmap(QPixmap.fromImage(qimg))

        # Add jaws divider
        self.scene.addLine(QLineF(0, self.y_line, self.image.shape[1], self.y_line), pen=QPen(QColor.fromRgb(255, 0, 0)))
        self.scene.addLine(QLineF(0, self.y_top_line, self.image.shape[1], self.y_top_line), pen=QPen(QColor.fromRgb(255, 0, 0)))
        self.scene.addLine(QLineF(0, self.y_lower_line, self.image.shape[1], self.y_lower_line), pen=QPen(QColor.fromRgb(255, 0, 0)))


        # Add image center
        self.scene.addEllipse(self.image.shape[0]/2 - self.landmark_size, self.image.shape[1]/2 - self.landmark_size,
                             self.landmark_size * 2, self.landmark_size * 2,
                             pen=QPen(QColor.fromRgb(255, 0, 0)), brush=QBrush(QColor.fromRgb(255, 0, 0)))

        # Draw Hough lines
        if self.lines is not None:
            #for x1,y1,x2,y2 in self.lines[0]:
            for i, line_param in enumerate(self.lines):
                    rho,theta = line_param
                    a = np.cos(theta)
                    b = np.sin(theta)
                    x0 = a*rho
                    y0 = b*rho
                    x1 = int(x0 + 200*(-b))
                    y1 = int(y0 + 200*(a))
                    x2 = int(x0 - 200*(-b))
                    y2 = int(y0 - 200*(a))
                    self.scene.addLine(QLineF(x1, y1, x2, y2), pen=QPen(QColor.fromRgb(0, 255, 0)))
Ejemplo n.º 40
0
class qfi_ADI (QGraphicsView):

    viewUpdate = pyqtSignal()

    def __init__(self,winParent):
        QGraphicsView.__init__(self)

        self.winParent=winParent

        self.viewUpdate.connect(self.update)

        
        self.m_roll = 0
        self.m_pitch = 0

        self.m_faceDeltaX_new = 0
        self.m_faceDeltaX_old = 0
        self.m_faceDeltaY_new = 0
        self.m_faceDeltaY_old = 0

        self.m_originalHeight = 240
        self.m_originalWidth = 240

        self.m_originalPixPerDeg = 1.7

        self.m_originalAdiCtr = QPointF(120,120)

        self.m_backZ = -30
        self.m_faceZ = -20
        self.m_ringZ = -10
        self.m_caseZ = 10

        self.setStyleSheet("background: transparent; border: none");
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.setInteractive(False)
        self.setEnabled(False)


        self.m_scene = QGraphicsScene(self)
        
        self.setScene(self.m_scene)

        self.init()

        

    def init (self):
        self.m_scaleX = self.width() / self.m_originalWidth
        self.m_scaleY = self.height() / self.m_originalHeight


        self.m_itemBack = QGraphicsSvgItem(":/qfi/images/adi/adi_back.svg")
        self.m_itemBack.setCacheMode (QGraphicsItem.NoCache)
        self.m_itemBack.setZValue( self.m_backZ )
        self.m_itemBack.setTransform( QTransform.fromScale( self.m_scaleX, self.m_scaleY ), True )
        self.m_itemBack.setTransformOriginPoint( self.m_originalAdiCtr )
        self.m_scene.addItem (self.m_itemBack)

        self.m_itemFace = QGraphicsSvgItem(":/qfi/images/adi/adi_face.svg")
        self.m_itemFace.setCacheMode (QGraphicsItem.NoCache)
        self.m_itemFace.setZValue( self.m_faceZ )
        self.m_itemFace.setTransform( QTransform.fromScale( self.m_scaleX, self.m_scaleY ), True )
        self.m_itemFace.setTransformOriginPoint( self.m_originalAdiCtr )
        self.m_scene.addItem (self.m_itemFace)

        self.m_itemRing = QGraphicsSvgItem(":/qfi/images/adi/adi_ring.svg")
        self.m_itemRing.setCacheMode (QGraphicsItem.NoCache)
        self.m_itemRing.setZValue( self.m_ringZ )
        self.m_itemRing.setTransform( QTransform.fromScale( self.m_scaleX, self.m_scaleY ), True )
        self.m_itemRing.setTransformOriginPoint( self.m_originalAdiCtr )
        self.m_scene.addItem (self.m_itemRing)


        self.m_itemCase = QGraphicsSvgItem(":/qfi/images/alt/alt_case.svg")
        self.m_itemCase.setCacheMode (QGraphicsItem.NoCache)
        self.m_itemCase.setZValue( self.m_caseZ )
        self.m_itemCase.setTransform( QTransform.fromScale( self.m_scaleX, self.m_scaleY ), True )
        self.m_itemCase.setTransformOriginPoint( self.m_originalAdiCtr )
        self.m_scene.addItem (self.m_itemCase)

        self.centerOn (self.width()/2, self.height()/2)

        self.updateView()

    def reinit(self):
        if (self.m_scene):
            self.m_scene.clear()
            self.init()


    def update(self):
        self.updateView()
        self.m_faceDeltaX_old  = self.m_faceDeltaX_new
        self.m_faceDeltaY_old  = self.m_faceDeltaY_new


    def setRoll (self, roll):
        self.m_roll = roll

        if (self.m_roll < -180):
            self.m_roll = -180
        if (self.m_roll > 180):
            self.m_roll = 180


    def setPitch (self, pitch):
        self.m_pitch = pitch
        if (self.m_pitch < -25):
            self.m_pitch = -25
        if (self.m_pitch > 25):
            self.m_pitch = 25

    def resizeEvent (self, event):
        QGraphicsView.resizeEvent (self,event)
        self.reinit()

    def reset (self):
        self.m_itemBack = None
        self.m_itemFace = None
        self.m_itemRing = None
        self.m_itemCase   = None

        self.m_roll =  0.0
        self.m_pitch = 0.0


    def updateView(self):

        self.m_scaleX = self.width() / self.m_originalWidth
        self.m_scaleY = self.height() / self.m_originalHeight
        
        self.m_itemBack.setRotation(- self.m_roll)
        self.m_itemRing.setRotation(- self.m_roll)
        self.m_itemFace.setRotation(- self.m_roll)

        roll_rad = math.pi * self.m_roll / 180.0
        delta  = self.m_originalPixPerDeg * self.m_pitch

        self.m_faceDeltaX_new = self.m_scaleX * delta * math.sin( roll_rad )
        self.m_faceDeltaY_new = self.m_scaleY * delta * math.cos( roll_rad )

        self.m_itemFace.moveBy( self.m_faceDeltaX_new - self.m_faceDeltaX_old, self.m_faceDeltaY_new - self.m_faceDeltaY_old )


        self.m_scene.update()
Ejemplo n.º 41
0
class MainWindow(QMainWindow):
    def __init__(self, parent: QWidget=None) -> None:
        super(MainWindow, self).__init__(parent)
        uic.loadUi(os.path.join(getResourcesPath(), 'ui', 'mainwindow.ui'),
                   self)
        self.actionExit.triggered.connect(QApplication.quit)
        self.actionLoad_G_Code.triggered.connect(self.askGCodeFile)
        self.actionPrint.triggered.connect(self.actionPrintSlot)
        self.actionClear.triggered.connect(self.actionClearSlot)
        self.actionZoomIn.triggered.connect(self.zoomIn)
        self.actionZoomOut.triggered.connect(self.zoomOut)
        self.actionResetZoom.triggered.connect(self.resetZoom)
        self.actionSetPenWidth.triggered.connect(self.askPenWidth)
        self.actionShowMovement.toggled.connect(self.actionShowMovementSlot)
        self.checkBoxActionShowMovement = QCheckBox(
            self.actionShowMovement.text(), self.toolBar)
        self.checkBoxActionShowMovement.setChecked(True)
        # noinspection PyUnresolvedReferences
        self.checkBoxActionShowMovement.toggled.connect(
            self.actionShowMovementSlot)
        self.toolBar.insertWidget(self.actionSetMoveLineColor,
                                  self.checkBoxActionShowMovement)
        self.actionSetMoveLineColor.triggered.connect(
            self.actionSetMoveLineColorSlot)

        self.zoomFactor = 1
        self._precision = 1
        self._moveLineColor = Qt.green
        self.material = None
        self.scene = QGraphicsScene()
        self.graphicsView.setScene(self.scene)
        self.graphicsView.scale(1, -1)
        self.graphicsView.setBackgroundBrush(QBrush(Qt.lightGray))
        self.clearScene()
        self.updateStatusBar()

    @property
    def moveLineColor(self) -> QColor:
        return self._moveLineColor

    @moveLineColor.setter
    def moveLineColor(self, new_color: QColor) -> None:
        self._moveLineColor = new_color
        for item in self.scene.items():
            if isinstance(item, QGraphicsMovementLineItem):
                item.color = self.moveLineColor

    @property
    def precision(self) -> number:
        return self._precision

    @precision.setter
    def precision(self, new_precision: number) -> None:
        self._precision = new_precision
        for item in self.scene.items():
            if isinstance(item, PenWidthSettable) and\
                    isinstance(item, QGraphicsItem):
                item.penWidth = self.precision
        self.updateStatusBar()

    def actionPrintSlot(self) -> None:
        printer = QPrinter()
        printer.setPageOrientation(QPageLayout.Landscape)
        if QPrintDialog(printer).exec_():
            painter = QPainter(printer)
            painter.setRenderHint(QPainter.Antialiasing)
            view = QGraphicsView()
            view.setScene(self.scene)
            view.setSceneRect(QRectF(0, 0, 290, 200))
            view.fitInView(QRectF(0, 0, 290, 200), Qt.KeepAspectRatio)
            view.scale(1, -1)
            view.render(painter)
            del painter  # necessary, thanks Qt

    def updateStatusBar(self) -> None:
        # noinspection PyUnresolvedReferences
        self.statusBar.showMessage('Current pen width: %.3f' % self._precision)

    def actionShowMovementSlot(self, toggle: bool) -> None:
        self.checkBoxActionShowMovement.setChecked(toggle)
        self.actionShowMovement.setChecked(toggle)
        for item in self.scene.items():
            if isinstance(item, QGraphicsMovementLineItem):
                item.setVisible(toggle)

    def askPenWidth(self) -> None:
        # noinspection PyCallByClass, PyTypeChecker
        res = QInputDialog.getDouble(self, 'Change pen width',
                                     'Enter new pen width:',
                                     self.precision, -10000, 10000, 3)
        if res[1]:
            self.precision = res[0]

    def actionClearSlot(self) -> None:
        if self.askClearScene():
            self.clearScene()

    def actionSetMoveLineColorSlot(self) -> None:
        # Inspector doesn't understand Qt's static methods
        # noinspection PyCallByClass,PyTypeChecker
        color = QColorDialog.getColor(self.moveLineColor, self,
                                      'Select new move line color')
        if QColor.isValid(color):
            self.moveLineColor = color

    def askClearScene(self) -> bool:
        msgbox = QMessageBox(self)
        msgbox.setText('This will clear the area.')
        msgbox.setInformativeText('Are you sure you want to continue?')
        msgbox.setStandardButtons(
            QMessageBox.Cancel | QMessageBox.Ok)
        msgbox.setDefaultButton(QMessageBox.Cancel)
        ret = msgbox.exec()
        if ret == QMessageBox.Ok:
            return True
        return False

    def clearScene(self) -> None:
        self.scene.clear()
        self.precision = 1
        self.updateStatusBar()
        self.material = self.scene.addRect(QRectF(0, 0, 290, 200))
        self.material.setPen(QPen(Qt.white))
        self.material.setBrush(QBrush(Qt.white))

    def askGCodeFile(self) -> None:
        # noinspection PyCallByClass, PyTypeChecker
        filetuple = QFileDialog.getOpenFileName(self,
                                                'Select G Code file',
                                                getResourcesPath(),
                                                'G Code files (*.gcode);;'
                                                'Text files (*.txt);;'
                                                'All Files (*.*)')
        if filetuple:
            if os.path.isfile(filetuple[0]):
                self.loadGCode(filetuple[0])

    def zoomIn(self) -> None:
        self.graphicsView.scale(1.15, 1.15)
        self.zoomFactor *= 1.15

    def zoomOut(self) -> None:
        self.graphicsView.scale(1.0 / 1.15, 1.0 / 1.15)
        self.zoomFactor /= 1.15

    def resetZoom(self) -> None:
        self.graphicsView.scale(1.0 / self.zoomFactor, 1.0 / self.zoomFactor)
        self.zoomFactor = 1

    def loadGCode(self, filename: str) -> None:
        rawSteps = []
        # a step is tuple of str (command) and dict of arg -> value
        # eg ('G1', {'X': 0})
        with open(filename) as f:
            for index, line in enumerate(f):
                line = line.split(';', 1)[0]
                if not line:
                    continue
                splitted = line.strip().split(' ')
                cmd = splitted[0]
                packedArgs = splitted[1:]
                args = {}
                for arg in packedArgs:
                    args[arg[0]] = arg[1:]
                rawSteps.append((cmd, args))
        for rawStep in rawSteps:
            cmd = rawStep[0]
            args = rawStep[1]
            if cmd == 'G2' or cmd == 'G3':
                try:
                    args['I']
                except KeyError:
                    args['I'] = 0
                try:
                    args['J']
                except KeyError:
                    args['J'] = 0
        self.execGCode(rawSteps)

    def execGCode(self, codes: List[GCode]) -> None:
        relative_mode = False
        prevX = 0
        prevY = 0
        for code in codes:
            cmd = code[0]
            args = code[1]
            if 'X' in args:
                x = float(args['X']) + (prevX if relative_mode else 0)
            else:
                x = prevX
            if 'Y' in args:
                y = float(args['Y']) + (prevY if relative_mode else 0)
            else:
                y = prevY
            if cmd == 'G0':
                line = QGraphicsMovementLineItem(
                    line=QLineF(prevX, prevY, x, y),
                    color=self._moveLineColor,
                    penWidth=self.precision)
                if not self.checkBoxActionShowMovement.isChecked():
                    line.setVisible(False)
                self.scene.addItem(line)
            elif cmd == 'G1':
                self.scene.addItem(
                    QGraphicsColoredLineItem(
                        line=QLineF(prevX, prevY, x, y),
                        penWidth=self.precision))
            elif cmd == 'G2' or cmd == 'G3':
                offsetX = float(args['I'])
                offsetY = float(args['J'])
                if offsetX == 0 and offsetY == 0:
                    # only R given
                    radius = float(args['R'])
                    dx = x - prevX
                    dy = y - prevY
                    dist = math.sqrt(dx ** 2 + dy ** 2)
                    h = math.sqrt((radius ** 2) - ((dist ** 2) / 4))
                    tmpx = dy * h / dist
                    tmpy = -dx * h / dist
                    ccw = (cmd == 'G3')
                    if (ccw and radius > 0) or ((not ccw) and radius < 0):
                        tmpx = -tmpx
                        tmpy = -tmpy
                    middleX = tmpx + (2 * x - dx) / 2
                    middleY = tmpy + (2 * y - dy) / 2
                else:
                    radius = math.sqrt(offsetX ** 2 + offsetY ** 2)
                    middleX = prevX + offsetX
                    middleY = prevY + offsetY
                rectBottomLeftX = middleX - radius
                rectBottomLeftY = middleY - radius
                rectLength = 2 * radius
                alpha = math.degrees(math.atan2(prevY - middleY,
                                                prevX - middleX))
                beta = math.degrees(math.atan2(y - middleY, x - middleX))
                if cmd == 'G2':
                    if beta > alpha:
                        if beta >= 180:
                            beta -= 360
                        else:
                            alpha += 360
                elif cmd == 'G3':
                    if beta < alpha:
                        if alpha > 180:
                            alpha -= 360
                        else:
                            beta += 360
                delta = alpha - beta
                if delta == 0:
                    delta = 360
                ellipse = QGraphicsArcItem(rectBottomLeftX, rectBottomLeftY,
                                           rectLength, rectLength,
                                           penWidth=self.precision)
                ellipse.setStartAngle(-alpha)
                ellipse.setSpanAngle(delta)
                self.scene.addItem(ellipse)
            elif cmd == 'G91':
                relative_mode = True
            elif cmd == 'G90':
                relative_mode = False
            elif cmd == 'G28':
                # reference drive + general init
                relative_mode = False
                x = -0.9
                y = 242.3
            prevX = x
            prevY = y
Ejemplo n.º 42
0
Archivo: gui.py Proyecto: B-Rich/DaAoA
class ui_simulator(object):
    def init_ui(self, simulator):
        simulator.setObjectName("Simulator")
        simulator.setFixedSize(748, 519)
        self.frame = QFrame(simulator)
        self.frame.setGeometry(QtCore.QRect(50, 340, 651, 151))
        self.frame.setFrameShape(QFrame.StyledPanel)
        self.frame.setFrameShadow(QFrame.Raised)
        self.frame.setObjectName("frame")
        self.group = QGroupBox(self.frame)
        self.group.setGeometry(QtCore.QRect(10, 10, 171, 131))
        self.group.setObjectName("group")
        self.rb_1 = QRadioButton(self.group)
        self.rb_1.setGeometry(QtCore.QRect(10, 30, 82, 17))
        self.rb_1.setObjectName("rb")
        self.rb_1.toggled.connect(lambda: self.show_nodes(self.rb_1))
        self.rb_2 = QRadioButton(self.group)
        self.rb_2.setGeometry(QtCore.QRect(10, 50, 82, 17))
        self.rb_2.setObjectName("rb_2")
        self.rb_2.toggled.connect(lambda: self.show_nodes(self.rb_2))
        self.rb_3 = QRadioButton(self.group)
        self.rb_3.setGeometry(QtCore.QRect(10, 70, 82, 17))
        self.rb_3.setObjectName("rb_3")
        self.rb_3.toggled.connect(lambda: self.show_nodes(self.rb_3))
        self.rb_4 = QRadioButton(self.group)
        self.rb_4.setGeometry(QtCore.QRect(10, 90, 82, 17))
        self.rb_4.setObjectName("rb_4")
        self.rb_4.toggled.connect(lambda: self.show_nodes(self.rb_4))
        self.button = QPushButton(self.frame)
        self.button.setGeometry(QtCore.QRect(210, 110, 75, 23))
        self.button.setObjectName("button")
        self.button.clicked.connect(self.runner)
        # self.button.click(self, PyQt5.QtWidgets.PYQT_SIGNAL("clicked()"), self.runner)
        # QObject.connect(self.button, PYQT_SIGNAL("clicked()"), b2_clicked)
        self.button.setToolTip('Run simulation using selected number of nodes')
        self.frame_2 = QFrame(simulator)
        self.frame_2.setGeometry(QtCore.QRect(50, 39, 641, 291))
        self.frame_2.setFrameShape(QFrame.StyledPanel)
        self.frame_2.setFrameShadow(QFrame.Raised)
        self.frame_2.setObjectName("frame_2")
        self.graphics = QGraphicsView(self.frame_2)
        self.graphics.setGeometry(QtCore.QRect(0, 0, 641, 291))
        self.graphics.setObjectName("graphics")
        self.scene = QGraphicsScene(0, 0, 600, 250)
        self.label = QLabel(simulator)
        self.label.setGeometry(QtCore.QRect(50, 10, 61, 20))
        self.label.setObjectName("label")
        self.console = QLabel(self.frame)
        self.console.setGeometry(QtCore.QRect(300, 10, 61, 20))
        self.console.setObjectName("console_label")
        self.textarea = QTextEdit(simulator)
        self.textarea.setStyleSheet("color: white; background-color: black;")
        self.textarea.setReadOnly(True)
        self.textarea.setGeometry(QtCore.QRect(410, 350, 300, 131))
        self.textarea.setObjectName("textarea")
        self.retranslate_ui(simulator)
        QtCore.QMetaObject.connectSlotsByName(simulator)

    def retranslate_ui(self, simulator):
        simulator.setWindowTitle(_translate("Simulator", "Simulator", None))
        self.group.setTitle(_translate("Simulator", "Nodes:", None))
        self.console.setText("Console: ")
        self.rb_1.setText(_translate("Simulator", "5", None))
        self.rb_2.setText(_translate("Simulator", "10", None))
        self.rb_3.setText(_translate("Simulator", "15", None))
        self.rb_4.setText(_translate("Simulator", "20", None))
        self.button.setText(_translate("Simulator", "Start", None))
        self.label.setText(_translate("Simulator", "Node Grid:", None))

    @pyqtSlot()
    def runner(self):
        grid = Grid()
        air = sc()
        self.group.setEnabled(False)
        self.textarea.setTextColor(Qt.white)
        node_names = list(string.ascii_uppercase)
        for i in range(len(self.random_x)):
            grid.add_node(node_names[i], self.random_x[i], self.random_y[i])
        # grid.establish_conn()
        grid.establish_conn(True)
        nd = grid.node_dictionary
        # print(nd.keys())
        for n in nd.values():
            # print(str(n.x_pos) + " " +str(n.y_pos))
            self.textarea.append(
                str(n.name) + " Neighbor Table: " +
                str([x.name for x in n.neighbors.keys()]) +
                "\nRouting table: " + str(n.RT) + "\n")
        for item in self.graphics.scene().items():
            i = self.graphics.scene().items().index(item)
            item.setToolTip("Node name: " + str(node_names[i]) + "\n X: " +
                            str(self.random_x[i]) + " Y: " +
                            str(self.random_y[i]))
        for x in range(5):
            for item in self.graphics.scene().items():
                item.setBrush(Qt.green)
            self.textarea.append("Transmission attempt: " + str(x + 1))
            src = nd[random.choice(list(nd.keys()))]
            dst = nd[random.choice(list(nd.keys()))]
            while src is dst:
                dst = nd[random.choice(list(nd.keys()))]
            src.prepare_msg(src, dst, 'Hi')
            self.textarea.append("Sending from " + src.name + " to " +
                                 dst.name)
            while src.buffer:
                src_pos = self.random_x.index(src.x_pos)
                dst_pos = self.random_x.index(dst.x_pos)
                self.graphics.scene().items()[src_pos].setBrush(Qt.blue)
                self.graphics.scene().items()[dst_pos].setBrush(Qt.red)
                self.textarea.append("Current Transmission range (" +
                                     src.name + "): " + str(src.t_range) + "m")
                air.carry(src.send_msg())
                rcv = list(air.transmit_to)
                self.textarea.append("Next hop: " +
                                     str(air.message.target_node))
                air.propagate(self.textarea)
                for node in rcv:
                    if node.buffer:
                        src = node
                QApplication.processEvents()
                time.sleep(0.5)
            self.textarea.append('-------------')
        self.group.setEnabled(True)

    def show_nodes(self, button):
        self.scene.setSceneRect(0, 0, 600, 250)
        self.textarea.setText("")
        self.scene.clear()
        # scene.setSceneRect(0, 0, 600, 250)
        nodes = int(button.text())
        self.random_x = random.sample(range(1, 31), nodes)
        self.random_y = random.sample(range(1, 31), nodes)
        for i in range(len(self.random_x)):
            item = QGraphicsEllipseItem(self.random_x[i] * 8,
                                        self.random_y[i] * 8, 15, 15)
            item.setToolTip("X: " + str(self.random_x[i]) + " Y: " +
                            str(self.random_y[i]))
            item.setBrush(Qt.green)
            self.scene.addItem(item)
        self.graphics.setScene(self.scene)
        self.graphics.update()
Ejemplo n.º 43
0
class MapCanvas(QGraphicsView):

    def __init__(self):
        # UI Init
        super(QGraphicsView, self).__init__()
        self.setAutoFillBackground(True)
        self.setAttribute(Qt.WA_StyledBackground)
        self.setStyleSheet(
            'QGraphicsView { background-color: rgba(0, 0, 0, 255); }'
        )
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setContentsMargins(0, 0, 0, 0)
        self.setTransformationAnchor(self.AnchorViewCenter)
        self.setFocusPolicy(Qt.StrongFocus)
        self.setRenderHint(QPainter.Antialiasing)

        # Class Init
        self._scene = QGraphicsScene(self)
        self.setScene(self._scene)
        self.scale_ratio = 1
        self.map_data = None
        self.map_line_path_items = {}
        self.map_points_items = []
        self.map_points_text_items = []
        self.map_grid_path_item = QGraphicsPathItem()
        self.map_points_player_items = {}
        self.players = {}

        # Application Settings
        self.settings = settings.Settings('parse99')

    def load_map(self, map_name):
        self._scene.clear()
        self.map_data = MapData(map_name)
        self.create_grid_lines()
        self.create_map_lines()
        self.create_map_points()
        self.update_players()
        self.set_scene_padding(self.map_data.map_grid_geometry.width,
                               self.map_data.map_grid_geometry.height)
        self.draw()
        self.centerOn(0, 0)

    def create_grid_lines(self):
        grid_line_width = self.settings.get_value('maps', 'grid_line_width')
        self.map_grid_path_item = QGraphicsPathItem()
        line_path = QPainterPath()
        for map_line in self.map_data.grid_lines:
            line_path.moveTo(map_line.x1, map_line.y1)
            line_path.lineTo(map_line.x2, map_line.y2)
        self.map_grid_path_item = QGraphicsPathItem(line_path)
        color = QColor().fromRgb(255, 255, 255, 25)
        self.map_grid_path_item.setPen(
            QPen(
                color,
                grid_line_width / self.scale_ratio
            )
        )

    def create_map_lines(self):
        map_line_width = self.settings.get_value('maps', 'map_line_width')
        # use color as string for dictionary keys to preserve line colours
        self.map_line_path_items = {}
        line_path = {}
        colors = {}
        for map_line in self.map_data.map_lines:
            key = str(map_line.r) + ',' \
                + str(map_line.g) + ',' \
                + str(map_line.b)
            if key not in line_path.keys():
                line_path[key] = QPainterPath()
                colors[key] = QColor().fromRgb(
                    map_line.r,
                    map_line.g,
                    map_line.b
                )
            line_path[key].moveTo(QPointF(map_line.x1, map_line.y1))
            line_path[key].lineTo(QPointF(map_line.x2, map_line.y2))
        for key in line_path.keys():
            self.map_line_path_items[key] = QGraphicsPathItem(line_path[key])
            self.map_line_path_items[key].setPen(
                QPen(
                    colors[key],
                    map_line_width / self.scale_ratio
                )
            )

    def create_map_points(self):
        self.map_points_text_items = []
        self.map_points_items = []
        for map_point in self.map_data.map_points:
            color = QColor().fromRgb(map_point.r, map_point.g, map_point.b)
            rect = QGraphicsRectItem(
                QRectF(
                    QPointF(map_point.x, map_point.y),
                    QSizeF(5 / self.scale_ratio, 5 / self.scale_ratio)
                )
            )
            rect.setPen(QPen(Qt.black, 1 / self.scale_ratio))
            rect.setBrush(color)
            self.map_points_items.append(rect)
            text = QGraphicsTextItem(map_point.text)
            text.setDefaultTextColor(color)
            text.setPos(map_point.x, map_point.y)
            text.setFont(QFont('Times New Roman', 8 / self.scale_ratio, 2))
            self.map_points_text_items.append(text)

    def draw(self):
        # Draw map grid
        self._scene.addItem(self.map_grid_path_item)

        # Draw map lines
        for key in self.map_line_path_items.keys():
            self._scene.addItem(self.map_line_path_items[key])

        # Draw map points
        for item in self.map_points_items:
            self._scene.addItem(item)

        # Draw map point's text
        for item in self.map_points_text_items:
            self._scene.addItem(item)

    def update_players(self):
        # Convert lists to sets
        player_list_set = set(self.players.keys())

        # Player points and text should be the same so only use one
        player_items_set = set(self.map_points_player_items.keys())

        # calculate size of player circles
        circle_size = max(10, 10 / self.scale_ratio)

        # Draw and/or update all players in players
        for player in player_list_set:
            player_data = self.players[player]
            if player in player_items_set and \
               self.map_points_player_items[player] in self._scene.items():
                # Update
                self.map_points_player_items[player_data.name].setRect(
                    player_data.x - circle_size / 2,
                    player_data.y - circle_size / 2,
                    circle_size,
                    circle_size
                )
            else:
                # Create New Point
                color = QColor().fromRgb(
                    player_data.r,
                    player_data.g,
                    player_data.b
                )
                circle = QGraphicsEllipseItem(
                    player_data.x - circle_size / 2,
                    player_data.y - circle_size / 2,
                    circle_size,
                    circle_size
                )
                circle.setBrush(color)
                self.map_points_player_items[player_data.name] = circle
                self._scene.addItem(
                    self.map_points_player_items[player_data.name]
                )

        # Find/remove players who aren't in players list from the map
        for key in [player for player in player_items_set
                    if player not in player_list_set]:
            self._scene.removeItem(self.map_points_player_items[key])

        # Center map
        self.center()

    def set_scale(self, ratio):
        # Scale scene
        self.setTransform(QTransform())
        self.scale_ratio = ratio
        self.scale(self.scale_ratio, self.scale_ratio)

        # Scale map lines
        map_line_width = self.settings.get_value('maps', 'map_line_width')
        for key in self.map_line_path_items.keys():
            pen = self.map_line_path_items[key].pen()
            pen.setWidth(
                max(
                    map_line_width,
                    map_line_width / self.scale_ratio
                )
            )
            self.map_line_path_items[key].setPen(pen)

        # Scale map grid
        grid_line_width = self.settings.get_value('maps', 'grid_line_width')
        pen = self.map_grid_path_item.pen()
        pen.setWidth(
            max(
                grid_line_width,
                grid_line_width / self.scale_ratio
            )
        )
        self.map_grid_path_item.setPen(pen)

        # Scale map points
        for i, rect in enumerate(self.map_points_items):
            rect.setRect(
                self.map_data.map_points[i].x,
                self.map_data.map_points[i].y,
                max(5, 5 / self.scale_ratio),
                max(5, 5 / self.scale_ratio)
            )

        # Scale map point's text
        for i, text in enumerate(self.map_points_text_items):
            text.setFont(
                QFont(
                    'Times New Roman',
                    max(8, 8 / self.scale_ratio)
                )
            )
            text.setX(
                self.map_data.map_points[i].x + max(5, 5 / self.scale_ratio)
            )

        # Scale player point
        circle_size = max(10, 10 / self.scale_ratio)
        for player in self.map_points_player_items.keys():
            self.map_points_player_items[player].setRect(
                self.players[player].x - circle_size / 2,
                self.players[player].y - circle_size / 2,
                circle_size,
                circle_size
            )

    def set_scene_padding(self, padding_x, padding_y):
        # Make it so that if you are zoomed out, you can still
        # drag the map around (not that smooth)
        rect = self._scene.sceneRect()
        rect.adjust(
            -padding_x * 2, -padding_y * 2, padding_x * 2, padding_y * 2
        )
        self.setSceneRect(rect)

    def draw_loading_screen(self):
        pass

    def fit_to_window(self):
        pass

    def center(self):
        if self.settings.get_value('maps', 'center_on') == 'player':
            # Center on Player for now by default
            # Added try/except because initialization causes resize event
            try:
                if '__you__' in self.players.keys():
                    self.centerOn(
                        self.players['__you__'].x,
                        self.players['__you__'].y
                    )
            except AttributeError as e:
                print("MapCanvas().center():", e)

    def add_player(self, name, time_stamp, location):
        y, x, z = [float(value) for value in location.strip().split(',')]
        y = -y
        x = -x
        if name not in self.players.keys():
            r, g, b = (0, 255, 0)
            flag = '__other__'
            user_level = None
            if name == '__you__':
                r, g, b = (0, 255, 0)
                flag = '__you__'
                user_level = None
            self.players[name] = Player(
                name=name,
                x=x,
                y=y,
                z=z,
                r=r,
                g=g,
                b=b,
                flag=flag,
                user_level=user_level,
                time_stamp=time_stamp
            )
        else:
            self.players[name].x = x
            self.players[name].y = y
            self.players[name].z = z
            self.players[name].time_stamp = time_stamp

    def wheelEvent(self, event):
        # Scale based on scroll wheel direction
        movement = event.angleDelta().y()
        if movement > 0:
            self.set_scale(self.scale_ratio + self.scale_ratio * 0.1)
        else:
            self.set_scale(self.scale_ratio - self.scale_ratio * 0.1)

    def keyPressEvent(self, event):
        # Enable drag mode while control button is being held down
        if event.modifiers() == Qt.ControlModifier:
            self.setDragMode(self.ScrollHandDrag)
        return QGraphicsView.keyPressEvent(self, event)

    def keyReleaseEvent(self, event):
        # Disable drag mode when control button released
        if event.key() == Qt.Key_Control:
            self.setDragMode(self.NoDrag)
        return QGraphicsView.keyPressEvent(self, event)

    def resizeEvent(self, event):
        self.center()
        return QGraphicsView.resizeEvent(self, event)
Ejemplo n.º 44
0
class Traces(QGraphicsView):
    """Main widget that contains the recordings to be plotted.

    Attributes
    ----------
    parent : instance of QMainWindow
        the main window.
    config : instance of ConfigTraces
        settings for this widget

    y_scrollbar_value : int
        position of the vertical scrollbar
    data : instance of ChanTime
        filtered and reref'ed data

    chan : list of str
        list of channels (labels and channel group)
    chan_pos : list of int
        y-position of each channel (based on value at 0)
    chan_scale : list of float
        scaling factor for each channel
    time_pos : list of QPointF
        we need to keep track of the position of time label during creation
    sel_chan : int
        index of self.chan of the first selected channel
    sel_xy : tuple of 2 floats
        x and y position of the first selected point

    scene : instance of QGraphicsScene
        the main scene.
    idx_label : list of instance of QGraphicsSimpleTextItem
        the channel labels on the y-axis
    idx_time : list of instance of QGraphicsSimpleTextItem
        the time labels on the x-axis
    idx_sel : instance of QGraphicsRectItem
        the rectangle showing the selection (both for selection and event)
    idx_info : instance of QGraphicsSimpleTextItem
        the rectangle showing the selection
    idx_markers : list of QGraphicsRectItem
        list of markers in the dataset
    idx_annot : list of QGraphicsRectItem
        list of user-made annotations
    """
    def __init__(self, parent):
        super().__init__()
        self.parent = parent
        self.config = ConfigTraces(self.parent.overview.update_position)

        self.y_scrollbar_value = 0
        self.data = None
        self.chan = []
        self.chan_pos = []  # used later to find out which channel we're using
        self.chan_scale = []
        self.time_pos = []
        self.sel_chan = None
        self.sel_xy = (None, None)

        self.scene = None
        self.idx_label = []
        self.idx_time = []
        self.idx_sel = None
        self.idx_info = None
        self.idx_markers = []
        self.idx_annot = []

        self.create_action()

    def create_action(self):
        """Create actions associated with this widget."""
        actions = {}

        act = QAction(QIcon(ICON['step_prev']), 'Previous Step', self)
        act.setShortcut(QKeySequence.MoveToPreviousChar)
        act.triggered.connect(self.step_prev)
        actions['step_prev'] = act

        act = QAction(QIcon(ICON['step_next']), 'Next Step', self)
        act.setShortcut(QKeySequence.MoveToNextChar)
        act.triggered.connect(self.step_next)
        actions['step_next'] = act

        act = QAction(QIcon(ICON['page_prev']), 'Previous Page', self)
        act.setShortcut(QKeySequence.MoveToPreviousPage)
        act.triggered.connect(self.page_prev)
        actions['page_prev'] = act

        act = QAction(QIcon(ICON['page_next']), 'Next Page', self)
        act.setShortcut(QKeySequence.MoveToNextPage)
        act.triggered.connect(self.page_next)
        actions['page_next'] = act

        act = QAction(QIcon(ICON['zoomprev']), 'Wider Time Window', self)
        act.setShortcut(QKeySequence.ZoomIn)
        act.triggered.connect(self.X_more)
        actions['X_more'] = act

        act = QAction(QIcon(ICON['zoomnext']), 'Narrower Time Window', self)
        act.setShortcut(QKeySequence.ZoomOut)
        act.triggered.connect(self.X_less)
        actions['X_less'] = act

        act = QAction(QIcon(ICON['zoomin']), 'Larger Amplitude', self)
        act.setShortcut(QKeySequence.MoveToPreviousLine)
        act.triggered.connect(self.Y_more)
        actions['Y_less'] = act

        act = QAction(QIcon(ICON['zoomout']), 'Smaller Amplitude', self)
        act.setShortcut(QKeySequence.MoveToNextLine)
        act.triggered.connect(self.Y_less)
        actions['Y_more'] = act

        act = QAction(QIcon(ICON['ydist_more']), 'Larger Y Distance', self)
        act.triggered.connect(self.Y_wider)
        actions['Y_wider'] = act

        act = QAction(QIcon(ICON['ydist_less']), 'Smaller Y Distance', self)
        act.triggered.connect(self.Y_tighter)
        actions['Y_tighter'] = act

        act = QAction(QIcon(ICON['chronometer']), '6 Hours Earlier', self)
        act.triggered.connect(partial(self.add_time, -6 * 60 * 60))
        actions['addtime_-6h'] = act

        act = QAction(QIcon(ICON['chronometer']), '1 Hour Earlier', self)
        act.triggered.connect(partial(self.add_time, -60 * 60))
        actions['addtime_-1h'] = act

        act = QAction(QIcon(ICON['chronometer']), '10 Minutes Earlier', self)
        act.triggered.connect(partial(self.add_time, -10 * 60))
        actions['addtime_-10min'] = act

        act = QAction(QIcon(ICON['chronometer']), '10 Minutes Later', self)
        act.triggered.connect(partial(self.add_time, 10 * 60))
        actions['addtime_10min'] = act

        act = QAction(QIcon(ICON['chronometer']), '1 Hour Later', self)
        act.triggered.connect(partial(self.add_time, 60 * 60))
        actions['addtime_1h'] = act

        act = QAction(QIcon(ICON['chronometer']), '6 Hours Later', self)
        act.triggered.connect(partial(self.add_time, 6 * 60 * 60))
        actions['addtime_6h'] = act

        self.action = actions

    def read_data(self):
        """Read the data to plot."""
        window_start = self.parent.value('window_start')
        window_end = window_start + self.parent.value('window_length')
        dataset = self.parent.info.dataset
        groups = self.parent.channels.groups

        chan_to_read = []
        for one_grp in groups:
            chan_to_read.extend(one_grp['chan_to_plot'] + one_grp['ref_chan'])

        if not chan_to_read:
            return
        data = dataset.read_data(chan=chan_to_read,
                                 begtime=window_start,
                                 endtime=window_end)

        max_s_freq = self.parent.value('max_s_freq')
        if data.s_freq > max_s_freq:
            q = int(data.s_freq / max_s_freq)
            lg.debug('Decimate (no low-pass filter) at ' + str(q))

            data.data[0] = data.data[0][:, slice(None, None, q)]
            data.axis['time'][0] = data.axis['time'][0][slice(None, None, q)]
            data.s_freq = int(data.s_freq / q)

        self.data = _create_data_to_plot(data, self.parent.channels.groups)

    def display(self):
        """Display the recordings."""
        if self.data is None:
            return

        if self.scene is not None:
            self.y_scrollbar_value = self.verticalScrollBar().value()
            self.scene.clear()

        self.create_chan_labels()
        self.create_time_labels()

        window_start = self.parent.value('window_start')
        window_length = self.parent.value('window_length')

        time_height = max([x.boundingRect().height() for x in self.idx_time])
        label_width = window_length * self.parent.value('label_ratio')
        scene_height = (len(self.idx_label) * self.parent.value('y_distance') +
                        time_height)

        self.scene = QGraphicsScene(window_start - label_width,
                                    0,
                                    window_length + label_width,
                                    scene_height)
        self.setScene(self.scene)

        self.idx_markers = []
        self.idx_annot = []

        self.add_chan_labels()
        self.add_time_labels()
        self.add_traces()
        self.display_grid()
        self.display_markers()
        self.display_annotations()

        self.resizeEvent(None)
        self.verticalScrollBar().setValue(self.y_scrollbar_value)
        self.parent.info.display_view()
        self.parent.overview.display_current()

    def create_chan_labels(self):
        """Create the channel labels, but don't plot them yet.

        Notes
        -----
        It's necessary to have the width of the labels, so that we can adjust
        the main scene.
        """
        self.idx_label = []
        for one_grp in self.parent.channels.groups:
            for one_label in one_grp['chan_to_plot']:
                item = QGraphicsSimpleTextItem(one_label)
                item.setBrush(QBrush(QColor(one_grp['color'])))
                item.setFlag(QGraphicsItem.ItemIgnoresTransformations)
                self.idx_label.append(item)

    def create_time_labels(self):
        """Create the time labels, but don't plot them yet.

        Notes
        -----
        It's necessary to have the height of the time labels, so that we can
        adjust the main scene.

        Not very robust, because it uses seconds as integers.
        """
        min_time = int(floor(min(self.data.axis['time'][0])))
        max_time = int(ceil(max(self.data.axis['time'][0])))
        n_time_labels = self.parent.value('n_time_labels')

        self.idx_time = []
        self.time_pos = []
        for one_time in linspace(min_time, max_time, n_time_labels):
            x_label = (self.data.start_time +
                       timedelta(seconds=one_time)).strftime('%H:%M:%S')
            item = QGraphicsSimpleTextItem(x_label)
            item.setFlag(QGraphicsItem.ItemIgnoresTransformations)
            self.idx_time.append(item)
            self.time_pos.append(QPointF(one_time,
                                         len(self.idx_label) *
                                         self.parent.value('y_distance')))

    def add_chan_labels(self):
        """Add channel labels on the left."""
        window_start = self.parent.value('window_start')
        window_length = self.parent.value('window_length')
        label_width = window_length * self.parent.value('label_ratio')

        for row, one_label_item in enumerate(self.idx_label):
            self.scene.addItem(one_label_item)
            one_label_item.setPos(window_start - label_width,
                                  self.parent.value('y_distance') * row +
                                  self.parent.value('y_distance') / 2)

    def add_time_labels(self):
        """Add time labels at the bottom."""
        for text, pos in zip(self.idx_time, self.time_pos):
            self.scene.addItem(text)
            text.setPos(pos)

    def add_traces(self):
        """Add traces based on self.data."""
        y_distance = self.parent.value('y_distance')
        self.chan = []
        self.chan_pos = []
        self.chan_scale = []

        row = 0
        for one_grp in self.parent.channels.groups:
            for one_chan in one_grp['chan_to_plot']:

                # channel name
                chan_name = one_chan + ' (' + one_grp['name'] + ')'

                # trace
                dat = (self.data(trial=0, chan=chan_name) *
                       self.parent.value('y_scale'))
                dat *= -1  # flip data, upside down
                path = self.scene.addPath(Path(self.data.axis['time'][0],
                                               dat))
                path.setPen(QPen(QColor(one_grp['color']), LINE_WIDTH))

                # adjust position
                chan_pos = y_distance * row + y_distance / 2
                path.setPos(0, chan_pos)
                row += 1

                self.chan.append(chan_name)
                self.chan_scale.append(one_grp['scale'])
                self.chan_pos.append(chan_pos)

    def display_grid(self):
        """Display grid on x-axis and y-axis."""
        window_start = self.parent.value('window_start')
        window_length = self.parent.value('window_length')
        window_end = window_start + window_length

        if self.parent.value('grid_x'):
            x_tick = self.parent.value('grid_xtick')
            x_ticks = arange(window_start, window_end + x_tick, x_tick)
            for x in x_ticks:
                x_pos = [x, x]
                y_pos = [0,
                         self.parent.value('y_distance') * len(self.idx_label)]
                path = self.scene.addPath(Path(x_pos, y_pos))
                path.setPen(QPen(QColor(LINE_COLOR), LINE_WIDTH,
                                 Qt.DotLine))

        if self.parent.value('grid_y'):
            for one_label_item in self.idx_label:
                x_pos = [window_start, window_end]
                y_pos = [one_label_item.y(), one_label_item.y()]
                path = self.scene.addPath(Path(x_pos, y_pos))
                path.setPen(QPen(QColor(LINE_COLOR), LINE_WIDTH, Qt.DotLine))

    def display_markers(self):
        """Add markers on top of first plot."""
        for item in self.idx_markers:
            self.scene.removeItem(item)
        self.idx_markers = []

        window_start = self.parent.value('window_start')
        window_length = self.parent.value('window_length')
        window_end = window_start + window_length
        y_distance = self.parent.value('y_distance')

        markers = []
        if self.parent.info.markers is not None:
            if self.parent.value('marker_show'):
                markers = self.parent.info.markers

        for mrk in markers:
            if window_start <= mrk['end'] and window_end >= mrk['start']:

                mrk_start = max((mrk['start'], window_start))
                mrk_end = min((mrk['end'], window_end))
                color = QColor(self.parent.value('marker_color'))

                item = QGraphicsRectItem(mrk_start, 0,
                                         mrk_end - mrk_start,
                                         len(self.idx_label) * y_distance)
                item.setPen(color)
                item.setBrush(color)
                item.setZValue(-9)
                self.scene.addItem(item)

                item = TextItem_with_BG(color.darker(200))
                item.setText(mrk['name'])
                item.setPos(mrk['start'],
                            len(self.idx_label) *
                            self.parent.value('y_distance'))
                item.setFlag(QGraphicsItem.ItemIgnoresTransformations)
                item.setRotation(-90)
                self.scene.addItem(item)
                self.idx_markers.append(item)

    def display_annotations(self):
        """Mark all the bookmarks/events, on top of first plot."""
        for item in self.idx_annot:
            self.scene.removeItem(item)
        self.idx_annot = []

        window_start = self.parent.value('window_start')
        window_length = self.parent.value('window_length')
        window_end = window_start + window_length
        y_distance = self.parent.value('y_distance')
        raw_chan_name = list(map(take_raw_name, self.chan))

        bookmarks = []
        events = []

        if self.parent.notes.annot is not None:
            if self.parent.value('annot_show'):
                bookmarks = self.parent.notes.annot.get_bookmarks()
                events = self.parent.notes.get_selected_events((window_start,
                                                                window_end))
        annotations = bookmarks + events

        for annot in annotations:

            if window_start <= annot['end'] and window_end >= annot['start']:

                mrk_start = max((annot['start'], window_start))
                mrk_end = min((annot['end'], window_end))
                if annot in bookmarks:
                    color = QColor(self.parent.value('annot_bookmark_color'))
                if annot in events:
                    color = convert_name_to_color(annot['name'])

                if annot['chan'] == ['']:
                    h_annot = len(self.idx_label) * y_distance
                    y_annot = (0, )

                    item = TextItem_with_BG(color.darker(200))
                    item.setText(annot['name'])
                    item.setPos(annot['start'],
                                len(self.idx_label) * y_distance)
                    item.setFlag(QGraphicsItem.ItemIgnoresTransformations)
                    item.setRotation(-90)
                    self.scene.addItem(item)
                    self.idx_annot.append(item)
                    zvalue = -8

                else:
                    h_annot = y_distance
                    # find indices of channels with annotations
                    chan_idx_in_mrk = in1d(raw_chan_name, annot['chan'])
                    y_annot = asarray(self.chan_pos)[chan_idx_in_mrk]
                    y_annot -= y_distance / 2
                    zvalue = -7

                for y in y_annot:
                    item = QGraphicsRectItem(mrk_start, y,
                                             mrk_end - mrk_start, h_annot)
                    item.setPen(color)
                    item.setBrush(color)
                    item.setZValue(zvalue)
                    self.scene.addItem(item)
                    self.idx_annot.append(item)

    def step_prev(self):
        """Go to the previous step."""
        window_start = (self.parent.value('window_start') -
                        self.parent.value('window_length') /
                        self.parent.value('window_step'))
        self.parent.overview.update_position(window_start)

    def step_next(self):
        """Go to the next step."""
        window_start = (self.parent.value('window_start') +
                        self.parent.value('window_length') /
                        self.parent.value('window_step'))
        self.parent.overview.update_position(window_start)

    def page_prev(self):
        """Go to the previous page."""
        window_start = (self.parent.value('window_start') -
                        self.parent.value('window_length'))
        self.parent.overview.update_position(window_start)

    def page_next(self):
        """Go to the next page."""
        window_start = (self.parent.value('window_start') +
                        self.parent.value('window_length'))
        self.parent.overview.update_position(window_start)

    def add_time(self, extra_time):
        """Go to the predefined time forward."""
        window_start = self.parent.value('window_start') + extra_time
        self.parent.overview.update_position(window_start)

    def X_more(self):
        """Zoom in on the x-axis."""
        self.parent.value('window_length',
                          self.parent.value('window_length') * 2)
        self.parent.overview.update_position()

    def X_less(self):
        """Zoom out on the x-axis."""
        self.parent.value('window_length',
                          self.parent.value('window_length') / 2)
        self.parent.overview.update_position()

    def X_length(self, new_window_length):
        """Use presets for length of the window."""
        self.parent.value('window_length', new_window_length)
        self.parent.overview.update_position()

    def Y_more(self):
        """Increase the amplitude."""
        self.parent.value('y_scale', self.parent.value('y_scale') * 2)
        self.parent.traces.display()

    def Y_less(self):
        """Decrease the amplitude."""
        self.parent.value('y_scale', self.parent.value('y_scale') / 2)
        self.parent.traces.display()

    def Y_ampl(self, new_y_scale):
        """Make amplitude on Y axis using predefined values"""
        self.parent.value('y_scale', new_y_scale)
        self.parent.traces.display()

    def Y_wider(self):
        """Increase the distance of the lines."""
        self.parent.value('y_distance', self.parent.value('y_distance') * 1.4)
        self.parent.traces.display()

    def Y_tighter(self):
        """Decrease the distance of the lines."""
        self.parent.value('y_distance', self.parent.value('y_distance') / 1.4)
        self.parent.traces.display()

    def Y_dist(self, new_y_distance):
        """Use preset values for the distance between lines."""
        self.parent.value('y_distance', new_y_distance)
        self.parent.traces.display()

    def mousePressEvent(self, event):
        """Create a marker or start selection

        Parameters
        ----------
        event : instance of QtCore.QEvent
            it contains the position that was clicked.
        """
        if not self.scene:
            return

        xy_scene = self.mapToScene(event.pos())
        chan_idx = argmin(abs(asarray(self.chan_pos) - xy_scene.y()))
        self.sel_chan = chan_idx
        self.sel_xy = (xy_scene.x(), xy_scene.y())

        chk_marker = self.parent.notes.action['new_bookmark'].isChecked()
        chk_event = self.parent.notes.action['new_event'].isChecked()

        if not (chk_marker or chk_event):
            channame = self.chan[self.sel_chan] + ' in selected window'
            self.parent.spectrum.show_channame(channame)

    def mouseMoveEvent(self, event):
        """When normal selection, update power spectrum with current selection.
        Otherwise, show the range of the new marker.
        """
        if not self.scene:
            return

        if self.idx_sel in self.scene.items():
            self.scene.removeItem(self.idx_sel)
            self.idx_sel = None

        chk_marker = self.parent.notes.action['new_bookmark'].isChecked()
        chk_event = self.parent.notes.action['new_event'].isChecked()

        if chk_marker or chk_event:
            xy_scene = self.mapToScene(event.pos())
            y_distance = self.parent.value('y_distance')
            pos = QRectF(self.sel_xy[0],
                         0,
                         xy_scene.x() - self.sel_xy[0],
                         len(self.idx_label) * y_distance)
            item = QGraphicsRectItem(pos.normalized())
            item.setPen(NoPen)

            if chk_marker:
                color = QColor(self.parent.value('annot_bookmark_color'))

            elif chk_event:
                eventtype = self.parent.notes.idx_eventtype.currentText()
                color = convert_name_to_color(eventtype)

            item.setBrush(QBrush(color.lighter(115)))
            item.setZValue(-10)
            self.scene.addItem(item)
            self.idx_sel = item
            return

        xy_scene = self.mapToScene(event.pos())
        pos = QRectF(self.sel_xy[0], self.sel_xy[1],
                     xy_scene.x() - self.sel_xy[0],
                     xy_scene.y() - self.sel_xy[1])
        self.idx_sel = QGraphicsRectItem(pos.normalized())
        self.idx_sel.setPen(QPen(QColor(LINE_COLOR), LINE_WIDTH))
        self.scene.addItem(self.idx_sel)

        if self.idx_info in self.scene.items():
            self.scene.removeItem(self.idx_info)

        duration = '{0:0.2f}s'.format(abs(xy_scene.x() - self.sel_xy[0]))

        # get y-size, based on scaling too
        y = abs(xy_scene.y() - self.sel_xy[1])
        scale = self.parent.value('y_scale') * self.chan_scale[self.sel_chan]
        height = '{0:0.3f}uV'.format(y / scale)

        item = TextItem_with_BG()
        item.setText(duration + ' ' + height)
        item.setPos(self.sel_xy[0], self.sel_xy[1])
        self.scene.addItem(item)
        self.idx_info = item

        trial = 0
        time = self.parent.traces.data.axis['time'][trial]
        beg_win = min((self.sel_xy[0], xy_scene.x()))
        end_win = max((self.sel_xy[0], xy_scene.x()))
        time_of_interest = time[(time >= beg_win) & (time < end_win)]
        if len(time_of_interest) > MINIMUM_N_SAMPLES:
            data = self.parent.traces.data(trial=trial,
                                           chan=self.chan[self.sel_chan],
                                           time=time_of_interest)
            n_data = len(data)
            n_pad = (power(2, ceil(log2(n_data))) - n_data) / 2
            data = pad(data, (int(ceil(n_pad)), int(floor(n_pad))), 'constant')

            self.parent.spectrum.display(data)

    def mouseReleaseEvent(self, event):
        """Create a new event or marker, or show the previous power spectrum
        """
        if not self.scene:
            return

        chk_marker = self.parent.notes.action['new_bookmark'].isChecked()
        chk_event = self.parent.notes.action['new_event'].isChecked()

        if chk_marker or chk_event:

            x_in_scene = self.mapToScene(event.pos()).x()

            # it can happen that selection is empty (f.e. double-click)
            if self.sel_xy[0] is not None:
                # max resolution = sampling frequency
                # in case there is no data
                s_freq = self.parent.info.dataset.header['s_freq']
                at_s_freq = lambda x: round(x * s_freq) / s_freq
                start = at_s_freq(self.sel_xy[0])
                end = at_s_freq(x_in_scene)

                if abs(end - start) < self.parent.value('min_marker_dur'):
                    end = start

                if start <= end:
                    time = (start, end)
                else:
                    time = (end, start)

                if chk_marker:
                    self.parent.notes.add_bookmark(time)

                elif chk_event:
                    eventtype = self.parent.notes.idx_eventtype.currentText()
                    self.parent.notes.add_event(eventtype, time)

        else:  # normal selection

            if self.idx_info in self.scene.items():
                self.scene.removeItem(self.idx_info)
            self.idx_info = None

            # restore spectrum
            self.parent.spectrum.update()
            self.parent.spectrum.display_window()

        # general garbage collection
        self.sel_chan = None
        self.sel_xy = (None, None)

        if self.idx_sel in self.scene.items():
            self.scene.removeItem(self.idx_sel)
            self.idx_sel = None

    def resizeEvent(self, event):
        """Resize scene so that it fits the whole widget.

        Parameters
        ----------
        event : instance of QtCore.QEvent
            not important

        Notes
        -----
        This function overwrites Qt function, therefore the non-standard
        name. Argument also depends on Qt.

        The function is used to change the scale of view, so that the scene
        fits the whole scene. There are two problems that I could not fix: 1)
        how to give the width of the label in absolute width, 2) how to strech
        scene just enough that it doesn't trigger a scrollbar. However, it's
        pretty good as it is now.
        """
        if self.scene is not None:
            ratio = self.width() / (self.scene.width() * 1.1)
            self.resetTransform()
            self.scale(ratio, 1)

    def reset(self):
        self.y_scrollbar_value = 0
        self.data = None
        self.chan = []
        self.chan_pos = []
        self.chan_scale = []
        self.sel_chan = None
        self.sel_xy = (None, None)

        if self.scene is not None:
            self.scene.clear()
        self.scene = None
        self.idx_sel = None
        self.idx_info = None
        self.idx_label = []
        self.idx_time = []
        self.time_pos = []
Ejemplo n.º 45
0
class MainWindow(QMainWindow):
    def __init__(self, parent):
        QMainWindow.__init__(self)

        self.printer = QPrinter()
        self.load_img = self.load_img_fit
        self.reload_img = self.reload_auto
        self.open_new = parent.open_win
        self.exit = parent.closeAllWindows
        self.scene = QGraphicsScene()
        self.img_view = ImageView(self)
        self.img_view.setScene(self.scene)
        self.setCentralWidget(self.img_view)

        self.create_actions()
        self.create_menu()
        self.create_dict()
        self.slides_next = True

        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.showMenu)

        self.read_prefs()
        self.read_list = parent.read_list
        self.write_list = parent.write_list
        self.pics_dir = os.path.expanduser('~/Pictures') or QDir.currentPath()
        self.resize(700, 500)

    def create_actions(self):
        self.open_act = QAction('&Open', self, shortcut='Ctrl+O')
        self.open_act.triggered.connect(self.open)
        self.open_new_act = QAction('Open new window', self, shortcut='Ctrl+Shift+O')
        self.open_new_act.triggered.connect(partial(self.open, True))
        self.reload_act = QAction('&Reload image', self, shortcut='Ctrl+R')
        self.reload_act.triggered.connect(self.reload_img)
        self.print_act = QAction('&Print', self, shortcut='Ctrl+P')
        self.print_act.triggered.connect(self.print_img)
        self.save_act = QAction('&Save image', self, shortcut='Ctrl+S')
        self.save_act.triggered.connect(self.save_img)
        self.close_act = QAction('Close window', self, shortcut='Ctrl+W')
        self.close_act.triggered.connect(self.close)
        self.exit_act = QAction('E&xit', self, shortcut='Ctrl+Q')
        self.exit_act.triggered.connect(self.exit)
        self.fulls_act = QAction('Fullscreen', self, shortcut='F11', checkable=True)
        self.fulls_act.triggered.connect(self.toggle_fs)
        self.ss_act = QAction('Slideshow', self, shortcut='F5', checkable=True)
        self.ss_act.triggered.connect(self.toggle_slideshow)
        self.ss_next_act = QAction('Next / Random image', self, checkable=True)
        self.ss_next_act.triggered.connect(self.set_slide_type)
        self.ss_next_act.setChecked(True)
        self.next_act = QAction('Next image', self, shortcut='Right')
        self.next_act.triggered.connect(self.go_next_img)
        self.prev_act = QAction('Previous image', self, shortcut='Left')
        self.prev_act.triggered.connect(self.go_prev_img)
        self.rotleft_act = QAction('Rotate left', self, shortcut='Ctrl+Left')
        self.rotleft_act.triggered.connect(partial(self.img_rotate, 270))
        self.rotright_act = QAction('Rotate right', self, shortcut='Ctrl+Right')
        self.rotright_act.triggered.connect(partial(self.img_rotate, 90))
        self.fliph_act = QAction('Flip image horizontally', self, shortcut='Ctrl+H')
        self.fliph_act.triggered.connect(partial(self.img_flip, -1, 1))
        self.flipv_act = QAction('Flip image vertically', self, shortcut='Ctrl+V')
        self.flipv_act.triggered.connect(partial(self.img_flip, 1, -1))
        self.resize_act = QAction('Resize image', self, triggered=self.resize_img)
        self.crop_act = QAction('Crop image', self, triggered=self.crop_img)
        self.zin_act = QAction('Zoom &In', self, shortcut='Up')
        self.zin_act.triggered.connect(partial(self.img_view.zoom, 1.1))
        self.zout_act = QAction('Zoom &Out', self, shortcut='Down')
        self.zout_act.triggered.connect(partial(self.img_view.zoom, 1 / 1.1))
        self.fit_win_act = QAction('Best &fit', self, checkable=True, shortcut='F',
                triggered=self.zoom_default)
        self.fit_win_act.setChecked(True)
        self.prefs_act = QAction('Preferences', self, triggered=self.set_prefs)
        self.props_act = QAction('Properties', self, triggered=self.get_props)
        self.help_act = QAction('&Help', self, shortcut='F1', triggered=self.help_page)
        self.about_act = QAction('&About', self, triggered=self.about_cm)
        self.aboutQt_act = QAction('About &Qt', self,
                triggered=qApp.aboutQt)

    def create_menu(self):
        self.popup = QMenu(self)
        main_acts = [self.open_act, self.open_new_act, self.reload_act, self.print_act, self.save_act]
        edit_acts1 = [self.rotleft_act, self.rotright_act, self.fliph_act, self.flipv_act]
        edit_acts2 = [self.resize_act, self.crop_act]
        view_acts = [self.next_act, self.prev_act, self.zin_act, self.zout_act, self.fit_win_act, self.fulls_act, self.ss_act, self.ss_next_act]
        help_acts = [self.help_act, self.about_act, self.aboutQt_act]
        end_acts = [self.prefs_act, self.props_act, self.close_act, self.exit_act]
        for act in main_acts:
            self.popup.addAction(act)
        edit_menu = QMenu(self.popup)
        edit_menu.setTitle('&Edit')
        for act in edit_acts1:
            edit_menu.addAction(act)
        edit_menu.addSeparator()
        for act in edit_acts2:
            edit_menu.addAction(act)
        self.popup.addMenu(edit_menu)
        view_menu = QMenu(self.popup)
        view_menu.setTitle('&View')
        for act in view_acts:
            view_menu.addAction(act)
        self.popup.addMenu(view_menu)
        help_menu = QMenu(self.popup)
        help_menu.setTitle('&Help')
        for act in help_acts:
            help_menu.addAction(act)
        self.popup.addMenu(help_menu)
        for act in end_acts:
            self.popup.addAction(act)

        self.action_list = main_acts + edit_acts1 + edit_acts2 + view_acts + help_acts + end_acts
        for act in self.action_list:
            self.addAction(act)

    def showMenu(self, pos):
        self.popup.popup(self.mapToGlobal(pos))
 
    def create_dict(self):
        """Create a dictionary to handle auto-orientation."""
        self.orient_dict = {None: self.load_img,
                '1': self.load_img,
                '2': partial(self.img_flip, -1, 1),
                '3': partial(self.img_rotate, 180),
                '4': partial(self.img_flip, -1, 1),
                '5': self.img_rotate_fliph,
                '6': partial(self.img_rotate, 90),
                '7': self.img_rotate_flipv,
                '8': partial(self.img_rotate, 270)}

    def read_prefs(self):
        """Parse the preferences from the config file, or set default values."""
        try:
            conf = preferences.Config()
            values = conf.read_config()
            self.auto_orient = values[0]
            self.slide_delay = values[1]
            self.quality = values[2]
        except:
            self.auto_orient = True
            self.slide_delay = 5
            self.quality = 90
        self.reload_img = self.reload_auto if self.auto_orient else self.reload_nonauto

    def set_prefs(self):
        """Write preferences to the config file."""
        dialog = preferences.PrefsDialog(self)
        if dialog.exec_() == QDialog.Accepted:
            self.auto_orient = dialog.auto_orient
            self.slide_delay = dialog.delay_spinb.value()
            self.quality = dialog.qual_spinb.value()
            conf = preferences.Config()
            conf.write_config(self.auto_orient, self.slide_delay, self.quality)
        self.reload_img = self.reload_auto if self.auto_orient else self.reload_nonauto

    def open(self, new_win=False):
        fname = QFileDialog.getOpenFileName(self, 'Open File', self.pics_dir)[0]
        if fname:
            if fname.lower().endswith(self.read_list):
                if new_win:
                    self.open_new(fname)
                else:
                    self.open_img(fname)
            else:
                QMessageBox.information(self, 'Error', 'Cannot load {} images.'.format(fname.rsplit('.', 1)[1]))

    def open_img(self, fname):
        self.fname = fname
        self.reload_img()
        dirname = os.path.dirname(self.fname)
        self.set_img_list(dirname)
        self.img_index = self.filelist.index(self.fname)

    def set_img_list(self, dirname):
        """Create a list of readable images from the current directory."""
        filelist = os.listdir(dirname)
        self.filelist = [os.path.join(dirname, fname) for fname in filelist
                        if fname.lower().endswith(self.read_list)]
        self.filelist.sort()
        self.last_file = len(self.filelist) - 1

    def get_img(self):
        """Get image from fname and create pixmap."""
        image = QImage(self.fname)
        self.pixmap = QPixmap.fromImage(image)
        self.setWindowTitle(self.fname.rsplit('/', 1)[1])

    def reload_auto(self):
        """Load a new image with auto-orientation."""
        self.get_img()
        try:
            orient = GExiv2.Metadata(self.fname)['Exif.Image.Orientation']
            self.orient_dict[orient]()
        except:
            self.load_img()

    def reload_nonauto(self):
        """Load a new image without auto-orientation."""
        self.get_img()
        self.load_img()

    def load_img_fit(self):
        """Load the image to fit the window."""
        self.scene.clear()
        self.scene.addPixmap(self.pixmap)
        self.scene.setSceneRect(0, 0, self.pixmap.width(), self.pixmap.height())
        self.img_view.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio)

    def load_img_1to1(self):
        """Load the image at its original size."""
        self.scene.clear()
        self.img_view.resetTransform()
        self.scene.addPixmap(self.pixmap)
        self.scene.setSceneRect(0, 0, self.pixmap.width(), self.pixmap.height())
        pixitem = QGraphicsPixmapItem(self.pixmap)
        self.img_view.centerOn(pixitem)

    def go_next_img(self):
        self.img_index = self.img_index + 1 if self.img_index < self.last_file else 0
        self.fname = self.filelist[self.img_index]
        self.reload_img()

    def go_prev_img(self):
        self.img_index = self.img_index - 1 if self.img_index else self.last_file
        self.fname = self.filelist[self.img_index]
        self.reload_img()

    def zoom_default(self):
        """Toggle best fit / original size loading."""
        if self.fit_win_act.isChecked():
            self.load_img = self.load_img_fit
            self.create_dict()
            self.load_img()
        else:
            self.load_img = self.load_img_1to1
            self.create_dict()
            self.load_img()

    def img_rotate(self, angle):
        self.pixmap = self.pixmap.transformed(QTransform().rotate(angle))
        self.load_img()

    def img_flip(self, x, y):
        self.pixmap = self.pixmap.transformed(QTransform().scale(x, y))
        self.load_img()

    def img_rotate_fliph(self):
        self.img_rotate(90)
        self.img_flip(-1, 1)

    def img_rotate_flipv(self):
        self.img_rotate(90)
        self.img_flip(1, -1)

    def resize_img(self):
        dialog = editimage.ResizeDialog(self, self.pixmap.width(), self.pixmap.height())
        if dialog.exec_() == QDialog.Accepted:
            width = dialog.get_width.value()
            height = dialog.get_height.value()
            self.pixmap = self.pixmap.scaled(width, height, Qt.IgnoreAspectRatio,
                    Qt.SmoothTransformation)
            self.save_img()

    def crop_img(self):
        self.img_view.setup_crop(self.pixmap.width(), self.pixmap.height())
        dialog = editimage.CropDialog(self, self.pixmap.width(), self.pixmap.height())
        if dialog.exec_() == QDialog.Accepted:
            coords = self.img_view.get_coords()
            self.pixmap = self.pixmap.copy(*coords)
            self.load_img()
        self.img_view.rband.hide()

    def toggle_fs(self):
        if self.fulls_act.isChecked():
            self.showFullScreen()
        else:
            self.showNormal()

    def toggle_slideshow(self):
        if self.ss_act.isChecked():
            self.showFullScreen()
            self.start_ss()
        else:
            self.toggle_fs()
            self.timer.stop()
            self.ss_timer.stop()

    def start_ss(self):
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_img)
        self.timer.start(self.slide_delay * 1000)
        self.ss_timer = QTimer()
        self.ss_timer.timeout.connect(self.update_img)
        self.ss_timer.start(60000)

    def update_img(self):
        if self.slides_next:
            self.go_next_img()
        else:
            self.fname = random.choice(self.filelist)
            self.reload_img()

    def set_slide_type(self):
        self.slides_next = self.ss_next_act.isChecked()

    def save_img(self):
        fname = QFileDialog.getSaveFileName(self, 'Save your image', self.fname)[0]
        if fname:
            if fname.lower().endswith(self.write_list):
                keep_exif = QMessageBox.question(self, 'Save exif data',
                        'Do you want to save the picture metadata?', QMessageBox.Yes |
                        QMessageBox.No, QMessageBox.Yes)
                if keep_exif == QMessageBox.Yes:
                    self.pixmap.save(fname, None, self.quality)
                    exif = GExiv2.Metadata(self.fname)
                    if exif:
                        saved_exif = GExiv2.Metadata(fname)
                        for tag in exif.get_exif_tags():
                            saved_exif[tag] = exif[tag]
                        saved_exif.set_orientation(GExiv2.Orientation.NORMAL)
                        saved_exif.save_file()
            else:
                QMessageBox.information(self, 'Error', 'Cannot save {} images.'.format(fname.rsplit('.', 1)[1]))

    def print_img(self):
        dialog = QPrintDialog(self.printer, self)
        if dialog.exec_():
            painter = QPainter(self.printer)
            rect = painter.viewport()
            if self.pixmap.width() > self.pixmap.height():
                self.pixmap = self.pixmap.transformed(QTransform().rotate(90))
            size = self.pixmap.size()
            size.scale(rect.size(), Qt.KeepAspectRatio)
            painter.setViewport(rect.x(), rect.y(), size.width(), size.height())
            painter.setWindow(self.pixmap.rect())
            painter.drawPixmap(0, 0, self.pixmap)

    def resizeEvent(self, event=None):
        if self.fit_win_act.isChecked():
            try:
                self.load_img()
            except:
                pass

    def get_props(self):
        """Get the properties of the current image."""
        image = QImage(self.fname)
        preferences.PropsDialog(self, self.fname.rsplit('/', 1)[1], image.width(), image.height())

    def help_page(self):
        preferences.HelpDialog(self)

    def about_cm(self):
        about_message = 'Version: 0.3.9\nAuthor: David Whitlock\nLicense: GPLv3'
        QMessageBox.about(self, 'About Cheesemaker', about_message)
Ejemplo n.º 46
0
class Overview(QGraphicsView):
    """Show an overview of data, such as hypnogram and data in memory.

    Attributes
    ----------
    parent : instance of QMainWindow
        the main window.
    config : ConfigChannels
        preferences for this widget

    minimum : int or float
        start time of the recording, from the absolute time of start_time in s
    maximum : int or float
        length of the recordings in s
    start_time : datetime
        absolute start time of the recording

    scene : instance of QGraphicsScene
        to keep track of the objects
    idx_current : QGraphicsRectItem
        instance of the current time window
    idx_markers : list of QGraphicsRectItem
        list of markers in the dataset
    idx_annot : list of QGraphicsRectItem
        list of user-made annotations
    """
    def __init__(self, parent):
        super().__init__()
        self.parent = parent
        self.config = ConfigOverview(self.update_settings)

        self.minimum = None
        self.maximum = None
        self.start_time = None  # datetime, absolute start time

        self.scene = None
        self.idx_current = None
        self.idx_markers = []
        self.idx_annot = []

        self.setMinimumHeight(TOTAL_HEIGHT + 30)

    def update(self):
        """Read full duration and update maximum."""
        if self.parent.info.dataset is not None:
            # read from the dataset, if available
            header = self.parent.info.dataset.header
            maximum = header['n_samples'] / header['s_freq']  # in s
            self.minimum = 0
            self.maximum = maximum
            self.start_time = self.parent.info.dataset.header['start_time']

        elif self.parent.notes.annot is not None:
            # read from annotations
            annot = self.parent.notes.annot
            self.minimum = annot.first_second
            self.maximum = annot.last_second
            self.start_time = annot.start_time

        # make it time-zone unaware
        self.start_time = self.start_time.replace(tzinfo=None)

        self.parent.value('window_start', 0)  # the only value that is reset

        self.display()

    def display(self):
        """Updates the widgets, especially based on length of recordings."""
        lg.debug('GraphicsScene is between {}s and {}s'.format(self.minimum,
                                                               self.maximum))

        x_scale = 1 / self.parent.value('overview_scale')
        lg.debug('Set scene x-scaling to {}'.format(x_scale))

        self.scale(1 / self.transform().m11(), 1)  # reset to 1
        self.scale(x_scale, 1)

        self.scene = QGraphicsScene(self.minimum, 0,
                                    self.maximum,
                                    TOTAL_HEIGHT)
        self.setScene(self.scene)

        # reset annotations
        self.idx_markers = []
        self.idx_annot = []

        self.display_current()

        for name, pos in BARS.items():
            item = QGraphicsRectItem(self.minimum, pos['pos0'],
                                     self.maximum, pos['pos1'])
            item.setToolTip(pos['tip'])
            self.scene.addItem(item)

        self.add_timestamps()

    def add_timestamps(self):
        """Add timestamps at the bottom of the overview."""
        transform, _ = self.transform().inverted()

        stamps = _make_timestamps(self.start_time, self.minimum, self.maximum,
                                  self.parent.value('timestamp_steps'))

        for stamp, xpos in zip(*stamps):
            text = self.scene.addSimpleText(stamp)
            text.setFlag(QGraphicsItem.ItemIgnoresTransformations)

            # set xpos and adjust for text width
            text_width = text.boundingRect().width() * transform.m11()
            text.setPos(xpos - text_width / 2, TIME_HEIGHT)

    def update_settings(self):
        """After changing the settings, we need to recreate the whole image."""
        self.display()
        self.display_markers()
        if self.parent.notes.annot is not None:
            self.parent.notes.display_notes()

    def update_position(self, new_position=None):
        """Update the cursor position and much more.

        Parameters
        ----------
        new_position : int or float
            new position in s, for plotting etc.

        Notes
        -----
        This is a central function. It updates the cursor, then updates
        the traces, the scores, and the power spectrum. In other words, this
        function is responsible for keep track of the changes every time
        the start time of the window changes.
        """
        if new_position is not None:
            lg.debug('Updating position to {}'.format(new_position))
            self.parent.value('window_start', new_position)
            self.idx_current.setPos(new_position, 0)

            current_time = (self.start_time +
                            timedelta(seconds=new_position))
            msg = 'Current time: ' + current_time.strftime('%H:%M:%S')
            self.parent.statusBar().showMessage(msg)
        else:
            lg.debug('Updating position at {}'
                     ''.format(self.parent.value('window_start')))

        if self.parent.info.dataset is not None:
            self.parent.traces.read_data()
            if self.parent.traces.data is not None:
                self.parent.traces.display()
                self.parent.spectrum.display_window()

        if self.parent.notes.annot is not None:
            self.parent.notes.set_stage_index()

        self.display_current()

    def display_current(self):
        """Create a rectangle showing the current window."""
        if self.idx_current in self.scene.items():
            self.scene.removeItem(self.idx_current)

        item = QGraphicsRectItem(0,
                                 CURR['pos0'],
                                 self.parent.value('window_length'),
                                 CURR['pos1'])
        # it's necessary to create rect first, and then move it
        item.setPos(self.parent.value('window_start'), 0)
        item.setPen(QPen(Qt.lightGray))
        item.setBrush(QBrush(Qt.lightGray))
        item.setZValue(-10)
        self.scene.addItem(item)
        self.idx_current = item

    def display_markers(self):
        """Mark all the markers, from the dataset.

        This function should be called only when we load the dataset or when
        we change the settings.
        """
        for rect in self.idx_markers:
            self.scene.removeItem(rect)
        self.idx_markers = []

        markers = []
        if self.parent.info.markers is not None:
            if self.parent.value('marker_show'):
                markers = self.parent.info.markers

        for mrk in markers:
            rect = QGraphicsRectItem(mrk['start'],
                                     BARS['markers']['pos0'],
                                     mrk['end'] - mrk['start'],
                                     BARS['markers']['pos1'])
            self.scene.addItem(rect)

            color = self.parent.value('marker_color')
            rect.setPen(QPen(QColor(color)))
            rect.setBrush(QBrush(QColor(color)))
            rect.setZValue(-5)
            self.idx_markers.append(rect)

    def display_annotations(self):
        """Mark all the bookmarks/events, from annotations.

        This function is similar to display_markers, but they are called at
        different stages (f.e. when loading annotations file), so we keep them
        separate
        """
        for rect in self.idx_annot:
            self.scene.removeItem(rect)
        self.idx_annot = []

        if self.parent.notes.annot is None:
            return

        bookmarks = []
        events = []
        if self.parent.value('annot_show'):
            bookmarks = self.parent.notes.annot.get_bookmarks()
            events = self.parent.notes.get_selected_events()

        annotations = bookmarks + events

        for annot in annotations:
            rect = QGraphicsRectItem(annot['start'],
                                     BARS['annot']['pos0'],
                                     annot['end'] - annot['start'],
                                     BARS['annot']['pos1'])
            self.scene.addItem(rect)

            if annot in bookmarks:
                color = self.parent.value('annot_bookmark_color')
            if annot in events:
                color = convert_name_to_color(annot['name'])

            rect.setPen(QPen(QColor(color), LINE_WIDTH))
            rect.setBrush(QBrush(QColor(color)))
            rect.setZValue(-5)
            self.idx_annot.append(rect)

        for epoch in self.parent.notes.annot.epochs:
            self.mark_stages(epoch['start'],
                             epoch['end'] - epoch['start'],
                             epoch['stage'])

    def mark_stages(self, start_time, length, stage_name):
        """Mark stages, only add the new ones.

        Parameters
        ----------
        start_time : int
            start time in s of the epoch being scored.
        length : int
           duration in s of the epoch being scored.
        stage_name : str
            one of the stages defined in global stages.
        """
        y_pos = BARS['stage']['pos0']

        # the -1 is really important, otherwise we stay on the edge of the rect
        old_score = self.scene.itemAt(start_time + length / 2,
                                      y_pos +
                                      STAGES[stage_name]['pos0'] +
                                      STAGES[stage_name]['pos1'] - 1,
                                      self.transform())

        # check we are not removing the black border
        if old_score is not None and old_score.pen() == NoPen:
            lg.debug('Removing old score at {}'.format(start_time))
            self.scene.removeItem(old_score)
            self.idx_annot.remove(old_score)

        rect = QGraphicsRectItem(start_time,
                                 y_pos + STAGES[stage_name]['pos0'],
                                 length,
                                 STAGES[stage_name]['pos1'])
        rect.setPen(NoPen)
        rect.setBrush(STAGES[stage_name]['color'])
        self.scene.addItem(rect)
        self.idx_annot.append(rect)

    def mousePressEvent(self, event):
        """Jump to window when user clicks on overview.

        Parameters
        ----------
        event : instance of QtCore.QEvent
            it contains the position that was clicked.
        """
        if self.scene is not None:
            x_in_scene = self.mapToScene(event.pos()).x()
            window_length = self.parent.value('window_length')
            window_start = int(floor(x_in_scene / window_length) *
                               window_length)
            self.update_position(window_start)

    def reset(self):
        """Reset the widget, and clear the scene."""
        self.minimum = None
        self.maximum = None
        self.start_time = None  # datetime, absolute start time

        self.idx_current = None
        self.idx_markers = []
        self.idx_annot = []

        if self.scene is not None:
            self.scene.clear()
        self.scene = None
Ejemplo n.º 47
0
class RunTimeGui(QMainWindow):

    activeStateChanged = pyqtSignal(int)
    runningStateChanged = pyqtSignal(int)
    loadFromRoot = pyqtSignal(int)

    def __init__(self, parent=None):
        super(QMainWindow, self).__init__()

        self.setWindowTitle("VisualStates RunTime GUI")

        self.rootState = None

        # create status bar
        self.statusBar()

        self.createTreeView()
        self.createStateCanvas()

        self.setGeometry(0, 0, 800, 600)
        self.show()

        self.states = {}
        self.transitions = {}

        self.activeState = None

        self.activeStateChanged.connect(self.activeStateChangedHandle)
        self.runningStateChanged.connect(self.runningStateChangedHandle)
        self.loadFromRoot.connect(self.loadFromRootHandle)

        self.memory = None
        self.ipcThread = None

    def createTreeView(self):
        dockWidget = QDockWidget()
        dockWidget.setAllowedAreas(Qt.LeftDockWidgetArea)
        dockWidget.setFeatures(QDockWidget.NoDockWidgetFeatures)
        dockWidget.setTitleBarWidget(QWidget())
        self.treeView = QTreeView()
        self.treeView.clicked.connect(self.treeItemClicked)
        self.treeModel = TreeModel()
        self.treeView.setModel(self.treeModel)

        self.logo = QLabel()
        logoPixmap = QPixmap(CMAKE_INSTALL_PREFIX + '/share/jderobot/resources/jderobot.png')
        self.logo.setPixmap(logoPixmap)

        self.upButton = QPushButton()
        self.upButton.setText('Up')
        self.upButton.clicked.connect(self.upButtonClicked)

        leftContainer = QWidget()
        leftLayout = QVBoxLayout()
        leftLayout.addWidget(self.treeView)
        leftLayout.addWidget(self.upButton)
        leftLayout.addWidget(self.logo)
        leftContainer.setLayout(leftLayout)

        dockWidget.setWidget(leftContainer)
        self.addDockWidget(Qt.LeftDockWidgetArea, dockWidget)

    def createStateCanvas(self):
        self.stateCanvas = QGraphicsView()
        self.scene = QGraphicsScene()
        self.scene.setSceneRect(0, 0, 2000, 2000)

        self.setCentralWidget(self.stateCanvas)
        self.stateCanvas.setScene(self.scene)
        self.stateCanvas.setRenderHint(QPainter.Antialiasing)


    def addState(self, id, name, initial, x, y, parentId):
        if parentId is not None:
            self.states[id] = State(id, name, initial, self.states[parentId])
            self.states[parentId].addChild(self.states[id])
            parentItem = self.treeModel.getByDataId(parentId)
            # print('parent:' + str(parentItem))
        else:
            self.states[id] = State(id, name, initial, None)
        if id == 0:
            self.rootState = self.states[id]

        self.states[id].setPos(x, y)

    def addTransition(self, id, name, originId, destinationId, x, y):
        self.transitions[id] = Transition(id, name, self.states[originId], self.states[destinationId])
        self.transitions[id].setPos(x, y)

    def emitRunningStateById(self, id):
        # print('emit running state:' + str(id))
        self.runningStateChanged.emit(id)

    def runningStateChangedHandle(self, id):
        # print('running state:' + str(id))
        if id not in self.states:
            return

        runningState = self.states[id]

        parentId = None
        if runningState.parent is not None:
            for child in runningState.parent.getChildren():
                child.setRunning(False)

            runningState.setRunning(True)
            parentId = runningState.parent.id

        self.treeModel.setAllBackgroundByParentId(Qt.white, parentId)
        self.treeModel.setBackgroundById(runningState.id, Qt.green)

    def emitActiveStateById(self, id):
        self.activeStateChanged.emit(id)

    def activeStateChangedHandle(self, id):
        if self.activeState is not None:
            for child in self.activeState.getChildren():
                child.resetGraphicsItem()
                for tran in child.getOriginTransitions():
                    tran.resetGraphicsItem()

        self.activeState = self.states[id]
        # print('set active state:' + str(id))
        self.scene.clear()
        for childState in self.activeState.getChildren():
            # print('add child to scene:' + str(childState.id))
            qitem = childState.getGraphicsItem()
            qitem.setAcceptHoverEvents(False)
            qitem.setFlag(QGraphicsItem.ItemIsMovable, False)
            qitem.doubleClicked.connect(self.stateDoubleClicked)
            self.setAcceptDrops(False)
            self.scene.addItem(qitem)
            for tran in childState.getOriginTransitions():
                # print('add transition:' + str(tran.id))
                qitem = tran.getGraphicsItem()
                qitem.disableInteraction()
                self.scene.addItem(qitem)

    def emitLoadFromRoot(self):
        self.loadFromRoot.emit(0)

    def loadFromRootHandle(self, id):
        self.treeModel.loadFromRoot(self.states[id])

    def stateDoubleClicked(self, stateItem):
        if len(stateItem.stateData.getChildren()) > 0:
            self.emitActiveStateById(stateItem.stateData.id)

    def upButtonClicked(self):
        if self.activeState is not None:
            if self.activeState.parent is not None:
                self.emitActiveStateById(self.activeState.parent.id)

    def getStateById(self,state, id):
        if state.id == id:
            return state
        else:
            result = None
            for child in state.getChildren():
                result = self.getStateById(child, id)
                if result is not None:
                    return result
            return result

    def treeItemClicked(self, index):
        # print('clicked item.id:' + str(index.internalPointer().id))
        pass

    def getStateList(self, state, stateList):
        if len(state.getChildren()) > 0:
            stateList.append(state)

        for s in state.getChildren():
            self.getStateList(s, stateList)

    def loopIPC(self):
        while True:
            msg = self.getIPCMessage()
            if msg is not None:
                # print('msg received:' + msg)
                methodName = msg.split(' ')[0]
                id = int(msg.split(' ')[1])
                if methodName == 'emitRunningStateById':
                    self.emitRunningStateById(id)
                else:
                    print('unknown method name')

            time.sleep(1.0/1000)

    def activateIPC(self):
        try:
            self.memory = sysv_ipc.SharedMemory(123456, sysv_ipc.IPC_CREX)
        except:
            # if memory exists just open shared memory
            self.memory = sysv_ipc.SharedMemory(123456)

        self.ipcThread = Thread(target=self.loopIPC)
        self.ipcThread.start()

    def getIPCMessage(self):
        if self.memory is not None:
            data = self.memory.read().decode()
            if data[0] != '0':
                self.memory.write('0'.encode())
                i = data.find('\0')
                if i != -1:
                    data = data[:i]
                return data

        return None
Ejemplo n.º 48
0
class MainWindow(QMainWindow):
    def __init__(self, parent):
        QMainWindow.__init__(self)

        self.printer = QPrinter()
        self.load_img = self.load_img_fit
        self.reload_img = self.reload_auto
        self.open_new = parent.open_win
        self.scene = QGraphicsScene()
        self.img_view = ImageView(self)
        self.img_view.setScene(self.scene)
        self.setCentralWidget(self.img_view)

        self.create_actions()
        self.create_menu()
        self.create_dict()
        self.create_toolbar()
        self.slides_next = True

        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.showMenu)

        self.read_prefs()
        self.read_list = parent.read_list
        self.write_list = parent.write_list
        self.pics_dir = os.path.expanduser('~/Pictures') or QDir.currentPath()
        self.resize(700, 500)

    def create_actions(self):
        self.open_act = QAction('&Open', self, shortcut='Ctrl+O')
        self.open_act.triggered.connect(self.open)
        self.open_new_act = QAction('Open new window',
                                    self,
                                    shortcut='Ctrl+Shift+O')
        self.open_new_act.triggered.connect(partial(self.open, True))
        self.reload_act = QAction('&Reload image', self, shortcut='Ctrl+R')
        self.reload_act.triggered.connect(self.reload_img)
        self.print_act = QAction('&Print', self, shortcut='Ctrl+P')
        self.print_act.triggered.connect(self.print_img)
        self.save_act = QAction('&Save image', self, shortcut='Ctrl+S')
        self.save_act.triggered.connect(self.save_img_as)
        self.close_act = QAction('Close window', self, shortcut='Ctrl+W')
        self.close_act.triggered.connect(self.close)
        self.exit_act = QAction('E&xit', self, shortcut='Ctrl+Q')
        self.exit_act.triggered.connect(self.exit)
        self.fulls_act = QAction('Fullscreen',
                                 self,
                                 shortcut='F11',
                                 checkable=True)
        self.fulls_act.triggered.connect(self.toggle_fs)
        self.ss_act = QAction('Slideshow', self, shortcut='F5', checkable=True)
        self.ss_act.triggered.connect(self.toggle_slideshow)
        self.ss_next_act = QAction('Next / Random image', self, checkable=True)
        self.ss_next_act.triggered.connect(self.set_slide_type)
        self.ss_next_act.setChecked(True)
        self.next_act = QAction('Next image', self, shortcut='Right')
        self.next_act.triggered.connect(self.go_next_img)
        self.prev_act = QAction('Previous image', self, shortcut='Left')
        self.prev_act.triggered.connect(self.go_prev_img)
        self.rotleft_act = QAction('Rotate left', self, shortcut='Ctrl+Left')
        self.rotleft_act.triggered.connect(partial(self.img_rotate, 270))
        self.rotright_act = QAction('Rotate right',
                                    self,
                                    shortcut='Ctrl+Right')
        self.rotright_act.triggered.connect(partial(self.img_rotate, 90))
        self.fliph_act = QAction('Flip image horizontally',
                                 self,
                                 shortcut='Ctrl+H')
        self.fliph_act.triggered.connect(partial(self.img_flip, -1, 1))
        self.flipv_act = QAction('Flip image vertically',
                                 self,
                                 shortcut='Ctrl+V')
        self.flipv_act.triggered.connect(partial(self.img_flip, 1, -1))
        self.resize_act = QAction('Resize image',
                                  self,
                                  triggered=self.resize_img)
        self.crop_act = QAction('Crop image', self, triggered=self.crop_img)
        self.zin_act = QAction('Zoom &In', self, shortcut='Up')
        self.zin_act.triggered.connect(partial(self.img_view.zoom, 1.1))
        self.zout_act = QAction('Zoom &Out', self, shortcut='Down')
        self.zout_act.triggered.connect(partial(self.img_view.zoom, 1 / 1.1))
        self.fit_win_act = QAction('Best &fit',
                                   self,
                                   checkable=True,
                                   shortcut='F',
                                   triggered=self.zoom_default)
        self.fit_win_act.setChecked(True)
        self.prefs_act = QAction('Preferences', self, triggered=self.set_prefs)
        self.props_act = QAction('Properties', self, triggered=self.get_props)
        self.help_act = QAction('&Help',
                                self,
                                shortcut='F1',
                                triggered=self.help_page)
        self.about_act = QAction('&About', self, triggered=self.about_cm)
        self.aboutQt_act = QAction('About &Qt', self, triggered=qApp.aboutQt)

    def create_menu(self):
        self.popup = QMenu(self)
        main_acts = [
            self.open_act, self.open_new_act, self.reload_act, self.print_act,
            self.save_act
        ]
        edit_acts1 = [
            self.rotleft_act, self.rotright_act, self.fliph_act, self.flipv_act
        ]
        edit_acts2 = [self.resize_act, self.crop_act]
        view_acts = [
            self.next_act, self.prev_act, self.zin_act, self.zout_act,
            self.fit_win_act, self.fulls_act, self.ss_act, self.ss_next_act
        ]
        help_acts = [self.help_act, self.about_act, self.aboutQt_act]
        end_acts = [
            self.prefs_act, self.props_act, self.close_act, self.exit_act
        ]
        for act in main_acts:
            self.popup.addAction(act)
        edit_menu = QMenu(self.popup)
        edit_menu.setTitle('&Edit')
        for act in edit_acts1:
            edit_menu.addAction(act)
        edit_menu.addSeparator()
        for act in edit_acts2:
            edit_menu.addAction(act)
        self.popup.addMenu(edit_menu)
        view_menu = QMenu(self.popup)
        view_menu.setTitle('&View')
        for act in view_acts:
            view_menu.addAction(act)
        self.popup.addMenu(view_menu)
        help_menu = QMenu(self.popup)
        help_menu.setTitle('&Help')
        for act in help_acts:
            help_menu.addAction(act)
        self.popup.addMenu(help_menu)
        for act in end_acts:
            self.popup.addAction(act)

        self.action_list = main_acts + edit_acts1 + edit_acts2 + view_acts + help_acts + end_acts
        for act in self.action_list:
            self.addAction(act)

    def showMenu(self, pos):
        self.popup.popup(self.mapToGlobal(pos))

    def create_dict(self):
        """Create a dictionary to handle auto-orientation."""
        self.orient_dict = {
            None: self.load_img,
            '1': self.load_img,
            '2': partial(self.img_flip, -1, 1),
            '3': partial(self.img_rotate, 180),
            '4': partial(self.img_flip, -1, 1),
            '5': self.img_rotate_fliph,
            '6': partial(self.img_rotate, 90),
            '7': self.img_rotate_flipv,
            '8': partial(self.img_rotate, 270)
        }

    def create_toolbar(self):
        script_dir = os.path.dirname(os.path.realpath(__file__))

        def icon(icon_name):
            return QIcon(os.path.join(script_dir, "assets", icon_name))

        def add_action(description, icon_file, function):
            action = QAction(icon(icon_file), description, self)
            action.triggered.connect(function)
            self.toolbar.addAction(action)

        self.toolbar = self.addToolBar("File")
        add_action("save", "save.png", self.save_img)
        add_action("crop", "crop.png", self.crop_img)
        add_action("resize", "resize.png", self.resize_img)
        add_action("save important", "star.png",
                   lambda: self.save_img(rating=100))
        add_action("save non important", "hollow_star.png",
                   lambda: self.save_img(rating=0))

    def read_prefs(self):
        """Parse the preferences from the config file, or set default values."""
        try:
            conf = preferences.Config()
            values = conf.read_config()
            self.auto_orient = values[0]
            self.slide_delay = values[1]
            self.quality = values[2]
        except:
            self.auto_orient = True
            self.slide_delay = 5
            self.quality = 90
        self.reload_img = self.reload_auto if self.auto_orient else self.reload_nonauto

    def set_prefs(self):
        """Write preferences to the config file."""
        dialog = preferences.PrefsDialog(self)
        if dialog.exec_() == QDialog.Accepted:
            self.auto_orient = dialog.auto_orient
            self.slide_delay = dialog.delay_spinb.value()
            self.quality = dialog.qual_spinb.value()
            conf = preferences.Config()
            conf.write_config(self.auto_orient, self.slide_delay, self.quality)
        self.reload_img = self.reload_auto if self.auto_orient else self.reload_nonauto

    def open(self, new_win=False):
        fname = QFileDialog.getOpenFileName(self, 'Open File',
                                            self.pics_dir)[0]
        if fname:
            if fname.lower().endswith(self.read_list):
                if new_win:
                    self.open_new(fname)
                else:
                    self.open_img(fname)
            else:
                QMessageBox.information(
                    self, 'Error',
                    'Cannot load {} images.'.format(fname.rsplit('.', 1)[1]))

    def open_img(self, fname):
        self.fname = fname
        self.reload_img()
        dirname = os.path.dirname(self.fname)
        self.set_img_list(dirname)
        self.img_index = self.filelist.index(self.fname)

    def set_img_list(self, dirname):
        """Create a list of readable images from the current directory."""
        filelist = os.listdir(dirname)
        self.filelist = [
            os.path.join(dirname, fname) for fname in filelist
            if fname.lower().endswith(self.read_list)
        ]
        self.filelist.sort()
        self.last_file = len(self.filelist) - 1

    def set_title(self):
        file_name = self.fname.rsplit('/', 1)[1]
        size = " [%d x %d]" % (self.pixmap.width(), self.pixmap.height())
        self.setWindowTitle(file_name + size)

    def get_img(self):
        """Get image from fname and create pixmap."""
        image = QImage(self.fname)
        self.pixmap = QPixmap.fromImage(image)

    def reload_auto(self):
        """Load a new image with auto-orientation."""
        self.get_img()
        try:
            orient = GExiv2.Metadata(self.fname)['Exif.Image.Orientation']
            self.orient_dict[orient]()
        except:
            self.load_img()

    def reload_nonauto(self):
        """Load a new image without auto-orientation."""
        self.get_img()
        self.load_img()

    def load_img_fit(self):
        """Load the image to fit the window."""
        self.scene.clear()
        self.scene.addPixmap(self.pixmap)
        self.scene.setSceneRect(0, 0, self.pixmap.width(),
                                self.pixmap.height())
        self.img_view.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio)
        self.set_title()

    def load_img_1to1(self):
        """Load the image at its original size."""
        self.scene.clear()
        self.img_view.resetTransform()
        self.scene.addPixmap(self.pixmap)
        self.scene.setSceneRect(0, 0, self.pixmap.width(),
                                self.pixmap.height())
        pixitem = QGraphicsPixmapItem(self.pixmap)
        self.img_view.centerOn(pixitem)
        self.set_title()

    def go_next_img(self):
        self.img_index = self.img_index + 1 if self.img_index < self.last_file else 0
        self.fname = self.filelist[self.img_index]
        self.reload_img()

    def go_prev_img(self):
        self.img_index = self.img_index - 1 if self.img_index else self.last_file
        self.fname = self.filelist[self.img_index]
        self.reload_img()

    def zoom_default(self):
        """Toggle best fit / original size loading."""
        if self.fit_win_act.isChecked():
            self.load_img = self.load_img_fit
            self.create_dict()
            self.load_img()
        else:
            self.load_img = self.load_img_1to1
            self.create_dict()
            self.load_img()

    def img_rotate(self, angle):
        self.pixmap = self.pixmap.transformed(QTransform().rotate(angle))
        self.load_img()

    def img_flip(self, x, y):
        self.pixmap = self.pixmap.transformed(QTransform().scale(x, y))
        self.load_img()

    def img_rotate_fliph(self):
        self.img_rotate(90)
        self.img_flip(-1, 1)

    def img_rotate_flipv(self):
        self.img_rotate(90)
        self.img_flip(1, -1)

    def resize_img(self):
        dialog = editimage.ResizeDialog(self, self.pixmap.width(),
                                        self.pixmap.height())
        if dialog.exec_() == QDialog.Accepted:
            width = dialog.get_width.value()
            height = dialog.get_height.value()
            self.pixmap = self.pixmap.scaled(width, height,
                                             Qt.IgnoreAspectRatio,
                                             Qt.SmoothTransformation)
            self.load_img()

    def crop_img(self):
        def callback(coords):
            self.pixmap = self.pixmap.copy(*coords)
            self.load_img()

        self.img_view.crop(callback)

    def toggle_fs(self):
        if self.fulls_act.isChecked():
            self.showFullScreen()
        else:
            self.showNormal()

    def toggle_slideshow(self):
        if self.ss_act.isChecked():
            self.showFullScreen()
            self.start_ss()
        else:
            self.toggle_fs()
            self.timer.stop()
            self.ss_timer.stop()

    def start_ss(self):
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_img)
        self.timer.start(self.slide_delay * 1000)
        self.ss_timer = QTimer()
        self.ss_timer.timeout.connect(self.update_img)
        self.ss_timer.start(60000)

    def update_img(self):
        if self.slides_next:
            self.go_next_img()
        else:
            self.fname = random.choice(self.filelist)
            self.reload_img()

    def set_slide_type(self):
        self.slides_next = self.ss_next_act.isChecked()

    def save_img_as(self):
        fname = QFileDialog.getSaveFileName(self, 'Save your image',
                                            self.fname)[0]
        if fname:
            if fname.lower().endswith(self.write_list):
                keep_exif = QMessageBox.question(
                    self, 'Save exif data',
                    'Do you want to save the picture metadata?',
                    QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
                if keep_exif == QMessageBox.Yes:
                    exif = GExiv2.Metadata(self.fname)
                    self.pixmap.save(fname, None, self.quality)
                    if exif:
                        saved_exif = GExiv2.Metadata(fname)
                        for tag in exif.get_exif_tags():
                            saved_exif[tag] = exif[tag]
                        saved_exif.set_orientation(GExiv2.Orientation.NORMAL)
                        saved_exif.save_file()
            else:
                QMessageBox.information(
                    self, 'Error',
                    'Cannot save {} images.'.format(fname.rsplit('.', 1)[1]))

    def save_img(self, rating=None):
        exif = GExiv2.Metadata(self.fname)
        self.pixmap.save(self.fname, None, self.quality)
        if rating is not None:
            exif["Exif.Image.Rating"] = str(rating)
        if exif:
            exif.save_file()

    def print_img(self):
        dialog = QPrintDialog(self.printer, self)
        if dialog.exec_():
            painter = QPainter(self.printer)
            rect = painter.viewport()
            if self.pixmap.width() > self.pixmap.height():
                self.pixmap = self.pixmap.transformed(QTransform().rotate(90))
            size = self.pixmap.size()
            size.scale(rect.size(), Qt.KeepAspectRatio)
            painter.setViewport(rect.x(), rect.y(), size.width(),
                                size.height())
            painter.setWindow(self.pixmap.rect())
            painter.drawPixmap(0, 0, self.pixmap)

    def resizeEvent(self, event=None):
        if self.fit_win_act.isChecked():
            try:
                self.load_img()
            except:
                pass

    def get_props(self):
        """Get the properties of the current image."""
        image = QImage(self.fname)
        preferences.PropsDialog(self,
                                self.fname.rsplit('/', 1)[1], image.width(),
                                image.height())

    def help_page(self):
        preferences.HelpDialog(self)

    def about_cm(self):
        about_message = 'Version: 0.3.9\nAuthor: David Whitlock\nLicense: GPLv3'
        QMessageBox.about(self, 'About Cheesemaker', about_message)

    def exit(self):
        QCoreApplication.quit()
Ejemplo n.º 49
0
class qfi_ALT (QGraphicsView):

    viewUpdate = pyqtSignal()

    def __init__(self,winParent):
        QGraphicsView.__init__(self)

        self.winParent=winParent

        self.viewUpdate.connect(self.updateView)
        
        self.m_altitude = 0
        self.m_pressure = 28

        self.m_originalHeight = 240
        self.m_originalWidth = 240

        self.m_originalAltCtr = QPointF(120,120)

        self.m_face1Z = -50
        self.m_face2Z = -40
        self.m_face3Z = -30
        self.m_hand1Z = -20
        self.m_hand2Z = -10
        self.m_caseZ = 10

        self.setStyleSheet("background: transparent; border: none")
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.setInteractive(False)
        self.setEnabled(False)


        self.m_scene = QGraphicsScene(self)
        
        self.setScene(self.m_scene)

        self.init()

        

    def init (self):
        self.m_scaleX = self.width() / self.m_originalWidth
        self.m_scaleY = self.height() / self.m_originalHeight


        self.m_itemFace_1 = QGraphicsSvgItem(":/qfi/images/alt/alt_face_1.svg")
        self.m_itemFace_1.setCacheMode (QGraphicsItem.NoCache)
        self.m_itemFace_1.setZValue( self.m_face1Z )
        self.m_itemFace_1.setTransform( QTransform.fromScale( self.m_scaleX, self.m_scaleY ), True )
        self.m_itemFace_1.setTransformOriginPoint( self.m_originalAltCtr )
        self.m_scene.addItem (self.m_itemFace_1)

        self.m_itemFace_2 = QGraphicsSvgItem(":/qfi/images/alt/alt_face_2.svg")
        self.m_itemFace_2.setCacheMode (QGraphicsItem.NoCache)
        self.m_itemFace_2.setZValue( self.m_face2Z )
        self.m_itemFace_2.setTransform( QTransform.fromScale( self.m_scaleX, self.m_scaleY ), True )
        self.m_itemFace_2.setTransformOriginPoint( self.m_originalAltCtr )
        self.m_scene.addItem (self.m_itemFace_2)

        self.m_itemFace_3 = QGraphicsSvgItem(":/qfi/images/alt/alt_face_3.svg")
        self.m_itemFace_3.setCacheMode (QGraphicsItem.NoCache)
        self.m_itemFace_3.setZValue( self.m_face3Z )
        self.m_itemFace_3.setTransform( QTransform.fromScale( self.m_scaleX, self.m_scaleY ), True )
        self.m_itemFace_3.setTransformOriginPoint( self.m_originalAltCtr )
        self.m_scene.addItem (self.m_itemFace_3)

        self.m_itemHand_1 = QGraphicsSvgItem(":/qfi/images/alt/alt_hand_1.svg")
        self.m_itemHand_1.setCacheMode (QGraphicsItem.NoCache)
        self.m_itemHand_1.setZValue( self.m_hand1Z )
        self.m_itemHand_1.setTransform( QTransform.fromScale( self.m_scaleX, self.m_scaleY ), True )
        self.m_itemHand_1.setTransformOriginPoint( self.m_originalAltCtr )
        self.m_scene.addItem (self.m_itemHand_1)

        self.m_itemHand_2 = QGraphicsSvgItem(":/qfi/images/alt/alt_hand_2.svg")
        self.m_itemHand_2.setCacheMode (QGraphicsItem.NoCache)
        self.m_itemHand_2.setZValue( self.m_hand2Z )
        self.m_itemHand_2.setTransform( QTransform.fromScale( self.m_scaleX, self.m_scaleY ), True )
        self.m_itemHand_2.setTransformOriginPoint( self.m_originalAltCtr )
        self.m_scene.addItem (self.m_itemHand_2)

        self.m_itemCase = QGraphicsSvgItem(":/qfi/images/alt/alt_case.svg")
        self.m_itemCase.setCacheMode (QGraphicsItem.NoCache)
        self.m_itemCase.setZValue( self.m_caseZ )
        self.m_itemCase.setTransform( QTransform.fromScale( self.m_scaleX, self.m_scaleY ), True )
        self.m_itemCase.setTransformOriginPoint( self.m_originalAltCtr )
        self.m_scene.addItem (self.m_itemCase)

        self.centerOn (self.width()/2, self.height()/2)

        self.updateView()

    def reinit(self):
        if (self.m_scene):
            self.m_scene.clear()
            self.init()

    def update(self):
        self.updateView()

    def setAltitude (self, altitude):
        self.m_altitude = altitude

    def setPressure (self, pressure):
        self.m_pressure = pressure
        if (self.m_pressure < 28):
            self.m_pressure = 28
        if (self.m_pressure > 31.5):
            self.m_pressure = 31.5

    def resizeEvent (self, event):
        QGraphicsView.resizeEvent (self,event)
        self.reinit()

    def reset (self):
        self.m_itemFace_1 = None
        self.m_itemFace_2 = None
        self.m_itemFace_3 = None
        self.m_itemHand_1 = None
        self.m_itemHand_2 = None
        self.m_itemCase   = None

        self.m_altitude =  0.0
        self.m_pressure = 28.0


    def updateView(self):
        altitude = math.ceil(self.m_altitude + 0.5)
        angleH1 = self.m_altitude * 0.036
        angleH2 = ( altitude % 1000 ) * 0.36
        angleF1 = (self.m_pressure - 28.0 ) * 100.0
        angleF3 = self.m_altitude * 0.0036

        self.m_itemHand_1.setRotation(angleH1)
        self.m_itemHand_2.setRotation(angleH2)
        self.m_itemFace_1.setRotation(- angleF1)
        self.m_itemFace_3.setRotation(angleF3)

        self.m_scene.update()
Ejemplo n.º 50
0
class MapCanvas(QGraphicsView):
    """Map Widget for Everquest Map Files."""
    def __init__(self):

        self._data = None
        # UI Init
        super().__init__()
        self.setObjectName('MapCanvas')
        self.setAutoFillBackground(True)
        self.setAttribute(Qt.WA_StyledBackground)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setContentsMargins(0, 0, 0, 0)
        self.setTransformationAnchor(self.AnchorViewCenter)
        self.setFocusPolicy(Qt.StrongFocus)
        self.setRenderHint(QPainter.Antialiasing)
        self._scene = QGraphicsScene()
        self.setScene(self._scene)
        self._scale = config.data['maps']['scale']
        self._mouse_location = MouseLocation()

    def load_map(self, map_name):
        try:
            map_data = MapData(str(map_name))

        except:
            traceback.print_exc()

        else:
            self._data = map_data
            self._scene.clear()
            self._z_index = 0
            self._draw()
            rect = self._scene.sceneRect()
            rect.adjust(-self._data.geometry.width * 2,
                        -self._data.geometry.height * 2,
                        self._data.geometry.width * 2,
                        self._data.geometry.height * 2)
            self.setSceneRect(rect)
            self.update()
            self.update_()

            self.centerOn(self._data.geometry.center_x,
                          self._data.geometry.center_y)
            self._mouse_location = MouseLocation()
            self._scene.addItem(self._mouse_location)
            config.data['maps']['last_zone'] = self._data.zone
            config.save()

    def _draw(self):
        for z in self._data.keys():
            self._scene.addItem(self._data[z]['paths'])
            for p in self._data[z]['poi']:
                self._scene.addItem(p.text)

        self._scene.addItem(self._data.grid)

    def update_(self, ratio=None):
        if not ratio:
            ratio = self._scale

        current_alpha = config.data['maps']['current_z_alpha'] / 100
        other_alpha = config.data['maps']['other_z_alpha'] / 100
        closest_alpha = config.data['maps']['closest_z_alpha'] / 100

        # scene
        self.setTransform(QTransform())  # reset transform object
        self._scale = to_range(ratio, 0.0006, 5.0)
        config.data['maps']['scale'] = self._scale
        self.scale(self._scale, self._scale)

        # lines and points of interest
        current_z_level = self._data.geometry.z_groups[self._z_index]
        closest_z_levels = set()
        for x in [i for i in [self._z_index - 1, self._z_index + 1] if i > -1]:
            try:
                closest_z_levels.add(self._data.geometry.z_groups[x])
            except:
                pass

        for z in self._data.keys():
            alpha = current_alpha
            if config.data['maps']['use_z_layers']:
                if z == current_z_level:
                    alpha = current_alpha
                elif z in closest_z_levels:
                    alpha = closest_alpha
                else:
                    alpha = other_alpha
            # lines
            bolded = 0.5 if config.data['maps']['use_z_layers'] else 0.0
            for path in self._data[z]['paths'].childItems():
                if z == current_z_level or not config.data['maps'][
                        'use_z_layers']:
                    pen = path.pen()
                    pen.setWidth(
                        max(config.data['maps']['line_width'] + bolded,
                            (config.data['maps']['line_width'] + bolded) /
                            self._scale))
                    path.setPen(pen)
                else:
                    pen = path.pen()
                    pen.setWidth(
                        max(config.data['maps']['line_width'] - 0.8,
                            (config.data['maps']['line_width'] - 0.8) /
                            self._scale))
                    path.setPen(pen)

            self._data[z]['paths'].setOpacity(alpha)

            # points of interest
            for p in self._data[z]['poi']:
                p.update_(min(5, self.to_scale()))
                if not config.data['maps']['show_poi']:
                    p.text.setOpacity(0)
                elif config.data['maps']['use_z_layers']:
                    if z == current_z_level:
                        p.text.setOpacity(current_alpha)
                    else:
                        p.text.setOpacity(other_alpha)
                else:
                    p.text.setOpacity(current_alpha)

        # players
        for player in self._data.players.values():
            player.update_(self.to_scale())
            if config.data['maps']['use_z_layers']:
                if player.z_level == current_z_level:
                    player.setOpacity(current_alpha)
                else:
                    player.setOpacity(other_alpha)
            else:
                player.setOpacity(current_alpha)

        # waypoint
        if self._data.way_point:
            self._data.way_point.update_(self.to_scale())
            if config.data['maps']['use_z_layers']:
                self._data.way_point.pixmap.setOpacity(current_alpha if (
                    self._data.way_point.location.z == current_z_level
                ) else other_alpha)
                player = self._data.players.get('__you__', None)
                if player and current_z_level in \
                        [self._data.way_point.location.z, player.z_level]:
                    self._data.way_point.line.setOpacity(current_alpha)
                else:
                    self._data.way_point.line.setOpacity(other_alpha)

            else:
                self._data.way_point.pixmap.setOpacity(current_alpha)

        # spawns
        for spawn in self._data.spawns:
            spawn.setScale(self.to_scale())
            spawn.realign(self.to_scale())
            if config.data['maps']['use_z_layers']:
                spawn.setOpacity(current_alpha if (
                    spawn.location.z == current_z_level) else other_alpha)
            else:
                spawn.setOpacity(current_alpha)

        # grid lines
        if config.data['maps']['show_grid']:
            pen = self._data.grid.pen()
            pen.setWidth(
                max(config.data['maps']['grid_line_width'],
                    self.to_scale(config.data['maps']['grid_line_width'])))
            self._data.grid.setPen(pen)
            self._data.grid.setVisible(True)
        else:
            self._data.grid.setVisible(False)

    def to_scale(self, float_value=1.0):
        return float_value / self._scale

    def center(self):
        player = None
        if self._data:
            player = self._data.players.get('__you__', None)
        if config.data['maps']['auto_follow'] and player:
            self.centerOn(player.location.x, player.location.y)

    def add_player(self, name, timestamp, location):
        if name not in self._data.players.keys():
            self._data.players[name] = Player(name=name,
                                              location=location,
                                              timestamp=timestamp)
            self._scene.addItem(self._data.players[name])
        else:
            self._data.players[name].previous_location = self._data.players[
                name].location
            self._data.players[name].location = location
            self._data.players[name].timestamp = timestamp
        self._data.players[name].z_level = self._data.get_closest_z_group(
            self._data.players[name].location.z)

        if name == '__you__' and config.data['maps']['use_z_layers']:
            self._z_index = self._data.geometry.z_groups.index(
                self._data.get_closest_z_group(
                    self._data.players['__you__'].location.z))

        self.update_()

        if self._data.way_point and name == '__you__':
            self._data.way_point.update_(self.to_scale(), location=location)

        if name == '__you__' and config.data['maps']['auto_follow']:
            self.center()

    def enterEvent(self, event):
        if config.data['maps']['show_mouse_location']:
            self._mouse_location.setVisible(True)
        QGraphicsView.enterEvent(self, event)

    def leaveEvent(self, event):
        self._mouse_location.setVisible(False)
        QGraphicsView.leaveEvent(self, event)

    def mouseMoveEvent(self, event):
        self._mouse_location.set_value(self.mapToScene(event.pos()),
                                       self._scale, self)
        QGraphicsView.mouseMoveEvent(self, event)

    def wheelEvent(self, event):
        # Scale based on scroll wheel direction
        movement = event.angleDelta().y()
        if self.dragMode() == self.NoDrag:
            if movement > 0:
                self.update_(self._scale + self._scale * 0.1)
            else:
                self.update_(self._scale - self._scale * 0.1)
        else:
            if self._data:
                if movement > 0:
                    self._z_index = max(self._z_index - 1, 0)
                else:
                    self._z_index = min(self._z_index + 1,
                                        len(self._data.geometry.z_groups) - 1)
                self.update_()

        # Update Mouse Location
        self._mouse_location.set_value(self.mapToScene(event.pos()),
                                       self._scale, self)

    def keyPressEvent(self, event):
        # Enable drag mode while control button is being held down
        if event.modifiers() == Qt.ControlModifier:
            self.setDragMode(self.ScrollHandDrag)
        QGraphicsView.keyPressEvent(self, event)

    def keyReleaseEvent(self, event):
        # Disable drag mode when control button released
        if event.key() == Qt.Key_Control:
            self.setDragMode(self.NoDrag)
        QGraphicsView.keyPressEvent(self, event)

    def resizeEvent(self, event):
        self.center()
        QGraphicsView.resizeEvent(self, event)

    def contextMenuEvent(self, event):
        # create menu
        pos = self.mapToScene(event.pos())
        menu = QMenu(self)
        # remove from memory after usage
        menu.setAttribute(Qt.WA_DeleteOnClose)  # remove from memory
        spawn_point_menu = menu.addMenu('Spawn Point')
        spawn_point_create = spawn_point_menu.addAction('Create on Cursor')
        spawn_point_delete = spawn_point_menu.addAction('Delete on Cursor')
        spawn_point_delete_all = spawn_point_menu.addAction('Delete All')
        way_point_menu = menu.addMenu('Way Point')
        way_point_create = way_point_menu.addAction('Create on Cursor')
        way_point_delete = way_point_menu.addAction('Clear')
        load_map = menu.addAction('Load Map')

        # execute
        action = menu.exec_(self.mapToGlobal(event.pos()))

        # parse response

        if action == spawn_point_create:
            spawn_time = text_time_to_seconds('6:40')
            dialog = QInputDialog(self)
            dialog.setWindowTitle('Create Spawn Point')
            dialog.setLabelText('Respawn Time (hh:mm:ss):')
            dialog.setTextValue('6:40')

            if dialog.exec_():
                spawn_time = text_time_to_seconds(dialog.textValue())
            dialog.deleteLater()

            spawn = SpawnPoint(location=MapPoint(
                x=pos.x(),
                y=pos.y(),
                z=self._data.geometry.z_groups[self._z_index]),
                               length=spawn_time)

            self._scene.addItem(spawn)
            self._data.spawns.append(spawn)
            spawn.start()

        if action == spawn_point_delete:
            pixmap = self._scene.itemAt(pos.x(), pos.y(), QTransform())
            if pixmap:
                group = pixmap.parentItem()
                if group:
                    self._data.spawns.remove(group)
                    self._scene.removeItem(group)

        if action == spawn_point_delete_all:
            for spawn in self._data.spawns:
                self._scene.removeItem(spawn)
            self._data.spawns = []

        if action == way_point_create:
            if self._data.way_point:
                self._scene.removeItem(self._data.way_point.pixmap)
                self._scene.removeItem(self._data.way_point.line)
                self._data.way_point = None

            self._data.way_point = WayPoint(location=MapPoint(
                x=pos.x(),
                y=pos.y(),
                z=self._data.geometry.z_groups[self._z_index]))

            self._scene.addItem(self._data.way_point.pixmap)
            self._scene.addItem(self._data.way_point.line)

        if action == way_point_delete:
            if self._data.way_point:
                self._scene.removeItem(self._data.way_point.pixmap)
                self._scene.removeItem(self._data.way_point.line)
            self._data.way_point = None

        if action == load_map:
            dialog = QInputDialog(self)
            dialog.setWindowTitle('Load Map')
            dialog.setLabelText('Select map to load:')
            dialog.setComboBoxItems(
                sorted([map.title()
                        for map in MapData.get_zone_dict().keys()]))
            if dialog.exec_():
                self.load_map(dialog.textValue().lower())
            dialog.deleteLater()

        self.update_()
Ejemplo n.º 51
0
class Widget(QMainWindow, client_form):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setupUi(self)
        self.refreshLabel.setVisible(False)
        self.client = Client(50000, 3000)

        self.refreshButton.clicked.connect(self.refresh)
        self.connectButton.clicked.connect(self.connect)

        self._graphics_scene = QGraphicsScene(self)
        self.graphicsView.setScene(self._graphics_scene)
        self._graphics_scene.mousePressEvent = self.mouse_pressed
        self.exit_action.triggered.connect(self.exit)
        self.help_action.triggered.connect(self.show_help)
        self.bullshit_action.triggered.connect(self.send_incorrect_message)
        self.viewlog_action.triggered.connect(self.open_log)
        self.connected = False

    def open_log(self):
        if os.uname().sysname == "Darwin":
            webbrowser.open("file:///" + os.path.abspath("./client.log"))
        else:
            webbrowser.open("./client.log")

    def exit(self):
        if self.connected:
            self.revert()
            self.client.disconnect()

        self.close()

    def show_help(self):
        mb = QMessageBox.information(
            self, "О программе",
            "Программа удаленного управления рабочим столом.\n\n"
            "Создатели:\n"
            "Алексей Абакумкин, ИУ7-72\n"
            "Роман Инфлянскас, ИУ7-71\n"
            "(c) 2014, Москва, МГТУ им. Н. Э. Баумана")

    def critical(self, msg, log=True):
        self.revert()
        QMessageBox.critical(self, "Ошибка", msg)
        if log:
            logging.error("{ip}\t{msg}\tОшибка".format(ip=self.client.ip, msg=msg))

    def send_incorrect_message(self):
        if self.connected:
            try:
                self.client.send_incorrect_message()
            except:
                # mb = QMessageBox.critical(self, "Ошибка", "Сервер перестал отвечать")
                self.critical("Сервер перестал отвечать")

    def refresh(self):
        self.serverList.clear()
        self.refreshLabel.setVisible(True)
        self.repaint()

        for x in self.client.refresh_server_list():
            self.serverList.addItem("{0}:{1}".format(x[0], x[1]))

        self.refreshLabel.setVisible(False)

    def connect(self):
        if self.connected:
            self.revert()
            self.client.disconnect()
            return

        try:
            login, login_ok = QInputDialog.getText(self, 'Логин', 'Введите логин:')
            if login_ok:
                passwd, password_ok = QInputDialog.getText(self, 'Пароль', 'Введите пароль:', 2)
                if password_ok:
                    server_item = self.serverList.currentItem()
                    try:
                        address = server_item.text().split(":")
                    except:
                        # server_item = self.serverList.findItems('', 0)[0]
                        self.serverList.setCurrentRow(0)
                        server_item = self.serverList.currentItem()
                        address = server_item.text().split(":")
                    if self.client.connect_to_server(address, login, passwd):
                        self.connectButton.setText("Отключиться")
                        self.connected = True
                    else:
                        self.critical("Неверный логин или пароль!", log=False)
                        # mb = QMessageBox.critical(self, "Ошибка", "Неверный логин или пароль!")

        except TimeoutError:
            self.critical("Сервер перестал отвечать")
            # mb = QMessageBox.critical(self, "Ошибка", "Сервер перестал отвечать")

    def revert(self):
        self._graphics_scene.clear()
        self.connectButton.setText("Присоединиться")
        self.connected = False

    def paintEvent(self, QPaintEvent):
        if self.connected:
            try:
                self.image_base_64 = self.client.recieve_screenshot()
            except TimeoutError:
                self.critical("Сервер перестал отвечать")
                # mb = QMessageBox.critical(self, "Ошибка", "Сервер перестал отвечать")
                return


            self.data = QByteArray.fromBase64(self.image_base_64)
            self.pm = QPixmap()
            self.pm.loadFromData(self.data, "PNG")

            self._graphics_scene.clear()
            self._graphics_scene.addPixmap(self.pm)
            self.update()

    def mouse_pressed(self, event):
        if self.connected:
            x = int(event.scenePos().x())
            y = int(event.scenePos().y())

            button = event.button()
            if button == 4:
                button = 3

            try:
                self.client.send_mouse_event(x, y, button)
            except:
                self.critical("Сервер перестал отвечать")
                # mb = QMessageBox.critical(self, "Ошибка", "Сервер перестал отвечать")
                self.revert()
Ejemplo n.º 52
0
class panel(QGraphicsView):
    def __init__(self):
        super(panel, self).__init__()

        self.arbolito = None  #arbol de entornos

        self.y = 50  #posicion en y inicial
        self.escena = QGraphicsScene()  #escena de dibujo

        self.setScene(
            self.escena)  #asignamos la escena al QGraphicsView de la clase

    # -------------------------------------------------------------------------------------------------
    #           metodo que verifica cuando se hace click en la escena
    # -------------------------------------------------------------------------------------------------
    def mousePressEvent(self, event):
        print("clicked")
        x = event.pos().x()
        y = event.pos().y()
        print(x, y)
        pt = self.mapToScene(
            event.pos()
        )  #se escala la posicion de click del QGraphicsView a la escena (QGraphicsScene)

        root = self.arbolito.get_root()  #raiz del arbol
        if (root != None):
            rect = QRect(
                int(pt.x()), int(pt.y()), root.tam,
                root.tam)  # se crea un rectangulo para la colision con el nodo
            self.__colision(root, rect)

    # -------------------------------------------------------------------------------------------------
    #           metodo que verifica si el evento del click se realizo sobre algun nodo
    # -------------------------------------------------------------------------------------------------
    def __colision(self, nodo, rect):

        #si el nodo entrante fue el clickeado
        if nodo.rect.intersects(rect):

            #se muestra un mensaje
            #con la informacion del nodo-> nombre del procedimiento o funcion
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Information)

            msg.setText("Nombre Ambiente: " + str(nodo.info))
            msg.exec_()

            return True
        else:
            #si no se mira si se hizo el click en alguno de los hijos
            for i in nodo.childrens:
                self.__colision(i, rect)

    # -------------------------------------------------------------------------------------------------
    #       metodo que limpia la escena y llama al metodo de pintado del arbol
    # -------------------------------------------------------------------------------------------------
    def dibujar(self):

        #self.arbolito.get_root().print_tree()
        self.escena.clear()
        self.pintar()

    # -------------------------------------------------------------------------------------------------
    #       metodo publico que llama el pintado del arbol y sus lineas desde la razi
    # -------------------------------------------------------------------------------------------------
    def pintar(self):

        root = self.arbolito.get_root()
        self.y = 50
        self.__pintar_arbol(root, 10, self.y)
        self.__lineas(root)

    # -------------------------------------------------------------------------------------------------
    #      metodo que pinta todos los nodos del arbol
    # -------------------------------------------------------------------------------------------------
    def __pintar_arbol(self, nodo, x, y):

        pen = QPen(Qt.black)  #lapiz de nodo normal
        pen2 = QPen(Qt.green)  #lapiz de nodo actual
        nodo.x = x  #se asigna posicion x al nodo
        nodo.y = self.y  #se asigna posicion y al nodo

        nodo.rect = QRect(
            nodo.x, nodo.y, nodo.tam, nodo.tam
        )  # se crea un rectangulo para el nodo,para los eventos click

        #print("Pos x : ",nodo.x,"Pos y : ",nodo.y," Dato :",nodo.data," Info : ",nodo.info)

        xp = nodo.tam / 2
        #self.escena.addRect(nodo.rect,pen)
        if nodo.activo:
            self.escena.addEllipse(nodo.x, nodo.y, nodo.tam, nodo.tam, pen2)
        else:
            self.escena.addEllipse(nodo.x, nodo.y, nodo.tam, nodo.tam, pen)

        #texto del nodo
        text = self.escena.addText(str(nodo.data))
        text.setPos(QPointF(nodo.x + 2, nodo.y - 3))

        x += 50

        ##pintar los hijos
        for i in nodo.childrens:
            self.y += 40
            self.__pintar_arbol(i, x, self.y)

    # -------------------------------------------------------------------------------------------------
    #   metodo que pinta las lineas de relacion en el arbol
    # -------------------------------------------------------------------------------------------------
    def __lineas(self, nodo):

        pen = QPen(Qt.black)
        xp = nodo.tam / 2
        for i in nodo.childrens:
            xl1_a = nodo.x + nodo.tam + 5
            yl1_a = nodo.y + nodo.tam - 5

            ylb = i.y + xp
            self.escena.addLine(nodo.x + nodo.tam, yl1_a, xl1_a, yl1_a)
            self.escena.addLine(xl1_a, yl1_a, xl1_a, ylb, pen)
            self.escena.addLine(xl1_a, ylb, i.x, ylb, pen)
            self.__lineas(i)
Ejemplo n.º 53
0
class UMLDialog(E5MainWindow):
    """
    Class implementing a dialog showing UML like diagrams.
    """
    NoDiagram = 255
    ClassDiagram = 0
    PackageDiagram = 1
    ImportsDiagram = 2
    ApplicationDiagram = 3
    
    FileVersions = ["1.0"]
    
    def __init__(self, diagramType, project, path="", parent=None,
                 initBuilder=True, **kwargs):
        """
        Constructor
        
        @param diagramType type of the diagram (one of ApplicationDiagram,
            ClassDiagram, ImportsDiagram, NoDiagram, PackageDiagram)
        @param project reference to the project object (Project)
        @param path file or directory path to build the diagram from (string)
        @param parent parent widget of the dialog (QWidget)
        @keyparam initBuilder flag indicating to initialize the diagram
            builder (boolean)
        @keyparam kwargs diagram specific data
        """
        super(UMLDialog, self).__init__(parent)
        self.setObjectName("UMLDialog")
        
        self.__diagramType = diagramType
        self.__project = project
        
        from .UMLGraphicsView import UMLGraphicsView
        self.scene = QGraphicsScene(0.0, 0.0, 800.0, 600.0)
        self.umlView = UMLGraphicsView(self.scene, parent=self)
        self.builder = self.__diagramBuilder(
            self.__diagramType, path, **kwargs)
        if self.builder and initBuilder:
            self.builder.initialize()
        
        self.__fileName = ""
        
        self.__initActions()
        self.__initToolBars()
        
        self.setCentralWidget(self.umlView)
        
        self.umlView.relayout.connect(self.__relayout)
        
        self.setWindowTitle(self.__diagramTypeString())
    
    def __initActions(self):
        """
        Private slot to initialize the actions.
        """
        self.closeAct = \
            QAction(UI.PixmapCache.getIcon("close.png"),
                    self.tr("Close"), self)
        self.closeAct.triggered.connect(self.close)
        
        self.openAct = \
            QAction(UI.PixmapCache.getIcon("open.png"),
                    self.tr("Load"), self)
        self.openAct.triggered.connect(self.load)
        
        self.saveAct = \
            QAction(UI.PixmapCache.getIcon("fileSave.png"),
                    self.tr("Save"), self)
        self.saveAct.triggered.connect(self.__save)
        
        self.saveAsAct = \
            QAction(UI.PixmapCache.getIcon("fileSaveAs.png"),
                    self.tr("Save As..."), self)
        self.saveAsAct.triggered.connect(self.__saveAs)
        
        self.saveImageAct = \
            QAction(UI.PixmapCache.getIcon("fileSavePixmap.png"),
                    self.tr("Save as Image"), self)
        self.saveImageAct.triggered.connect(self.umlView.saveImage)
        
        self.printAct = \
            QAction(UI.PixmapCache.getIcon("print.png"),
                    self.tr("Print"), self)
        self.printAct.triggered.connect(self.umlView.printDiagram)
        
        self.printPreviewAct = \
            QAction(UI.PixmapCache.getIcon("printPreview.png"),
                    self.tr("Print Preview"), self)
        self.printPreviewAct.triggered.connect(
            self.umlView.printPreviewDiagram)
    
    def __initToolBars(self):
        """
        Private slot to initialize the toolbars.
        """
        self.windowToolBar = QToolBar(self.tr("Window"), self)
        self.windowToolBar.setIconSize(UI.Config.ToolBarIconSize)
        self.windowToolBar.addAction(self.closeAct)
        
        self.fileToolBar = QToolBar(self.tr("File"), self)
        self.fileToolBar.setIconSize(UI.Config.ToolBarIconSize)
        self.fileToolBar.addAction(self.openAct)
        self.fileToolBar.addSeparator()
        self.fileToolBar.addAction(self.saveAct)
        self.fileToolBar.addAction(self.saveAsAct)
        self.fileToolBar.addAction(self.saveImageAct)
        self.fileToolBar.addSeparator()
        self.fileToolBar.addAction(self.printPreviewAct)
        self.fileToolBar.addAction(self.printAct)
        
        self.umlToolBar = self.umlView.initToolBar()
        
        self.addToolBar(Qt.TopToolBarArea, self.fileToolBar)
        self.addToolBar(Qt.TopToolBarArea, self.windowToolBar)
        self.addToolBar(Qt.TopToolBarArea, self.umlToolBar)
    
    def show(self, fromFile=False):
        """
        Public method to show the dialog.
        
        @keyparam fromFile flag indicating, that the diagram was loaded
            from file (boolean)
        """
        if not fromFile and self.builder:
            self.builder.buildDiagram()
        super(UMLDialog, self).show()
    
    def __relayout(self):
        """
        Private method to relayout the diagram.
        """
        if self.builder:
            self.builder.buildDiagram()
    
    def __diagramBuilder(self, diagramType, path, **kwargs):
        """
        Private method to instantiate a diagram builder object.
        
        @param diagramType type of the diagram
            (one of ApplicationDiagram, ClassDiagram, ImportsDiagram,
            PackageDiagram)
        @param path file or directory path to build the diagram from (string)
        @keyparam kwargs diagram specific data
        @return reference to the instantiated diagram builder
        @exception ValueError raised to indicate an illegal diagram type
        """
        if diagramType == UMLDialog.ClassDiagram:
            from .UMLClassDiagramBuilder import UMLClassDiagramBuilder
            return UMLClassDiagramBuilder(
                self, self.umlView, self.__project, path, **kwargs)
        elif diagramType == UMLDialog.PackageDiagram:
            from .PackageDiagramBuilder import PackageDiagramBuilder
            return PackageDiagramBuilder(
                self, self.umlView, self.__project, path, **kwargs)
        elif diagramType == UMLDialog.ImportsDiagram:
            from .ImportsDiagramBuilder import ImportsDiagramBuilder
            return ImportsDiagramBuilder(
                self, self.umlView, self.__project, path, **kwargs)
        elif diagramType == UMLDialog.ApplicationDiagram:
            from .ApplicationDiagramBuilder import ApplicationDiagramBuilder
            return ApplicationDiagramBuilder(
                self, self.umlView, self.__project, **kwargs)
        elif diagramType == UMLDialog.NoDiagram:
            return None
        else:
            raise ValueError(self.tr(
                "Illegal diagram type '{0}' given.").format(diagramType))
    
    def __diagramTypeString(self):
        """
        Private method to generate a readable string for the diagram type.
        
        @return readable type string (string)
        """
        if self.__diagramType == UMLDialog.ClassDiagram:
            return "Class Diagram"
        elif self.__diagramType == UMLDialog.PackageDiagram:
            return "Package Diagram"
        elif self.__diagramType == UMLDialog.ImportsDiagram:
            return "Imports Diagram"
        elif self.__diagramType == UMLDialog.ApplicationDiagram:
            return "Application Diagram"
        else:
            return "Illegal Diagram Type"
    
    def __save(self):
        """
        Private slot to save the diagram with the current name.
        """
        self.__saveAs(self.__fileName)
    
    @pyqtSlot()
    def __saveAs(self, filename=""):
        """
        Private slot to save the diagram.
        
        @param filename name of the file to write to (string)
        """
        if not filename:
            fname, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
                self,
                self.tr("Save Diagram"),
                "",
                self.tr("Eric Graphics File (*.e5g);;All Files (*)"),
                "",
                E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
            if not fname:
                return
            ext = QFileInfo(fname).suffix()
            if not ext:
                ex = selectedFilter.split("(*")[1].split(")")[0]
                if ex:
                    fname += ex
            if QFileInfo(fname).exists():
                res = E5MessageBox.yesNo(
                    self,
                    self.tr("Save Diagram"),
                    self.tr("<p>The file <b>{0}</b> already exists."
                            " Overwrite it?</p>").format(fname),
                    icon=E5MessageBox.Warning)
                if not res:
                    return
            filename = fname
        
        lines = [
            "version: 1.0",
            "diagram_type: {0} ({1})".format(
                self.__diagramType, self.__diagramTypeString()),
            "scene_size: {0};{1}".format(self.scene.width(),
                                         self.scene.height()),
        ]
        persistenceData = self.builder.getPersistenceData()
        if persistenceData:
            lines.append("builder_data: {0}".format(persistenceData))
        lines.extend(self.umlView.getPersistenceData())
        
        try:
            f = open(filename, "w", encoding="utf-8")
            f.write("\n".join(lines))
            f.close()
        except (IOError, OSError) as err:
            E5MessageBox.critical(
                self,
                self.tr("Save Diagram"),
                self.tr(
                    """<p>The file <b>{0}</b> could not be saved.</p>"""
                    """<p>Reason: {1}</p>""").format(filename, str(err)))
            return
        
        self.__fileName = filename
    
    def load(self):
        """
        Public method to load a diagram from a file.
        
        @return flag indicating success (boolean)
        """
        filename = E5FileDialog.getOpenFileName(
            self,
            self.tr("Load Diagram"),
            "",
            self.tr("Eric Graphics File (*.e5g);;All Files (*)"))
        if not filename:
            # Cancelled by user
            return False
        
        try:
            f = open(filename, "r", encoding="utf-8")
            data = f.read()
            f.close()
        except (IOError, OSError) as err:
            E5MessageBox.critical(
                self,
                self.tr("Load Diagram"),
                self.tr(
                    """<p>The file <b>{0}</b> could not be read.</p>"""
                    """<p>Reason: {1}</p>""").format(filename, str(err)))
            return False
        
        lines = data.splitlines()
        if len(lines) < 3:
            self.__showInvalidDataMessage(filename)
            return False
        
        try:
            # step 1: check version
            linenum = 0
            key, value = lines[linenum].split(": ", 1)
            if key.strip() != "version" or \
                    value.strip() not in UMLDialog.FileVersions:
                self.__showInvalidDataMessage(filename, linenum)
                return False
            else:
                version = value
            
            # step 2: extract diagram type
            linenum += 1
            key, value = lines[linenum].split(": ", 1)
            if key.strip() != "diagram_type":
                self.__showInvalidDataMessage(filename, linenum)
                return False
            try:
                self.__diagramType = int(value.strip().split(None, 1)[0])
            except ValueError:
                self.__showInvalidDataMessage(filename, linenum)
                return False
            self.scene.clear()
            self.builder = self.__diagramBuilder(self.__diagramType, "")
            
            # step 3: extract scene size
            linenum += 1
            key, value = lines[linenum].split(": ", 1)
            if key.strip() != "scene_size":
                self.__showInvalidDataMessage(filename, linenum)
                return False
            try:
                width, height = [float(v.strip()) for v in value.split(";")]
            except ValueError:
                self.__showInvalidDataMessage(filename, linenum)
                return False
            self.umlView.setSceneSize(width, height)
            
            # step 4: extract builder data if available
            linenum += 1
            key, value = lines[linenum].split(": ", 1)
            if key.strip() == "builder_data":
                ok = self.builder.parsePersistenceData(version, value)
                if not ok:
                    self.__showInvalidDataMessage(filename, linenum)
                    return False
                linenum += 1
            
            # step 5: extract the graphics items
            ok, vlinenum = self.umlView.parsePersistenceData(
                version, lines[linenum:])
            if not ok:
                self.__showInvalidDataMessage(filename, linenum + vlinenum)
                return False
        
        except IndexError:
            self.__showInvalidDataMessage(filename)
            return False
        
        # everything worked fine, so remember the file name
        self.__fileName = filename
        return True
    
    def __showInvalidDataMessage(self, filename, linenum=-1):
        """
        Private slot to show a message dialog indicating an invalid data file.
        
        @param filename name of the file containing the invalid data (string)
        @param linenum number of the invalid line (integer)
        """
        if linenum < 0:
            msg = self.tr("""<p>The file <b>{0}</b> does not contain"""
                          """ valid data.</p>""").format(filename)
        else:
            msg = self.tr("""<p>The file <b>{0}</b> does not contain"""
                          """ valid data.</p><p>Invalid line: {1}</p>"""
                          ).format(filename, linenum + 1)
        E5MessageBox.critical(self, self.tr("Load Diagram"), msg)
Ejemplo n.º 54
0
class Game(QGraphicsView):

    end_signal = pyqtSignal(int)
    score_signal = pyqtSignal(int)

    def __init__(self):
        """
        Function creates MyView object.
        """
        QGraphicsView.__init__(self)
        self.__init_game()
        self.__init_ui()

    def __init_game(self):
        """
        Function initializes all backend game fields.
        :return:
        """
        self.bombs = []
        self.timer = QTimer()
        self.player = Player.Player(1, 1, 0)
        self.bots = [
            Bot.Bot(10 + (i + 1) * 6, 10 + (i + 1) * 6, i + 1)
            for i in range(num_of_bots)
        ]
        self.score = 0
        self.create_board()
        self.move_dict = {
            Qt.Key_Left: self.move_left,
            Qt.Key_Right: self.move_right,
            Qt.Key_Up: self.move_up,
            Qt.Key_Down: self.move_down,
            Qt.Key_Space: self.add_bomb
        }
        for bot in self.bots:
            bot.remember_board(self.board)
            bot.remember_player_pos([self.player])
            bot.remember_bombs(self.bombs)

    def __init_ui(self):
        """
        Function initializes User Interface and Map view.
        :return:
        """
        self.scene = QGraphicsScene(0, 0, WINDOW_HEIGHT, WINDOW_WIDTH)
        self.view = QGraphicsView(self.scene)
        self.draw_board()
        self.setScene(self.scene)
        self.timer.timeout.connect(self.update)
        self.timer.start(10)
        self.timer_bots = QTimer()
        self.timer_bots.timeout.connect(self.move_bot)
        self.timer_bots.start(200)

        self.items = self.scene.items()

    def reinit_game(self):
        """
        Function gets game to init state.
        :return:
        """
        self.__init_game()
        self.__init_ui()

    def get_obj(self, x, y):
        """
        Function returns object in a map by coordinates.
        :param x: x coordinate of an object
        :param y: y coordiate of an object
        :return: Object.
        """
        for item in self.items:
            if item.x == x and item.y == y:
                return item
            else:
                return None

    def update(self):
        """
        Function handles all games parameters such as bombs boom,
        player death etc.
        Should be called periodically.

        :return:
        """
        for bomb in self.bombs:
            self.board[bomb.x][bomb.y] = 'XX'  # Add bomb to the board.
            self.draw_image(bomb.x, bomb.y, path_bomb)
        if self.player.alive:
            self.board[self.player.x][
                self.player.y] = 'OO'  # Add player to the board.
            self.draw_image(self.player.last_x, self.player.last_y, path_road)
            self.draw_image(self.player.x, self.player.y, path_bomberman)
        for bot in self.bots:
            if bot.alive:
                self.board[bot.x][bot.y] = 'BB'
                self.draw_image(bot.last_x, bot.last_y, path_road)
                self.draw_image(bot.x, bot.y, path_bot)

        self.score_signal.emit(self.score)
        self.boom()

    def read_board_xml(self, filename="map.xml"):
        """
        Function reads game map from the XML file.

        :param filename: Name of xml file.
        :return:
        """
        xmldoc = xm.parse(filename)
        rowslist = xmldoc.getElementsByTagName('row')

        for i in range(len(rowslist)):
            obj = rowslist[i].getElementsByTagName('obj')
            for j in range(len(obj)):
                self.board[i][j] = obj[j].firstChild.data

    def write_board_xml(self, filename="map.xml"):
        """
        Function writes game map to the XML file.

        :param filename: Name of xml file.
        :return:
        """
        doc = xm.Document()
        map_elem = doc.createElement("mapa")
        for i in range(len(self.board)):
            row_elem = doc.createElement("row")

            for j in range(len(self.board[0])):
                obj_elem = doc.createElement("obj")
                row_elem.appendChild(obj_elem)
                obj_elem.appendChild(doc.createTextNode(self.board[i][j]))
            map_elem.appendChild(row_elem)
        doc.appendChild(map_elem)

        with open(filename, 'w') as the_file:
            the_file.write(doc.toprettyxml())

    def draw_board(self):
        """
        Function draw whole game map.
        :return:
        """
        self.scene.clear()
        for bomba in self.bombs:
            self.board[bomba.X][bomba.Y] = 'XX'
        if self.player.alive:
            self.board[self.player.x][self.player.y] = 'OO'

        for bot in self.bots:
            if bot.alive:
                self.board[bot.x][bot.y] = 'BB'

        for i in range(len(self.board)):
            for j in range(len(self.board[i])):
                if self.board[i][j] == '##':
                    self.draw_image(i, j, path_cant_destroy)
                elif self.board[i][j] == '**':
                    self.draw_image(i, j, path_can_destroy)
                elif self.board[i][j] == '  ':
                    self.draw_image(i, j, path_road)
                elif self.board[i][j] == 'OO':
                    self.draw_image(i, j, path_bomberman)
                elif self.board[i][j] == 'XX':
                    self.draw_image(i, j, path_bomb)
                elif self.board[i][j] == 'BB':
                    self.draw_image(i, j, path_bot)

    def create_board(self):
        """
        Function creates game map.
        It's based on creating maze algorithm.
        :return:
        """
        temp = numpy.zeros((MAP_WIDTH, MAP_HEIGHT), dtype=bool)
        temp = temp.astype(str)
        for x in range(MAP_WIDTH):
            for y in range(MAP_HEIGHT):
                if x == 0 or y == 0 or x == MAP_WIDTH - 1 or y == MAP_HEIGHT - 1:
                    temp[x][y] = "##"
                elif x % 2 == 0 and y % 2 == 0:
                    temp[x][y] = "##"
                else:
                    temp[x][y] = "**"
                if temp[self.player.x + 1][self.player.y] != "##":
                    temp[self.player.x + 1][self.player.y] = "  "
                if temp[self.player.x][self.player.y + 1] != "##":
                    temp[self.player.x][self.player.y + 1] = "  "
                if temp[self.player.x + 2][self.player.y] != "##":
                    temp[self.player.x + 2][self.player.y] = "  "
                if temp[self.player.x][self.player.y + 2] != "##":
                    temp[self.player.x][self.player.y + 2] = "  "
                for i in range(len(self.bots)):
                    if temp[self.bots[i].x - 1][self.bots[i].y] != "##":
                        temp[self.bots[i].x - 1][self.bots[i].y] = "  "
                    if temp[self.bots[i].x][self.bots[i].y - 1] != "##":
                        temp[self.bots[i].x][self.bots[i].y - 1] = "  "
                    if temp[self.bots[i].x - 2][self.bots[i].y] != "##":
                        temp[self.bots[i].x - 2][self.bots[i].y] = "  "
                    if temp[self.bots[i].x][self.bots[i].y - 2] != "##":
                        temp[self.bots[i].x][self.bots[i].y - 2] = "  "

                temp[14][16] = "  "
                temp[16][14] = "  "
                temp[14][15] = "  "
                temp[15][17] = "  "
                temp[15][15] = "  "
                temp[15][14] = "  "

        self.board = temp

    def draw_image(self, x, y, path):
        """
        Function draw single image on game map.
        :param x: X coordinate of an image.
        :param y: Y coordinate of an image.
        :param path: path with an image to be printed.
        :return:
        """
        # Remove items from scene.
        self.items = self.scene.items()
        item = self.get_obj(x, y)
        if len(self.items) > MAP_HEIGHT * MAP_WIDTH:
            if item is not None:
                self.scene.removeItem(item)
        item = MyRect.MyRect(x, y, path)
        item.setAcceptHoverEvents(True)
        item.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable)
        self.scene.addItem(item)

    def keyPressEvent(self, event):
        """
        Key press event.
        :param event:
        :return:
        """
        self.move_dict[event.key()](self.player)

    def move_up(self, player):
        """
        Function checks if player can go up. If can it moves, if can't it does nothing.

        :param player: Player to be moved.
        :return:
        """
        if player.y < MAP_HEIGHT - 1 and self.board[player.x][player.y + 1] != '**'\
                and self.board[player.x][player.y + 1] != '##':
            self.board[player.x][player.y] = '  '
            player.move('u')

    def move_down(self, player):
        """
        Function checks if player can go down. If can it moves, if can't it does nothing.

        :param player: Player to be moved.
        :return:
        """
        if player.y > 1 and self.board[player.x][player.y - 1] != '**'\
                and self.board[player.x][player.y - 1] != '##':
            self.board[player.x][player.y] = '  '
            player.move('d')

    def move_left(self, player):
        """
        Function checks if player can go left. If can it moves, if can't it does nothing.

        :param player: Player to be moved.
        :return:
        """
        if player.x > 1 and self.board[player.x - 1][player.y] != '**'\
                and self.board[player.x - 1][player.y] != '##':
            self.board[player.x][player.y] = '  '
            player.move('l')

    def move_right(self, player):
        """
        Function checks if player can go right. If can it moves, if can't it does nothing.

        :param player: Player to be moved.
        :return:
        """
        if player.x < MAP_HEIGHT - 1 and self.board[player.x + 1][player.y] != '**'\
                and self.board[player.x + 1][player.y] != '##':
            self.board[player.x][player.y] = '  '
            player.move('r')

    def add_bomb(self, player):
        """
        Function adds bomb to bombs list.

        :param player: Player which left the bomb.
        :return:
        """
        self.bombs.append(
            Bomb.Bomb(player.x, player.y, time.time(), player.ind))

    def boom(self):
        """
        Function handles bombs explosion.
        :return:
        """
        end = False
        for bomb in self.bombs:
            if time.time() - bomb.start > 3:
                self.clean_fields_after_boom(bomb)
                end = self.kill_players(bomb)
                self.bombs.remove(bomb)
                if bomb.owner == self.player.ind:
                    self.score += bomb_range
        if end:
            self.end_signal.emit(1)

    def clean_fields_after_boom(self, bomb):
        """
        Function cleans fields after bomb explosion.
        :param bomb:
        :return:
        """
        for field in bomb.get_cords_in_range():
            if 0 < field[0] < MAP_WIDTH and \
                0 < field[1] < MAP_HEIGHT and \
                self.board[field[0]][field[1]] != "##":
                self.board[field[0]][field[1]] = "  "
                self.draw_image(field[0], field[1], path_road)
        self.board[bomb.x][bomb.y] = "  "
        self.draw_image(bomb.x, bomb.y, path_road)

    def kill_players(self, bomb):
        """
        Function checks if player is killed by bomb.
        If is it returns True else returns False
        :param bomb: Bomb object
        :return:
        """
        for cords in bomb.get_cords_in_range():
            if (self.player.x, self.player.y) == cords:
                self.player.alive = False
            for bot in self.bots:
                if (bot.x, bot.y) == cords:
                    bot.alive = False

        return not self.player.alive

    def move_bot(self):
        """
        Function handles bot move.
        :return:
        """
        for bot in self.bots:
            old_x = bot.x
            old_y = bot.y
            bot.move()
            if bot.is_bomb_left():
                self.bombs.append(Bomb.Bomb(old_x, old_y, time.time(), 1))
                self.board[bot.last_x][bot.last_y] = "XX"
            else:
                self.board[old_x][old_y] = "  "
            self.board[bot.x][bot.y] = "BB"
            bot.remember_player_pos([self.player])
            bot.remember_board(self.board)
            bot.remember_bombs(self.bombs)
Ejemplo n.º 55
0
class FilteringDialog(QDialog, Ui_Dialog):
    scene = None
    base_image = None
    image = None
    current_sampling_level = 0

    sliders = None
    labels = None
    fit_allowed = False

    def __init__(self, data_manager):
        super(FilteringDialog, self).__init__()
        self.setupUi(self)
        self.setAttribute(Qt.WA_DeleteOnClose)

        assert isinstance(data_manager, DataManager)
        self.base_image = data_manager.radiographs[0].image
        h, w = self.base_image.shape
        ch, cw = h / 2, w / 2
        self.base_image = self.base_image[ch - 100:ch + 500, cw - 150:cw + 150].copy()
        self.image = self.base_image

        self.scene = QGraphicsScene()
        self.graphicsView.setScene(self.scene)

        self.levelSlider.setRange(1, MultiResolutionFramework.levels_count)
        self.levelSlider.setValue(self.current_sampling_level + 1)
        self.levelSlider.valueChanged.connect(self._sampling_level_changed)

        ranges = [(0, 20), (0, 20), (0, 20), (0, 200), (0, 200)]
        values = [2, 8, 9, 0, 5]
        self.sliders = list()
        self.labels = list()
        for i in range(0, len(ranges)):
            slider = QSlider(Qt.Horizontal, self.scrollAreaWidgetContents)
            label = QLabel()
            slider.setRange(ranges[i][0], ranges[i][1])
            slider.setValue(values[i])
            slider.valueChanged.connect(self._slider_moved)
            layout = QHBoxLayout()
            layout.addWidget(slider)
            layout.addWidget(label)
            self.scrollAreaWidgetContents.layout().addLayout(layout)
            self.sliders.append(slider)
            self.labels.append(label)

        self._set_labels()
        self._redraw()

    def _sampling_level_changed(self, value):
        self.current_sampling_level = value - 1

        self.image = self.base_image
        scale = 1.0
        for i in range(0, self.current_sampling_level):
            self.image = MultiResolutionFramework.downsample_image(self.image)
            scale *= 2

        self.graphicsView.resetTransform()
        self.graphicsView.scale(scale, scale)
        self._redraw()

    def _slider_moved(self, value):
        self._set_labels()
        self._redraw()

    def _set_labels(self):
        for i, label in enumerate(self.labels):
            value = self.sliders[i].value()
            if i < 2:
                value = value * 2 + 1 if value >= 1 else 0
            label.setText(str(value))

    def _scharr_filter(self, img):
        grad_x = cv2.Scharr(img, cv2.CV_64F, 1, 0) / 16
        grad_y = cv2.Scharr(img, cv2.CV_64F, 0, 1) / 16
        grad = np.sqrt(grad_x ** 2 + grad_y ** 2)
        return grad

    def _perform_fft(self, img):
        f = np.fft.fft2(img)
        fshift = np.fft.fftshift(f)
        return fshift

    def _focus_view(self, size):
        if not self.fit_allowed:
            self.fit_allowed = True
            return
        rect = QRectF(0, 0, size[0], size[1])
        self.scene.setSceneRect(rect)

    def _redraw(self):
        self.scene.clear()
        img = self.image.copy()

        med_kernel = self.sliders[0].value() * 2 + 1
        bi_kernel = self.sliders[1].value() * 2 + 1
        bi_color = self.sliders[2].value()

        med = cv2.medianBlur(img, med_kernel) if med_kernel > 1 else img
        med_bi = cv2.bilateralFilter(med, bi_kernel, bi_color, 200) if bi_kernel > 1 else med

        fshift = self._perform_fft(med_bi)
        # scharr = np.array([[ -1/16-1/16j, 1/2-1/8j,  +1/16 -1/16j],
        #                    [-1/8+0j, 1/2+0j, +1/8 +0j],
        #                    [ -1/16+1/16j, 0+1/8j,  +1/16 +1/16j]]) # Gx + j*Gy
        # fshift = signal.convolve2d(fshift, scharr, boundary='symm', mode='same')

        if self.sliders[3].value() != 0:
            rows, cols = img.shape
            crow, ccol = rows / 2, cols / 2
            mask = np.zeros(fshift.shape)
            cv2.circle(mask, (ccol, crow), self.sliders[3].value(), 1, -1)
            cv2.circle(mask, (ccol, crow), self.sliders[4].value(), 0, -1)
            fshift *= mask

        f_ishift = np.fft.ifftshift(fshift)
        img_back = np.fft.ifft2(f_ishift)
        img_back = np.abs(img_back)

        grad_med_bi = self._scharr_filter(img_back)

        # img = (img / img.max()) * 255
        mag = 20 * np.log(np.abs(fshift))
        mag = (mag / mag.max()) * 255
        img_back = (img_back / img_back.max()) * 255
        grad_med_bi = (grad_med_bi / grad_med_bi.max()) * 255

        together = np.hstack(
            (img.astype(np.uint8), mag.astype(np.uint8), img_back.astype(np.uint8), grad_med_bi.astype(np.uint8)))
        cv2.imwrite("together.png", together)
        qimg = toQImage(together)
        self.scene.addPixmap(QPixmap.fromImage(qimg))

        self._focus_view((qimg.width(), qimg.height()))
class APISRepresentativeImage(QDialog, FORM_CLASS):
    def __init__(self,
                 dbm,
                 imageRegistry,
                 currentPath,
                 filmNumber,
                 parent=None):
        """Constructor."""
        super(APISRepresentativeImage, self).__init__(parent)

        self.dbm = dbm
        self.imageRegistry = imageRegistry
        self.currentPath = currentPath
        self.filmNumber = filmNumber
        self.newPath = currentPath

        self.setupUi(self)
        if GetWindowSize("representative_image"):
            self.resize(GetWindowSize("representative_image"))

        self.settings = QSettings(QSettings().value("APIS/config_ini"),
                                  QSettings.IniFormat)

        # Signals/Slot Connections
        self.rejected.connect(self.onReject)
        self.buttonBox.rejected.connect(self.onReject)
        self.buttonBox.accepted.connect(self.onAccept)
        self.uiSelectImageFromSystem.clicked.connect(
            self.selectImageFromSystem)

        self.graphicLoaded = False

        self.scene = QGraphicsScene()
        self.uiRepresentativeImageView.setScene(self.scene)

        # ist FilmProjekt ein FILM?
        if IsFilm(self.dbm.db, self.filmNumber):
            self.populateFilmCombo(self.filmNumber)
        else:
            self.populateFilmCombo()
        # wenn nein self.populateFilmCombo()

        self.uiAvailableImagesCombo.currentIndexChanged.connect(
            self.loadNewImageByFilm)

    def populateFilmCombo(self, filmNumber=None):
        editor = self.uiFilmNumberCombo
        model = QSqlQueryModel(self)
        model.setQuery(
            "SELECT DISTINCT {0} FROM {1} ORDER BY {2}".format(
                'filmnummer', 'film', 'filmnummer'), self.dbm.db)

        tv = QTableView()
        editor.setView(tv)

        tv.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        tv.setSelectionMode(QAbstractItemView.SingleSelection)
        tv.setSelectionBehavior(QAbstractItemView.SelectRows)
        tv.setAutoScroll(False)

        editor.setModel(model)

        editor.setModelColumn(0)
        editor.setInsertPolicy(QComboBox.NoInsert)

        tv.resizeColumnsToContents()
        tv.resizeRowsToContents()
        tv.verticalHeader().setVisible(False)
        tv.horizontalHeader().setVisible(True)
        # tv.setMinimumWidth(tv.horizontalHeader().length())
        tv.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        #FIXME PyQt5 AutoCompletion
        #editor.setAutoCompletion(True)

        if filmNumber:
            editor.setCurrentIndex(editor.findText(filmNumber))
            self.populateAvailableImagesCombo()
        else:
            editor.setCurrentIndex(-1)

        editor.currentIndexChanged.connect(self.populateAvailableImagesCombo)

    def populateAvailableImagesCombo(self, idx=None):
        self.filmNumber = self.uiFilmNumberCombo.currentText()
        # query image registry
        availableImages = self.imageRegistry.getImageRegistryForFilm(
            self.filmNumber)
        self.uiAvailableImagesCombo.clear()
        self.uiAvailableImagesCombo.addItems(availableImages)
        self.uiAvailableImagesCombo.setCurrentIndex(-1)

    def showEvent(self, event):
        if self.currentPath:
            self.uiImagePathLbl.setText(self.currentPath)
            self.loadImage(self.currentPath)
        else:
            self.uiImagePathLbl.setText("--")
            self.loadText()

        self.graphicLoaded = True

    def loadText(self):
        self.scene.clear()
        noImageTxt = QGraphicsTextItem()
        noImageTxt.setPlainText(
            u"Wählen Sie ein repräsentatives Luftbild aus ...")
        self.rect = noImageTxt.boundingRect()
        self.scene.addItem(noImageTxt)
        self.scene.setSceneRect(self.rect)
        self.uiRepresentativeImageView.fitInView(self.rect, Qt.KeepAspectRatio)

    def loadImage(self, path):
        self.scene.clear()
        image = QImage(path)
        size = image.size()
        self.rect = QRectF(0, 0, size.width(), size.height())
        self.scene.addPixmap(QPixmap.fromImage(image))
        self.scene.setSceneRect(self.rect)
        self.uiRepresentativeImageView.fitInView(self.rect, Qt.KeepAspectRatio)

    def loadNewImageByFilm(self):
        # generatePath
        imgDir = self.settings.value("APIS/image_dir")
        filmDir = self.filmNumber
        self.newPath = os.path.normpath(
            imgDir + "\\" + filmDir + "\\" +
            self.uiAvailableImagesCombo.currentText().replace('.', '_') +
            ".jpg")
        self.uiImagePathLbl.setText(self.newPath)
        self.loadImage(self.newPath)

    def resizeEvent(self, event):
        if self.graphicLoaded:
            self.uiRepresentativeImageView.fitInView(self.rect,
                                                     Qt.KeepAspectRatio)

    def selectImageFromSystem(self):
        dir = self.settings.value("APIS/image_dir")
        fileName, _filter = QFileDialog.getOpenFileName(
            self, u"Repräsentatives Luftbild auswählen", dir,
            "Bild Dateien (*.jpg)")
        if fileName:
            self.uiFilmNumberCombo.setCurrentIndex(-1)
            self.newPath = fileName
            self.uiImagePathLbl.setText(self.newPath)
            self.loadImage(self.newPath)

    def onAccept(self):
        '''
        Check DB
        Save options when pressing OK button
        Update Plugin Status
        '''
        SetWindowSize("representative_image", self.size())
        self.accept()

    def onReject(self):
        '''
        Run some actions when
        the user closes the dialog
        '''
        SetWindowSize("representative_image", self.size())
        self.close()
class BackgroundGeneratorDialog(Ui_BackgroundGeneratorDialog, QDialog):
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        Ui_BackgroundGeneratorDialog.__init__(self)
        self.setupUi(self)

        self.videoPlaybackInit()
        self.imgInit()

        self.generateButton.pressed.connect(self.generateBackground)


    def closeEvent(self,event):
        pass

    def videoPlaybackInit(self):
        self.videoPlaybackWidget.frameChanged.connect(self.setFrame, type=Qt.QueuedConnection)

    def setFrame(self, frame):
        if frame is not None:

            self.cv_img = frame
            self.updateInputGraphicsView()

            if self.fgbg is not None:
                self.updateOutputGraphicsView()

    def imgInit(self):
        self.inputScene = QGraphicsScene()
        self.inputGraphicsView.setScene(self.inputScene)
        self.inputGraphicsView.resizeEvent = self.inputGraphicsViewResized

        self.outputScene = QGraphicsScene()
        self.outputGraphicsView.setScene(self.outputScene)
        self.outputGraphicsView.resizeEvent = self.outputGraphicsViewResized

        self.fgbg = None

    def openVideoFile(self, filePath = None):
        if len(filePath) is not 0:
            self.filePath = filePath

            ret = self.videoPlaybackWidget.openVideo(filePath)
            if ret == False:
                return False

            self.videoPlaybackWidget.show()
            self.filterClassHash = None

            return True

    def updateInputGraphicsView(self):
        self.inputScene.clear()
        # self.inputScene.removeItem(self.inputPixMapItem)
        qimg = cvMatToQImage(self.cv_img)
        self.inputPixMap = QPixmap.fromImage(qimg)

        rect = QtCore.QRectF(self.inputPixMap.rect())
        self.inputScene.setSceneRect(rect)
        self.outputScene.setSceneRect(rect)

        self.inputPixMapItem = QGraphicsPixmapItem(self.inputPixMap)
        # self.inputScene.setBackgroundBrush(QBrush(self.inputPixMap))
        self.inputScene.addItem(self.inputPixMapItem)

        self.inputGraphicsView.viewport().update()
        self.inputGraphicsViewResized()

    def updateOutputGraphicsView(self):
        if False:
            out_img = self.fgbg.apply(self.cv_img, learningRate=0)
        else:
            bg = self.fgbg.getBackgroundImage()
            out_img = cv2.absdiff(self.cv_img, bg)

        self.outputScene.clear()
        qimg = cvMatToQImage(out_img)
        self.outputPixMap = QPixmap.fromImage(qimg)

        rect = QtCore.QRectF(self.outputPixMap.rect())
        self.outputScene.setSceneRect(rect)

        self.outputPixMapItem = QGraphicsPixmapItem(self.outputPixMap)
        self.outputScene.addItem(self.outputPixMapItem)

        self.outputGraphicsView.viewport().update()
        self.outputGraphicsViewResized()

    def inputGraphicsViewResized(self, event=None):
        self.inputGraphicsView.fitInView(self.inputScene.sceneRect(), QtCore.Qt.KeepAspectRatio)

    def outputGraphicsViewResized(self, event=None):
        self.outputGraphicsView.fitInView(self.outputScene.sceneRect(), QtCore.Qt.KeepAspectRatio)

    def generateBackground(self):
        minFrame = self.videoPlaybackWidget.getMinRange()
        maxFrame = self.videoPlaybackWidget.getMaxRange()
        stride = self.strideSpinBox.value()
        numFrames = int((maxFrame-minFrame)/stride)
        progress = QProgressDialog("Generating background...", "Abort", 0, numFrames, self)

        progress.setWindowModality(Qt.WindowModal)

        fgbg = cv2.createBackgroundSubtractorMOG2()
        currentFrameNo = self.videoPlaybackWidget.currentFrameNo
        for i, frameNo in enumerate(range(minFrame, maxFrame+1, stride)):
            progress.setValue(i)
            if progress.wasCanceled():
                break

            ret, frame = self.videoPlaybackWidget.readFrame(frameNo)
            fgbg.apply(frame)

        if not progress.wasCanceled():
            self.fgbg = fgbg
            self.setFrame(self.cv_img)

        progress.setValue(numFrames)

        self.videoPlaybackWidget.currentFrameNo = currentFrameNo