Esempio n. 1
0
    def __init__(self, start_state: ShibumiGameState):
        super().__init__(start_state)
        self.start_state = start_state

        ui = self.ui = Ui_ShibumiDisplay()
        ui.setupUi(self)
        scene = QGraphicsScene()
        ui.game_display.setScene(scene)
        self.background_pixmap = self.assemble_board()
        self.background_item = scene.addPixmap(self.background_pixmap)
        self.white_scaled = self.white_pixmap = self.load_pixmap(
            'ball-w-shadow-1.png')
        self.black_scaled = self.black_pixmap = self.load_pixmap(
            'ball-b-shadow-1.png')
        self.red_scaled = self.red_pixmap = self.load_pixmap(
            'ball-r-shadow-1.png')
        self.remove_pixmap = self.load_pixmap('ball-x-shadow-1.png')
        self.item_levels = []
        self.hovered_piece: typing.Optional[GraphicsShibumiPieceItem] = None
        for height in range(self.start_state.size):
            item_level = []
            for row in range(self.start_state.size - height):
                item_row = []
                for column in range(self.start_state.size - height):
                    item = GraphicsShibumiPieceItem(height, row, column, self)
                    scene.addItem(item)
                    item_row.append(item)
                item_level.append(item_row)
            self.item_levels.append(item_level)
        self.row_labels = []
        self.column_labels = []
        for i in range(self.start_state.size * 2 - 1):
            self.row_labels.append(scene.addSimpleText(str(i + 1)))
            self.column_labels.append(scene.addSimpleText(chr(i + 65)))
        self.ui.move_black.clicked.connect(
            lambda: self.on_move_type_selected(MoveType.BLACK))
        self.ui.move_white.clicked.connect(
            lambda: self.on_move_type_selected(MoveType.WHITE))
        self.ui.move_red.clicked.connect(
            lambda: self.on_move_type_selected(MoveType.RED))
        self.ui.remove.clicked.connect(
            lambda: self.on_move_type_selected(MoveType.REMOVE))
        self._selected_move_type = MoveType.BLACK
        self._visible_counts: typing.FrozenSet[PlayerCode] = frozenset()
        self._visible_move_types: typing.FrozenSet[MoveType] = frozenset()
        self.ui.black_count_pixmap.setText('')
        self.ui.white_count_pixmap.setText('')
        self.ui.red_count_pixmap.setText('')
        self.ui.move_black.setText('')
        self.ui.move_white.setText('')
        self.ui.move_red.setText('')
        self.ui.remove.setText('')
        self.ui.move_black.setIcon(self.black_pixmap)
        self.ui.move_white.setIcon(self.white_pixmap)
        self.ui.move_red.setIcon(self.red_pixmap)
        self.ui.remove.setIcon(self.remove_pixmap)
        self.ui.pass_button.setVisible(False)
        self.show_counts = False
        self.show_move_types = False
        self.debug_message = ''
Esempio n. 2
0
    def __init__(self, start_state: GridGameState):
        super().__init__(start_state)
        self.start_state: GridGameState = start_state
        self.spaces = []  # self.spaces[i][j] holds row i, column j
        self.column_dividers = []
        self.row_dividers = []
        self.column_labels = []
        self.row_labels = []
        self.text_x = self.text_y = 0

        ui = self.ui = Ui_GridControls()
        ui.setupUi(self)
        scene = QGraphicsScene()
        ui.game_display.setScene(scene)
        scene.setBackgroundBrush(self.background_colour)
        self.player1_icon = self.create_icon(self.player1_colour)
        self.player2_icon = self.create_icon(self.player2_colour)
        ui.black_count_pixmap.setText('')
        ui.white_count_pixmap.setText('')
        ui.black_count.setText('')
        ui.white_count.setText('')

        for _ in range(start_state.board_height - 1):
            self.row_dividers.append(scene.addLine(0, 0, 1, 1))
        for _ in range(start_state.board_width - 1):
            self.column_dividers.append(scene.addLine(0, 0, 1, 1))
        for i in range(start_state.board_height):
            self.row_labels.append(scene.addSimpleText(f'{i + 1}'))
        for j in range(start_state.board_width):
            self.column_labels.append(scene.addSimpleText(chr(65 + j)))
        self.to_move = scene.addEllipse(0,
                                        0,
                                        1,
                                        1,
                                        brush=self.get_player_brush(
                                            self.start_state.X_PLAYER))
        self.to_move.setVisible(False)
        self.move_text = ui.move_text
        for i in range(self.start_state.board_height):
            row: typing.List[GraphicsPieceItem] = []
            self.spaces.append(row)
            for j in range(self.start_state.board_width):
                piece = GraphicsPieceItem(i, j, self)
                scene.addItem(piece)
                piece.setBrush(self.background_colour)
                piece.setPen(self.background_colour)
                row.append(piece)
        self.debug_message = ''
Esempio n. 3
0
    def _on_calculate_word_freq(self):
        # one reference
        # selected = self.window.refListView.currentIndex().row()
        # refPath = self.refPaths[selected]
        selecteds = self.window.refListView.selectedIndexes()
        selectedRefPaths = []
        for selected in selecteds:
            selectedRefPaths.append(self.refPaths[selected.row()])

        self.backend.update_refs(selectedRefPaths)
        wordCloudDraw = self.backend.drawWordCloud()

        # binary
        biWordCloudDraw = wordCloudDraw.to_array()

        x = biWordCloudDraw.shape[1]
        y = biWordCloudDraw.shape[0]
        channel = biWordCloudDraw.shape[2]
        frame = QImage(biWordCloudDraw, x, y, QImage.Format_RGB888)
        pix = QPixmap.fromImage(frame)
        scene = QGraphicsScene()
        item = QGraphicsPixmapItem(pix)
        scene.addItem(item)

        self.window.wordCloudView.setScene(scene)

        def fit_view():
            self.window.wordCloudView.fitInView(item)

        def save_image():
            wordCloudDraw.to_file('wc.png')

        rezoom = QAction(self.window.wordCloudView)
        rezoom.setText('Rezoom')
        rezoom.triggered.connect(fit_view)

        save = QAction(self.window.wordCloudView)
        save.setText('Save')
        save.triggered.connect(save_image)

        self.window.wordCloudView.addAction(rezoom)
        self.window.wordCloudView.addAction(save)
Esempio n. 4
0
class SpectrogramViewer(QtWidgets.QWidget, Ui_SpectrogramViewer):

    seek = QtCore.Signal(float)
    spectrogram_drawn = QtCore.Signal()

    def __init__(self, parent=None, audio=None, settings=None):
        super().__init__(parent)
        self.setupUi(self)
        self.bg_image = None
        self.spectrogram_scene = QGraphicsScene(self)

        self._audio = None
        self._spectrogram = None
        self._image_generator = None

        self.sound_marker = None
        self.marker_position = 0
        self.yscale = 1

        self.settings = settings

        self.audio = audio
        self.setup_graphics_view()
        self.define_shortcuts()
        self.install_filters()

    def setup_graphics_view(self):
        self.spectrogram_view.setScene(self.spectrogram_scene)

    def define_shortcuts(self):
        QtGui.QShortcut(
            QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_Plus), self,
            self.zoom_in)
        QtGui.QShortcut(
            QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_Minus),
            self,
            self.zoom_out,
        )

    def install_filters(self):
        self.mouse_filter = SpectrogramMouseFilter(self)
        self.spectrogram_scene.installEventFilter(self.mouse_filter)

    @property
    def audio(self):
        return self._audio

    @audio.setter
    def audio(self, audio):
        if audio is not None:
            self._audio = audio
            self.spectrogram = Spectrogram(audio, self.spectrogram_options)
            self.marker_position = 0

    @property
    def spectrogram(self):
        return self._spectrogram

    @spectrogram.setter
    def spectrogram(self, spectrogram):
        self._spectrogram = spectrogram
        self.display_spectrogram()

    @property
    def image_options(self):
        return self.settings.image_options if self.settings else {}

    @property
    def spectrogram_options(self):
        return self.settings.spectrogram_options if self.settings else {}

    @property
    def image_generator(self):
        if self._image_generator is None:
            self._image_generator = ImageGenerator(self.image_options)
        return self._image_generator

    def display_spectrogram(self):
        # TODO: save image somewhere
        im = self.image_generator.spec2img(self.spectrogram)
        # TODO: change events when checkbox is checked
        # if self.checkbox_draw_events.isChecked():
        #     im = self.draw_events(im, max_duration)
        img = ImageQt.ImageQt(im)
        pixmap = QtGui.QPixmap.fromImage(img)

        # Change Qt array to a Qt graphic
        self.bg_image = QGraphicsPixmapItem(pixmap)
        self.spectrogram_scene.clear()
        self.spectrogram_scene.addItem(self.bg_image)
        # Ensure spectrogram graphic is displayed as background
        self.bg_image.setZValue(-100)
        self.bg_image.setPos(0, 0)
        self.sound_marker = None
        if self.marker_position:
            self.update_sound_marker(None)
        self.spectrogram_drawn.emit()

    def display_text(self, text):
        text_item = QGraphicsTextItem()
        text_item.setPos(150, 100)
        text_item.setPlainText(text)
        self.spectrogram_scene.clear()
        self.spectrogram_scene.addItem(text_item)

    def update_sound_marker(self, position_sec):
        # 100 # multiply by step-size in SpecGen()
        if position_sec is not None:
            self.marker_position = self.image_generator.sec2pixels(
                position_sec)
        line = QtCore.QLineF(
            self.marker_position,
            0,
            self.marker_position,
            self.image_generator["height"],
        )
        if not self.sound_marker:
            penCol = QtGui.QColor()
            penCol.setRgb(255, 0, 0)
            self.sound_marker = self.spectrogram_scene.addLine(
                line, QtGui.QPen(penCol))
        else:
            self.sound_marker.setLine(line)

        self.spectrogram_scene.update()

        if self.spectrogram_options["follow_sound"]:
            self.center_view()

    def center_view(self):
        self.spectrogram_view.centerOn(self.marker_position,
                                       self.get_center().y())

    def zoom(self, scale, scene_pos=None):
        self.yscale *= scale
        self.spectrogram_view.scale(scale, scale)
        if scene_pos:
            self.spectrogram_view.centerOn(scene_pos)

    def zoom_in(self):
        self.zoom(1.5)

    def zoom_out(self):
        self.zoom(0.75)

    def seek_sound(self, pos):
        self.seek.emit(self.image_generator.pixels2sec(pos))

    def update_spectrogram(self, option, redraw):
        if redraw:
            self.spectrogram = Spectrogram(self.audio,
                                           self.spectrogram_options)
            self.freq2pixels(6000)

    def update_image(self, option, redraw):
        if redraw:
            self.display_spectrogram()

    def get_center(self):
        return self.spectrogram_view.mapToScene(
            self.spectrogram_view.viewport().rect().center())

    def clear_rects(self):
        items = self.spectrogram_scene.items()
        for item in items:
            if isinstance(item, AnnotatedRectItem):
                self.spectrogram_scene.removeItem(item)

    def freq2pixels(self, freq):
        res = 0
        if self.spectrogram["scale"] == "Linear":
            height = self.image_generator["height"]
            max_freq = self.audio.sr / 2
            freq_step = height / max_freq
            res = height - (freq * freq_step)
        else:
            print("Only linear scale is supported so far")

        return res

    def draw_annotation(self, opts):
        x1 = self.image_generator.sec2pixels(opts.get("start", 0))
        x2 = self.image_generator.sec2pixels(opts.get("end", 0))
        y1 = self.freq2pixels(opts.get("max_freq", 0))
        y2 = self.freq2pixels(opts.get("min_freq", 0))
        text = opts.get("text", "")
        buffer = opts.get("vertical_buffer", 1)
        top_offset = opts.get("top_offset", 0)
        bottom_offset = opts.get("bottom_offset", 0)

        if y2 - y1 <= 0:
            y1 = 0
            y2 = self.spectrogram_scene.height() - 2
            if buffer:
                v_offset = buffer * y2 / 100
                y1 += v_offset + top_offset
                y2 -= v_offset - bottom_offset
                if text:
                    font = QtGui.QFont(opts.get("text_font", ""),
                                       opts.get("text_fontsize", 12))
                    font_height = QtGui.QFontMetrics(font).height()
                    y1 += font_height

        coords = (x1, y1, x2 - x1, y2 - y1)

        opts["coords"] = coords

        rect = AnnotatedRectItem(opts)

        self.spectrogram_scene.addItem(rect)

    def draw_rect(self,
                  start,
                  end,
                  y=0,
                  height=-1,
                  color="#ffffff",
                  fill="",
                  buffer=1):
        x = self.image_generator.sec2pixels(start)
        width = self.image_generator.sec2pixels(end - start)
        if height == -1:
            height = self.spectrogram_scene.height() - 2
        rect = QtWidgets.QGraphicsRectItem()
        rect.setPen(QtGui.QPen(color))
        if fill is not None:
            if not fill:
                fill = color
            rect.setBrush(QtGui.QBrush(fill, QtCore.Qt.SolidPattern))
        if buffer:
            y += buffer * height / 100
            height -= buffer * height / 100
        rect.setRect(x, y, width, height)
        self.spectrogram_scene.addItem(rect)
Esempio n. 5
0
class QtImg(QtWidgets.QWidget, Ui_Img):
    def __init__(self):
        super(self.__class__, self).__init__()
        Ui_Img.__init__(self)
        self.setupUi(self)
        self.bookId = ""
        self.epsId = 0
        self.curIndex = 0
        self.setWindowTitle("IMG")
        self.setWindowModality(QtCore.Qt.ApplicationModal)
        self.resize(800, 900)
        self.checkBox.setChecked(True)
        self.index = 0
        self.comboBox.setCurrentIndex(self.index)
        validator = QIntValidator(0, 9999999)
        self.heighEdit.setValidator(validator)
        self.widthEdit.setValidator(validator)
        exp = QDoubleValidator(0.1, 64, 1)
        exp.setNotation(exp.StandardNotation)
        self.scaleEdit.setValidator(exp)
        # self.setWindowFlags(Qt.FramelessWindowHint)

        self.graphicsView.setFrameStyle(QFrame.NoFrame)
        self.graphicsView.setObjectName("graphicsView")

        self.graphicsView.setBackgroundBrush(QColor(Qt.white))
        self.graphicsView.setCursor(Qt.OpenHandCursor)
        self.graphicsView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.graphicsView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.graphicsView.setRenderHints(QPainter.Antialiasing |
                                         QPainter.SmoothPixmapTransform)
        self.graphicsView.setCacheMode(self.graphicsView.CacheBackground)
        self.graphicsView.setViewportUpdateMode(self.graphicsView.SmartViewportUpdate)

        self.graphicsItem = QGraphicsPixmapItem()
        self.graphicsItem.setFlags(QGraphicsPixmapItem.ItemIsFocusable |
                                   QGraphicsPixmapItem.ItemIsMovable)
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.CopyPicture)

        self.graphicsScene = QGraphicsScene(self)  # 场景
        self.graphicsView.setScene(self.graphicsScene)
        self.graphicsScene.addItem(self.graphicsItem)
        self.graphicsView.setMinimumSize(10, 10)
        self.pixMap = QPixmap("Loading")
        self.graphicsItem.setPixmap(self.pixMap)
        # self.radioButton.setChecked(True)
        self.isStripModel = False

        # self.radioButton.installEventFilter(self)
        # self.radioButton_2.installEventFilter(self)
        self.graphicsView.installEventFilter(self)
        self.graphicsView.setWindowFlag(Qt.FramelessWindowHint)
        # tta有BUG,暂时屏蔽 TODO
        # self.ttaModel.setEnabled(False)
        self.data = b""
        self.waifu2xData = b""

        self._delta = 0.1
        self.scaleCnt = 0

        self.backStatus = ""
        self.format = ""

    def ShowImg(self, data):
        if data:
            self.data = data
            self.waifu2xData = b""
            QtTask().CancelConver("QtImg")
            self._ShowImg(data)
        elif self.data:
            self._ShowImg(self.data)
        else:
            pass

    def _ShowImg(self, data):
        self.scaleCnt = 0
        self.pixMap = QPixmap()
        self.pixMap.loadFromData(data)
        self.show()
        self.graphicsItem.setPixmap(self.pixMap)
        self.graphicsView.setSceneRect(QRectF(QPointF(0, 0), QPointF(self.pixMap.width(), self.pixMap.height())))
        size = ToolUtil.GetDownloadSize(len(data))
        self.sizeLabel.setText(size)
        weight, height = ToolUtil.GetPictureSize(data)
        self.resolutionLabel.setText(str(weight) + "x" + str(height))
        self.ScalePicture()

    def ScalePicture(self):
        rect = QRectF(self.graphicsItem.pos(), QSizeF(
            self.pixMap.size()))
        unity = self.graphicsView.transform().mapRect(QRectF(0, 0, 1, 1))
        width = unity.width()
        height = unity.height()
        if width <= 0 or height <= 0:
            return
        self.graphicsView.scale(1 / width, 1 / height)
        viewRect = self.graphicsView.viewport().rect()
        sceneRect = self.graphicsView.transform().mapRect(rect)
        if sceneRect.width() <= 0 or sceneRect.height() <= 0:
            return
        x_ratio = viewRect.width() / sceneRect.width()
        y_ratio = viewRect.height() / sceneRect.height()
        x_ratio = y_ratio = min(x_ratio, y_ratio)

        self.graphicsView.scale(x_ratio, y_ratio)
        # if self.readImg.isStripModel:
        #     height2 = self.pixMap.size().height() / 2
        #     height3 = self.graphicsView.size().height()/2
        #     height3 = height3/x_ratio
        #     p = self.graphicsItem.pos()
        #     self.graphicsItem.setPos(p.x(), p.y()+height2-height3)
        self.graphicsView.centerOn(rect.center())

        for _ in range(abs(self.scaleCnt)):
            if self.scaleCnt > 0:
                self.graphicsView.scale(1.1, 1.1)
            else:
                self.graphicsView.scale(1/1.1, 1/1.1)

    def resizeEvent(self, event) -> None:
        super(self.__class__, self).resizeEvent(event)
        self.ScalePicture()

    def eventFilter(self, obj, ev):
        if ev.type() == QEvent.KeyPress:
            return True
        else:
            return super(self.__class__, self).eventFilter(obj, ev)

    def wheelEvent(self, event):
        if event.angleDelta().y() > 0:
            self.zoomIn()
        else:
            self.zoomOut()

    def zoomIn(self):
        """放大"""
        self.zoom(1.1)

    def zoomOut(self):
        """缩小"""
        self.zoom(1/1.1)

    def zoom(self, factor):
        """缩放
        :param factor: 缩放的比例因子
        """
        _factor = self.graphicsView.transform().scale(
            factor, factor).mapRect(QRectF(0, 0, 1, 1)).width()
        if _factor < 0.07 or _factor > 100:
            # 防止过大过小
            return
        if factor >= 1:
            self.scaleCnt += 1
        else:
            self.scaleCnt -= 1
        self.graphicsView.scale(factor, factor)

    def CopyPicture(self):
        clipboard = QApplication.clipboard()
        clipboard.setPixmap(self.pixMap)
        QtBubbleLabel.ShowMsgEx(self, "Copy Success")
        return

    def ReduceScalePic(self):
        self.zoom(1/1.1)
        return

    def AddScalePic(self):
        self.zoom(1.1)
        return

    def OpenPicture(self):
        try:
            filename = QFileDialog.getOpenFileName(self, "Open Image", ".", "Image Files(*.jpg *.png)")
            if filename and len(filename) >= 1:
                name = filename[0]
                if os.path.isfile(name):
                    f = open(name, "rb")
                    data = f.read()
                    f.close()
                    self.ShowImg(data)
        except Exception as ex:
            Log.Error(ex)
        return

    def StartWaifu2xPng(self):
        if self.StartWaifu2x("png"):
            self.format = "png"
            self.changeJpg.setEnabled(False)
            self.changePng.setEnabled(False)
        return

    def StartWaifu2xJPG(self):
        if self.StartWaifu2x("jpg"):
            self.format = "jpg"
            self.changeJpg.setEnabled(False)
            self.changePng.setEnabled(False)
        return

    def StartWaifu2x(self, format):
        if not self.data:
            return False
        if not config.CanWaifu2x:
            return False
        from waifu2x_vulkan import waifu2x_vulkan
        self.SetStatus(False)
        self.index = self.comboBox.currentIndex()
        index = self.comboBox.currentIndex()
        noise = int(self.noiseCombox.currentText())
        if index == 0:
            modelName = "CUNET"
        elif index == 1:
            modelName = "PHOTO"
        elif index == 2:
            modelName = "ANIME_STYLE_ART_RGB"
        else:
            return False
        if noise == -1:
            noiseName = "NO_NOISE"
        else:
            noiseName = "NOISE"+str(noise)
        if modelName == "CUNET" and self.scaleRadio.isChecked() and round(float(self.scaleEdit.text()), 1) <= 1:
            modelInsence = "MODEL_{}_NO_SCALE_{}".format(modelName, noiseName)
        else:
            modelInsence = "MODEL_{}_{}".format(modelName, noiseName)
        if self.ttaModel.isChecked():
            modelInsence += "_TTA"

        model = {
            "model":  getattr(waifu2x_vulkan, modelInsence),
        }
        if self.scaleRadio.isChecked():
            model['scale'] = round(float(self.scaleEdit.text()), 1)
        else:
            model['width'] = int(self.widthEdit.text())
            model['high'] = int(self.heighEdit.text())
        model['format'] = format
        self.backStatus = self.GetStatus()
        QtTask().AddConvertTask(self.data, model, self.AddConvertBack,
                                cleanFlag="QtImg")
        self.changeLabel.setText(self.tr("正在转换"))
        return True

    def AddConvertBack(self, data, waifuId, backParam, tick):
        if data:
            self.waifu2xData = data
            if self.checkBox.isChecked():
                self._ShowImg(data)
            self.changeLabel.setText(self.tr("已转换"))
            self.tickLabel.setText(str(round(tick, 3)) + "s")

        else:
            self.changeLabel.setText(self.tr("失败"))
        self.SetStatus(True)
        return

    def CheckHideButton(self):
        if self.format == "":
            self.changePng.setEnabled(True)
            self.changeJpg.setEnabled(True)
        elif self.format == "png":
            self.changePng.setEnabled(False)
            self.changeJpg.setEnabled(True)
        else:
            self.changePng.setEnabled(True)
            self.changeJpg.setEnabled(False)

    def SavePicture(self):
        data = self.waifu2xData if self.waifu2xData else self.data
        if not data:
            return
        try:
            today = time.strftime("%Y%m%d%H%M%S", time.localtime(time.time()))
            picFormat = self.format if self.format else "jpg"
            filepath = QFileDialog.getSaveFileName(self, "Save", "{}.{}".format(today, picFormat))
            if filepath and len(filepath) >= 1 and filepath[0]:
                name = filepath[0]
                f = open(name, "wb")
                f.write(data)
                f.close()
        except Exception as es:
            Log.Error(es)
        return

    def SwithPicture(self):
        if self.checkBox.isChecked() and self.waifu2xData:
            self._ShowImg(self.waifu2xData)
        else:
            self._ShowImg(self.data)
        return

    def ChangeModel(self, index):
        # self.index = self.comboBox.currentIndex()
        self.CheckScaleRadio()
        return

    def GetStatus(self):
        data = str(self.noiseCombox.currentText()) + \
            str(self.buttonGroup_2.checkedId()) + \
            str(self.scaleEdit.text()) + \
            str(self.heighEdit.text()) + \
            str(int(self.ttaModel.isChecked())) + \
            str(self.widthEdit.text()) + \
            str(self.comboBox.currentIndex())
        return data

    def SetStatus(self, status):
        self.scaleRadio.setEnabled(status)
        self.heighRadio.setEnabled(status)
        self.scaleEdit.setEnabled(status)
        self.widthEdit.setEnabled(status)
        self.heighEdit.setEnabled(status)
        self.noiseCombox.setEnabled(status)
        self.comboBox.setEnabled(status)
        # self.radioButton_4.setEnabled(status)
        # self.radioButton_5.setEnabled(status)
        # self.radioButton_6.setEnabled(status)
        # self.radioButton_7.setEnabled(status)
        # self.radioButton_8.setEnabled(status)
        # self.ttaModel.setEnabled(status)
        self.CheckScaleRadio()

    def SetEnable(self):
        self.SetStatus(True)

    def SetDisEnable(self):
        self.SetStatus(False)

    def CheckScaleRadio(self):
        if self.scaleRadio.isChecked() and self.scaleRadio.isEnabled():
            self.scaleEdit.setEnabled(True)
            self.widthEdit.setEnabled(False)
            self.heighEdit.setEnabled(False)
        elif self.heighRadio.isChecked() and self.heighRadio.isEnabled():
            self.scaleEdit.setEnabled(False)
            self.widthEdit.setEnabled(True)
            self.heighEdit.setEnabled(True)
        data = self.GetStatus()
        if self.backStatus != data:
            self.changePng.setEnabled(True)
            self.changeJpg.setEnabled(True)
        else:
            self.CheckHideButton()
Esempio n. 6
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.art_scene = QGraphicsScene(self)
        self.art_scene.addText('Open an image file.')
        self.ui.art_view.setScene(self.art_scene)
        self.symbols_scene = QGraphicsScene(self)
        self.ui.symbols_view.setScene(self.symbols_scene)
        self.ui.action_exit.triggered.connect(self.close)
        self.ui.action_open_art.triggered.connect(self.open_image)
        self.ui.action_open_words.triggered.connect(self.open_words)
        self.ui.action_save.triggered.connect(self.save_pdf)
        self.ui.action_save_png.triggered.connect(self.save_png)
        self.ui.action_shuffle.triggered.connect(self.shuffle)
        self.ui.action_sort.triggered.connect(self.sort)
        self.ui.rows.valueChanged.connect(self.on_options_changed)
        self.ui.columns.valueChanged.connect(self.on_options_changed)
        self.ui.word_clues_radio.toggled.connect(self.on_options_changed)
        self.ui.symbol_clues_radio.toggled.connect(self.on_options_changed)

        self.word_layout = QGridLayout(self.ui.word_content)
        self.ui.word_scroll.setWidgetResizable(True)
        self.word_labels: typing.Dict[str, QLabel] = {}
        self.word_shuffler = WordShuffler([])

        self.clues = None

        self.pixmap = self.scaled_pixmap = self.mini_pixmap = None
        self.sliced_pixmap_item: typing.Optional[QGraphicsPixmapItem] = None
        self.sliced_image: typing.Optional[QImage] = None
        self.selection_grid: typing.Optional[SelectionGrid] = None
        self.cells = []
        self.art_shuffler: typing.Optional[ArtShuffler] = None
        self.symbols_source_pixmap_item: typing.Optional[
            QGraphicsPixmapItem] = None
        self.symbols_pixmap_item: typing.Optional[QGraphicsPixmapItem] = None
        self.symbols_image: typing.Optional[QImage] = None
        self.symbols_shuffler: typing.Optional[ArtShuffler] = None
        self.selected_row: typing.Optional[int] = None
        self.selected_column: typing.Optional[int] = None
        self.settings = QSettings()
        self.image_path: typing.Optional[str] = self.settings.value(
            'image_path')
        self.words_path: typing.Optional[str] = self.settings.value(
            'words_path')

        self.dirty_letters = set()
        self.timer = QTimer()
        self.timer.setInterval(500)
        self.timer.setSingleShot(True)
        # noinspection PyUnresolvedReferences
        self.timer.timeout.connect(self.on_dirty)

        self.row_count = self.column_count = 0
        self.clue_type = ClueType.words
        self.ui.rows.setValue(self.settings.value('row_count', 6, int))
        self.ui.columns.setValue(self.settings.value('column_count', 4, int))
        clue_type_name = self.settings.value('clue_type', ClueType.words.name)
        try:
            clue_type = ClueType[clue_type_name]
        except KeyError:
            clue_type = ClueType.words
        if clue_type == ClueType.words:
            self.ui.word_clues_radio.setChecked(True)
        else:
            self.ui.symbol_clues_radio.setChecked(True)
        self.row_clues: typing.List[QPixmap] = []
        self.column_clues: typing.List[QPixmap] = []
        self.on_options_changed()

    def on_dirty(self):
        for letter in self.dirty_letters:
            self.word_labels[letter].setText(
                self.word_shuffler.make_display(letter))
            self.settings.setValue(f'word_{letter}',
                                   self.word_shuffler[letter])
        if self.dirty_letters:
            self.clues = self.word_shuffler.make_clues()
            self.art_shuffler.clues = dict(self.clues)
            self.dirty_letters.clear()
            self.on_selection_moved()

        if self.pixmap is not None:
            x, y, width, height = self.get_selected_fraction()
            self.settings.setValue('x', x)
            self.settings.setValue('y', y)
            self.settings.setValue('width', width)
            self.settings.setValue('height', height)

        new_rows = self.ui.rows.value()
        new_columns = self.ui.columns.value()
        if self.ui.word_clues_radio.isChecked():
            new_clue_type = ClueType.words
        else:
            new_clue_type = ClueType.symbols
        if (new_rows, new_columns,
                new_clue_type) == (self.row_count, self.column_count,
                                   self.clue_type):
            return
        self.settings.setValue('row_count', new_rows)
        self.settings.setValue('column_count', new_columns)
        self.settings.setValue('clue_type', new_clue_type.name)
        self.row_count, self.column_count = new_rows, new_columns
        self.clue_type = new_clue_type

        word_count = (self.row_count * self.column_count)
        while self.word_layout.count():
            layout_item = self.word_layout.takeAt(0)
            layout_item.widget().deleteLater()
        self.word_labels.clear()

        self.row_clues.clear()
        self.column_clues.clear()
        if self.image_path is not None:
            self.load_image(self.image_path)

        if self.words_path is not None:
            self.load_words(self.words_path)

        letters = [chr(65 + i) for i in range(word_count)]
        if self.word_shuffler.needs_blank:
            letters.insert(0, '')
        word_fields = {}
        for i, letter in enumerate(letters):
            word_field = QLineEdit()
            self.word_layout.addWidget(word_field, i, 0)
            # noinspection PyUnresolvedReferences
            word_field.textEdited.connect(partial(self.on_word_edited, letter))

            word_label = QLabel()
            self.word_layout.addWidget(word_label, i, 1)
            self.word_labels[letter] = word_label
            word_fields[letter] = word_field
        for i, letter in enumerate(letters):
            word = self.settings.value(f'word_{letter}', '')
            self.word_shuffler[letter] = word
            self.dirty_letters.add(letter)
            word_fields[letter].setText(word)

    def on_options_changed(self, *_):
        self.timer.start()

    def shuffle(self):
        self.clues = self.word_shuffler.make_clues()
        if self.art_shuffler is not None:
            self.art_shuffler.shuffle()
            self.on_selection_moved()

    def sort(self):
        if self.art_shuffler is not None:
            self.art_shuffler.sort()
            self.on_selection_moved()

    def open_words(self):
        word_filter = 'Text files (*.txt)'
        if self.words_path is None:
            words_folder = None
        else:
            words_folder = str(Path(self.words_path).parent)
        file_name, _ = QFileDialog.getOpenFileName(self,
                                                   "Open a words file.",
                                                   dir=words_folder,
                                                   filter=word_filter)
        if not file_name:
            return
        self.settings.setValue('words_path', file_name)
        self.load_words(file_name)

    def load_words(self, words_path):
        with open(words_path) as f:
            choice = 0
            if choice == 0:
                self.word_shuffler = WordShuffler(f)
            else:
                self.word_shuffler = WordStripper(f)

    def open_image(self):
        formats = QImageReader.supportedImageFormats()
        patterns = (f'*.{fmt.data().decode()}' for fmt in formats)
        image_filter = f'Images ({" ".join(patterns)})'
        if self.image_path is None:
            image_folder = None
        else:
            image_folder = str(Path(self.image_path).parent)
        file_name, _ = QFileDialog.getOpenFileName(self,
                                                   "Open an image file.",
                                                   dir=image_folder,
                                                   filter=image_filter)
        if not file_name:
            return
        self.settings.setValue('image_path', file_name)
        self.load_image(file_name)

    def load_image(self, image_path):
        self.pixmap = QPixmap(image_path)
        if self.pixmap.isNull():
            self.pixmap = None
        self.image_path = image_path
        self.scale_image()

    def scale_image(self):
        if self.pixmap is None:
            return

        if self.selection_grid is None:
            x = self.settings.value('x', 0.0, float)
            y = self.settings.value('y', 0.0, float)
            width = self.settings.value('width', 1.0, float)
            height = self.settings.value('height', 1.0, float)
        else:
            x, y, width, height = self.get_selected_fraction()
        self.art_scene.clear()
        self.cells.clear()
        view_size = self.ui.art_view.maximumViewportSize()
        if view_size.width() == 0:
            return
        self.art_scene.setSceneRect(0, 0, view_size.width(),
                                    view_size.height())
        display_size = QSize(view_size.width() * 0.99 / 2,
                             view_size.height() * 0.99)
        self.scaled_pixmap = self.pixmap.scaled(
            display_size, aspectMode=Qt.AspectRatioMode.KeepAspectRatio)
        self.art_scene.addPixmap(self.scaled_pixmap)
        scaled_size = self.scaled_pixmap.size()
        self.selection_grid = SelectionGrid(scaled_size.width() * x,
                                            scaled_size.height() * y,
                                            scaled_size.width() * width,
                                            scaled_size.height() * height,
                                            row_count=self.row_count,
                                            column_count=self.column_count)
        self.selection_grid.on_moved = self.on_selection_moved
        self.art_scene.addItem(self.selection_grid)
        self.sliced_image = QImage(display_size,
                                   QImage.Format.Format_ARGB32_Premultiplied)
        self.check_clues()
        self.art_shuffler = ArtShuffler(self.selection_grid.row_count,
                                        self.selection_grid.column_count,
                                        self.sliced_image,
                                        QRect(0, 0, display_size.width(),
                                              display_size.height()),
                                        clues=self.clues,
                                        row_clues=self.row_clues,
                                        column_clues=self.column_clues)
        self.sliced_pixmap_item = self.art_scene.addPixmap(
            QPixmap.fromImage(self.sliced_image))
        self.sliced_pixmap_item.setPos(display_size.width(), 0)

        self.symbols_scene.clear()
        self.symbols_source_pixmap_item = self.symbols_scene.addPixmap(
            self.scaled_pixmap)
        self.symbols_image = QImage(display_size,
                                    QImage.Format.Format_ARGB32_Premultiplied)
        if self.symbols_shuffler is not None:
            selected_row = self.symbols_shuffler.selected_row
            selected_column = self.symbols_shuffler.selected_column
        else:
            selected_row = 0
            selected_column = None
        self.symbols_shuffler = ArtShuffler(self.selection_grid.row_count,
                                            self.selection_grid.column_count,
                                            self.symbols_image,
                                            QRect(0, 0, display_size.width(),
                                                  display_size.height()),
                                            row_clues=self.row_clues,
                                            column_clues=self.column_clues)
        self.symbols_shuffler.selected_row = selected_row
        self.symbols_shuffler.selected_column = selected_column
        self.symbols_pixmap_item = ClickablePixmapItem(
            QPixmap.fromImage(self.symbols_image))
        self.symbols_pixmap_item.on_click = self.on_symbols_clicked
        self.symbols_scene.addItem(self.symbols_pixmap_item)

        self.symbols_pixmap_item.setPos(display_size.width(), 0)

        self.on_selection_moved()

    def on_symbols_clicked(self, event: QGraphicsSceneMouseEvent):
        self.symbols_scene.clearSelection()
        self.symbols_shuffler.select_clue(event.pos().toPoint())
        self.on_selection_moved()

    def on_word_edited(self, letter, word):
        self.word_shuffler[letter] = word
        self.dirty_letters.add(letter)
        self.timer.start()

    def get_selected_fraction(self):
        selection_rect = self.selection_grid.rect()
        selection_pos = self.selection_grid.pos()
        size = self.scaled_pixmap.size()
        x = (selection_pos.x() + selection_rect.x()) / size.width()
        width = selection_rect.width() / size.width()
        y = (selection_pos.y() + selection_rect.y()) / size.height()
        height = selection_rect.height() / size.height()
        return x, y, width, height

    def on_selection_moved(self):
        selected_pixmap = self.get_selected_pixmap()
        self.art_shuffler.draw(selected_pixmap)
        self.sliced_pixmap_item.setPixmap(QPixmap.fromImage(self.sliced_image))

        selected_pixmap = self.get_selected_pixmap()
        cell_width = (selected_pixmap.width() /
                      self.selection_grid.column_count)
        cell_height = (selected_pixmap.height() /
                       self.selection_grid.row_count)
        self.row_clues.clear()
        self.column_clues.clear()
        for i in range(self.selection_grid.row_count):
            clue_image = selected_pixmap.copy(0, i * cell_height, cell_width,
                                              cell_height)
            self.row_clues.append(clue_image)
        for j in range(self.selection_grid.column_count):
            clue_image = selected_pixmap.copy(j * cell_width, 0, cell_width,
                                              cell_height)
            self.column_clues.append(clue_image)
        self.symbols_shuffler.row_clues = self.row_clues
        self.symbols_shuffler.column_clues = self.column_clues

        self.symbols_shuffler.draw_grid(selected_pixmap)
        self.symbols_pixmap_item.setPixmap(
            QPixmap.fromImage(self.symbols_image))
        self.timer.start()

    def get_selected_pixmap(self) -> QPixmap:
        x, y, width, height = self.get_selected_fraction()
        original_size = self.pixmap.size()
        selected_pixmap = self.pixmap.copy(x * original_size.width(),
                                           y * original_size.height(),
                                           width * original_size.width(),
                                           height * original_size.height())
        return selected_pixmap

    def resizeEvent(self, event: QResizeEvent):
        super().resizeEvent(event)
        self.scale_image()

    def save_pdf(self):
        pdf_folder = self.settings.value('pdf_folder')
        file_name, _ = QFileDialog.getSaveFileName(self,
                                                   "Save a PDF file.",
                                                   dir=pdf_folder,
                                                   filter='Documents (*.pdf)')
        if not file_name:
            return
        self.settings.setValue('pdf_folder', os.path.dirname(file_name))
        writer = QPdfWriter(file_name)
        writer.setPageSize(QPageSize(QPageSize.Letter))
        writer.setTitle('Sliced Art Puzzle')
        writer.setCreator('Don Kirkby')
        self.paint_puzzle(writer)

    def save_png(self):
        pdf_folder = self.settings.value('pdf_folder')
        file_name, _ = QFileDialog.getSaveFileName(self,
                                                   "Save an image file.",
                                                   dir=pdf_folder,
                                                   filter='Images (*.png)')
        if not file_name:
            return
        writer = QPixmap(1000, 2000)
        self.paint_puzzle(writer)
        writer.save(file_name)
        self.settings.setValue('pdf_folder', os.path.dirname(file_name))

    def paint_puzzle(self, writer: QPaintDevice):
        self.check_clues()
        painter = QPainter(writer)
        try:
            print_shuffler = ArtShuffler(self.art_shuffler.rows,
                                         self.art_shuffler.cols,
                                         writer,
                                         QRect(0, 0, writer.width(),
                                               round(writer.height() / 2)),
                                         clues=self.clues,
                                         row_clues=self.row_clues,
                                         column_clues=self.column_clues)
            print_shuffler.cells = self.art_shuffler.cells[:]
            print_shuffler.is_shuffled = self.art_shuffler.is_shuffled
            selected_pixmap = self.get_selected_pixmap()
            print_shuffler.draw(selected_pixmap, painter)

            print_shuffler.rect.moveTop(writer.height() / 2)
            print_shuffler.draw_grid(selected_pixmap, painter)
        finally:
            painter.end()

    def check_clues(self):
        if self.clue_type == ClueType.words:
            if self.clues is None:
                self.clues = self.word_shuffler.make_clues()
            self.row_clues.clear()
            self.column_clues.clear()
        else:
            self.clues = None
Esempio n. 7
0
class QRScanner(QWidget):
    QR_SIZE = 0.75  # Size of rectangle for QR capture
    readyForCapture = Signal(bool)
    decodedQR = Signal(str)

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.processing = False
        self.rectangle = None

        self.setMinimumHeight(405)
        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.scene = QGraphicsScene(self)
        self.scene.setBackgroundBrush(QBrush(Qt.black))
        self.view = QGraphicsView(self.scene)
        self.viewfinder = QGraphicsVideoItem()
        self.scene.addItem(self.viewfinder)
        self.layout.addWidget(self.view)
        self.setLayout(self.layout)

        self.camera = None
        self.captureSession = None
        self.imageCapture = None
        self.captureTimer = None

    def startScan(self):
        if len(QMediaDevices.videoInputs()) == 0:
            logging.warning(self.tr("There are no cameras available"))
            return

        self.processing = True  # disable any capture while camera is starting
        self.camera = QCamera(QMediaDevices.defaultVideoInput())
        self.captureSession = QMediaCaptureSession()
        self.imageCapture = QImageCapture(self.camera)
        self.captureSession.setCamera(self.camera)
        self.captureSession.setVideoOutput(self.viewfinder)
        self.captureSession.setImageCapture(self.imageCapture)

        self.camera.errorOccurred.connect(self.onCameraError)
        self.readyForCapture.connect(self.onReadyForCapture)
        self.imageCapture.errorOccurred.connect(self.onCaptureError)
        self.imageCapture.readyForCaptureChanged.connect(
            self.onReadyForCapture)
        self.imageCapture.imageCaptured.connect(self.onImageCaptured)
        self.viewfinder.nativeSizeChanged.connect(self.onVideoSizeChanged)

        self.camera.start()
        self.processing = False
        self.readyForCapture.emit(self.imageCapture.isReadyForCapture())

    def stopScan(self):
        if self.camera is None:
            return
        self.processing = True  # disable capture
        self.camera.stop()

        self.camera = None
        self.captureSession = None
        self.imageCapture = None
        self.captureTimer = None

    def onVideoSizeChanged(self, _size):
        self.resizeEvent(None)

    # Take QImage or QRect (object with 'width' and 'height' properties and calculate position and size
    # of the square with side of self.QR_SIZE from minimum of height or width
    def calculate_center_square(self, img_rect) -> QRectF:
        a = self.QR_SIZE * min(img_rect.height(),
                               img_rect.width())  # Size of square side
        x = (img_rect.width() -
             a) / 2  # Position of the square inside rectangle
        y = (img_rect.height() - a) / 2
        if type(img_rect
                ) != QImage:  # if we have a bounding rectangle, not an image
            x += img_rect.left(
            )  # then we need to shift our square inside this rectangle
            y += img_rect.top()
        return QRectF(x, y, a, a)

    def resizeEvent(self, event):
        bounds = self.scene.itemsBoundingRect()
        if bounds.width() <= 0 or bounds.height() <= 0:
            return  # do nothing if size is zero
        self.view.fitInView(bounds, Qt.KeepAspectRatio)
        if self.rectangle is not None:
            self.scene.removeItem(self.rectangle)
        pen = QPen(Qt.green)
        pen.setWidth(0)
        pen.setStyle(Qt.DashLine)
        self.rectangle = self.scene.addRect(
            self.calculate_center_square(bounds), pen)
        self.view.centerOn(0, 0)
        self.view.raise_()

    def onCaptureError(self, _id, error, error_str):
        self.processing = False
        self.onCameraError(error, error_str)

    def onCameraError(self, error, error_str):
        logging.error(
            self.tr("Camera error: " + str(error) + " / " + error_str))

    def onReadyForCapture(self, ready: bool):
        if ready and not self.processing:
            self.imageCapture.capture()
            self.processing = True

    def onImageCaptured(self, _id: int, img: QImage):
        self.decodeQR(img)
        self.processing = False
        if self.imageCapture is not None:
            self.readyForCapture.emit(self.imageCapture.isReadyForCapture())

    def decodeQR(self, qr_image: QImage):
        cropped = qr_image.copy(
            self.calculate_center_square(qr_image).toRect())
        # TODO: the same code is present in slips.py -> move to one place
        buffer = QBuffer()
        buffer.open(QBuffer.ReadWrite)
        cropped.save(buffer, "BMP")
        try:
            pillow_image = Image.open(io.BytesIO(buffer.data()))
        except UnidentifiedImageError:
            print("Image format isn't supported")
            return
        barcodes = pyzbar.decode(pillow_image,
                                 symbols=[pyzbar.ZBarSymbol.QRCODE])
        if barcodes:
            self.decodedQR.emit(barcodes[0].data.decode('utf-8'))