Esempio n. 1
0
class SynthPdfWidget(QWidget):
    def __init__(self, status_bar):
        super(SynthPdfWidget, self).__init__()
        self.status_bar = status_bar
        layout = QHBoxLayout()
        self.list_view = QListWidget()
        self.list_view.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.list_view.setAlternatingRowColors(True)
        self.list_view.itemClicked.connect(self.click_item_signal)
        self.list_view.itemEntered.connect(self.click_item_signal)
        self.list_view.itemSelectionChanged.connect(
            self.change_selection_signal)

        controls_layout = QVBoxLayout()
        controls_layout.setAlignment(Qt.AlignTop)

        select_zone = SelectWidget(self.click_move_up, self.click_move_down,
                                   self.click_invert, self.click_delete)
        select_zone.setMinimumWidth(250)

        add_pages_button = QPushButton("Add Pages From PDF")
        add_pages_button.clicked.connect(self.add_pdf)

        controls_layout.addWidget(select_zone)
        controls_layout.addWidget(add_pages_button)

        layout.addWidget(self.list_view)
        layout.addLayout(controls_layout)
        self.setLayout(layout)

    def _add_pages_from_pdf(self, pdf_path):
        with open(pdf_path, "rb") as file:
            reader = PdfFileReader(file)
            file_name = os.path.basename(pdf_path)
            pages_count = reader.getNumPages()
            for i in range(pages_count):
                new_item = ImageListItem(
                    "page " + str(i + 1) + " (" + file_name + ")",
                    (pdf_path, i))
                self.list_view.addItem(new_item)
            self.status_bar.showMessage("Add " + str(pages_count) + " pages")

    # ----------external methods from create command
    def extern_get_files_and_pages(
        self
    ):  # return selected pages in the form {file1: [p1, p2, ...], file2: [p1, p2, ...], ...}
        to_return = {}
        if len(self.list_view.selectedItems()
               ) == 0:  # nothing selected, add all pages
            items_count = self.list_view.count()
            for item_index in range(items_count):
                item = self.list_view.item(item_index)
                item_data = item.get_data()
                file_name = item_data[0]
                page_index = item_data[1]
                if file_name in to_return:
                    to_return[file_name].append(page_index)
                else:
                    to_return[file_name] = [page_index]
        else:
            for s in self.list_view.selectedItems():
                s_data = s.get_data()
                file_name = s_data[0]
                page_index = s_data[1]
                if file_name in to_return:
                    to_return[file_name].append(page_index)
                else:
                    to_return[file_name] = [page_index]
        return to_return

    # ----------add button-----------------------
    def add_pdf(self):
        files_dialog = QFileDialog()
        files_dialog.setNameFilter("PDF (*.pdf)")
        files_dialog.setFileMode(QFileDialog.ExistingFiles)
        if files_dialog.exec_():
            files = files_dialog.selectedFiles()
            for f_path in files:
                self._add_pages_from_pdf(f_path)

    # ----------List_view signals----------------
    def click_item_signal(self, item):
        self.status_bar.showMessage("Select " + str(item.text()))

    def change_selection_signal(self):
        if len(self.list_view.selectedItems()) == 0:
            # self._set_preview(None)  # nothing selected
            pass

    # ----------list_view commands---------------
    def click_move_up(self):
        selected = self.list_view.selectedItems()
        selected_indexes = [
            self.list_view.indexFromItem(sel).row() for sel in selected
        ]
        selected_indexes.sort()
        if len(selected_indexes) > 0 and selected_indexes[0] > 0:
            for index in selected_indexes:
                prev_item = self.list_view.takeItem(index - 1)
                self.list_view.insertItem(index, prev_item)
            self.status_bar.showMessage("Move " + str(len(selected_indexes)) +
                                        " items")
        else:
            self.status_bar.showMessage("Nothing to move")

    def click_move_down(self):
        selected = self.list_view.selectedItems()
        selected_indexes = [
            self.list_view.indexFromItem(sel).row() for sel in selected
        ]
        selected_indexes.sort()
        sel_count = len(selected_indexes)
        if len(selected_indexes) > 0 and selected_indexes[
                sel_count - 1] < self.list_view.count() - 1:
            for i_index in range(sel_count):
                next_item = self.list_view.takeItem(
                    selected_indexes[sel_count - i_index - 1] + 1)
                self.list_view.insertItem(
                    selected_indexes[sel_count - i_index - 1], next_item)
            self.status_bar.showMessage("Move " + str(len(selected_indexes)) +
                                        " items")
        else:
            self.status_bar.showMessage("Nothing to move")

    def click_invert(self):
        selected = self.list_view.selectedItems()
        selected_indexes = []
        for sel in selected:
            selected_indexes.append(self.list_view.indexFromItem(sel).row())
        total_indexes = [i for i in range(self.list_view.count())]
        new_indexes = []
        for i in total_indexes:
            if i not in selected_indexes:
                new_indexes.append(i)
        self.list_view.clearSelection()
        for i in new_indexes:
            self.list_view.item(i).setSelected(True)
        self.status_bar.showMessage("Invert selection: " + str(new_indexes))

    def click_delete(self):
        selected = self.list_view.selectedItems()
        delete_names = []
        for s in selected:
            s_index = self.list_view.indexFromItem(s).row()
            del_item = self.list_view.takeItem(s_index)
            delete_names.append(del_item.text())
        if len(delete_names) == 0:
            self.status_bar.showMessage("Nothing to delete")
        else:
            self.status_bar.showMessage("Delete items: " +
                                        ", ".join(delete_names))
Esempio n. 2
0
class ImageToPdfWidget(QWidget):
    def __init__(self, status_link):
        super(ImageToPdfWidget, self).__init__()
        LABEL_WIDTH = 80
        self.last_selected_items = []
        self.options_mode = 0
        self.update_status_combobox = False
        layout = QHBoxLayout()
        self.status_bar = status_link
        self.list_view = QListWidget()
        self.list_view.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.list_view.setAlternatingRowColors(True)
        self.list_view.itemClicked.connect(self.click_item_signal)
        self.list_view.itemEntered.connect(self.click_item_signal)
        self.list_view.itemSelectionChanged.connect(
            self.change_selection_signal)

        controls_layout = QVBoxLayout()
        controls_layout.setAlignment(Qt.AlignTop)

        select_zone = SelectWidget(self.click_move_up, self.click_move_down,
                                   self.click_invert, self.click_delete)

        # options zone -------------------------------------
        options_zone = QGroupBox("Options")
        self.options_zone_layout = QVBoxLayout()

        self.options_mode_combobox = QComboBox()
        self._add_items_to_mode_combobox(self.options_mode_combobox)
        options_mode_label = QLabel("Mode")
        options_mode_label.setMaximumWidth(LABEL_WIDTH)
        options_mode_layout = QHBoxLayout()
        options_mode_layout.addWidget(options_mode_label)
        options_mode_layout.addWidget(self.options_mode_combobox)
        self.options_zone_layout.addLayout(options_mode_layout)
        self.option_source_widget = OptionsFromSourceWidget(
            label_width=LABEL_WIDTH, status_bar=self.status_bar)
        self.options_a_widget = OptionsAWidget(label_width=LABEL_WIDTH,
                                               status_bar=self.status_bar)
        self.options_mode_combobox.currentIndexChanged.connect(
            self.change_options_mode_signal)
        self.change_options_mode_signal(self.options_mode)

        options_zone.setLayout(self.options_zone_layout)

        # Add files button and final structures ---------------------------
        add_file_button = QPushButton("Add Files")
        add_file_button.clicked.connect(self.click_add_files)
        controls_layout.addWidget(select_zone)
        controls_layout.addWidget(options_zone)
        controls_layout.addWidget(add_file_button)

        # image preview ---------------------------------------------------
        image_prev_layout = QVBoxLayout()
        image_prev_layout.setContentsMargins(0, 0, 4, 0)
        self.IMG_PREVIEW_WIDTH = 256
        self.img_label = QLabel()
        self.img_label.setAlignment(Qt.AlignCenter)
        self.select_text = "Click item to preview"
        self.last_created_pix_path = ""
        self.img_label.setText(self.select_text)
        image_prev_layout.addWidget(self.img_label)
        # slider for the preview scale
        self.img_scale_slider = QSlider()
        self.img_scale_slider.setMinimum(6)
        self.img_scale_slider.setMaximum(2048)
        self.img_scale_slider.setValue(self.IMG_PREVIEW_WIDTH)
        self.img_scale_slider.setOrientation(Qt.Horizontal)
        self.img_scale_slider.valueChanged.connect(
            self.change_scale_slider_signal)
        image_prev_layout.addWidget(self.img_scale_slider)
        self._update_preview()

        layout.addLayout(image_prev_layout)
        layout.addWidget(self.list_view)
        layout.addLayout(controls_layout)
        self.setLayout(layout)
        self.update_status_combobox = True

    def _pillow_to_pixmap(self, img):
        if img.mode == "RGB":
            r, g, b = img.split()
            img = Image.merge("RGB", (b, g, r))
        elif img.mode == "RGBA":
            r, g, b, a = img.split()
            img = Image.merge("RGBA", (b, g, r, a))
        elif img.mode == "L":
            img = img.convert("RGBA")
        img2 = img.convert("RGBA")
        data = img2.tobytes("raw", "RGBA")
        qim = QImage(data, img.size[0], img.size[1], QImage.Format_ARGB32)
        pixmap = QPixmap.fromImage(qim)
        return pixmap

    def _update_preview(self):
        self.img_label.setMinimumWidth(self.IMG_PREVIEW_WIDTH)
        self.img_label.setMaximumWidth(
            max(self.IMG_PREVIEW_WIDTH, self.img_scale_slider.width()))
        if len(self.last_created_pix_path) > 0:
            img = Image.open(self.last_created_pix_path)
            img_pix = self._pillow_to_pixmap(img)
            img_pix = img_pix.scaled(
                QSize(self.IMG_PREVIEW_WIDTH, self.IMG_PREVIEW_WIDTH),
                Qt.KeepAspectRatio)
            self.img_label.setPixmap(img_pix)

    def _set_preview(self, img_path):
        if img_path is None:
            self.last_created_pix_path = ""
            self.img_label.setText(self.select_text)
        else:
            if img_path != self.last_created_pix_path:
                self.last_created_pix_path = img_path
                self._update_preview()

    def _add_items_to_mode_combobox(self, combobox):
        combobox.addItem("From Source")
        combobox.addItem("A4")
        # combobox.addItem("A5")
        # combobox.addItem("A6")
        # combobox.addItem("Letter")

    def _get_filtered_string(self, string):
        to_return_array = []
        for s in string:
            if s.isdigit():
                to_return_array.append(s)
        return "".join(to_return_array)

    def get_images_to_save(self):
        path_array = []
        for i in range(self.list_view.count()):
            path_array.append(self.list_view.item(i).get_data())
        return path_array

    def get_image_parameters(self):  # return as dictionary
        if self.options_mode == 0:
            return {
                "mode": 0,
                "pixels": self.option_source_widget.get_pixel_value(),
                "margin": self.option_source_widget.get_margin_value(),
                "background": self.option_source_widget.get_background_value()
            }
        else:
            return {
                "mode": self.options_mode,
                "align": self.options_a_widget.get_align_value(),
                "margin": self.options_a_widget.get_margin_value(),
                "background": self.options_a_widget.get_background_value()
            }

    def add_items(self, array):
        added_names = []
        for a in array:
            new_name = os.path.basename(a)
            new_item = ImageListItem(new_name, a)
            added_names.append(new_name)
            self.list_view.addItem(new_item)
        self.status_bar.showMessage("Add items: " + ", ".join(added_names))

    def change_scale_slider_signal(self, value):
        self.IMG_PREVIEW_WIDTH = value
        self._update_preview()
        self.status_bar.showMessage("Set preview scale to " + str(value))

    def click_item_signal(self, item):
        pass
        # self._set_preview(item.get_data())
        # self.status_bar.showMessage("Select " + str(item.text()))

    def _get_first_new_index(self, current, last):
        for v in current:
            if v not in last:
                return v
        return current[0]

    def change_selection_signal(self):
        if len(self.list_view.selectedItems()) == 0:
            self._set_preview(None)  # nothing selected
        else:
            selected_indexes = [
                self.list_view.indexFromItem(sel).row()
                for sel in self.list_view.selectedItems()
            ]
            item = self.list_view.item(
                self._get_first_new_index(selected_indexes,
                                          self.last_selected_items))
            self._set_preview(item.get_data())
            self.status_bar.showMessage("Select " + str(item.text()))
            self.last_selected_items = selected_indexes

    def change_options_mode_signal(self, index):
        self.options_mode = index
        if self.options_mode == 0:
            self.options_zone_layout.removeWidget(self.options_a_widget)
            self.options_a_widget.setParent(None)
            self.options_zone_layout.addWidget(self.option_source_widget)
        else:
            self.options_zone_layout.removeWidget(self.option_source_widget)
            self.option_source_widget.setParent(None)
            self.options_zone_layout.addWidget(self.options_a_widget)
        if self.update_status_combobox:
            self.status_bar.showMessage(
                "Set combine mode to \"" +
                self.options_mode_combobox.itemText(index) + "\"")

    def resizeEvent(self, size):
        # self._update_preview()
        pass

    def click_move_up(self):
        selected = self.list_view.selectedItems()
        selected_indexes = [
            self.list_view.indexFromItem(sel).row() for sel in selected
        ]
        selected_indexes.sort()
        if len(selected_indexes) > 0 and selected_indexes[0] > 0:
            for index in selected_indexes:
                prev_item = self.list_view.takeItem(index - 1)
                self.list_view.insertItem(index, prev_item)
            self.status_bar.showMessage("Move " + str(len(selected_indexes)) +
                                        " items")
        else:
            self.status_bar.showMessage("Nothing to move")

    def click_move_down(self):
        selected = self.list_view.selectedItems()
        selected_indexes = [
            self.list_view.indexFromItem(sel).row() for sel in selected
        ]
        selected_indexes.sort()
        sel_count = len(selected_indexes)
        if len(selected_indexes) > 0 and selected_indexes[
                sel_count - 1] < self.list_view.count() - 1:
            for i_index in range(sel_count):
                next_item = self.list_view.takeItem(
                    selected_indexes[sel_count - i_index - 1] + 1)
                self.list_view.insertItem(
                    selected_indexes[sel_count - i_index - 1], next_item)
            self.status_bar.showMessage("Move " + str(len(selected_indexes)) +
                                        " items")
        else:
            self.status_bar.showMessage("Nothing to move")

    def click_invert(self):
        selected = self.list_view.selectedItems()
        selected_indexes = []
        for sel in selected:
            selected_indexes.append(self.list_view.indexFromItem(sel).row())
        total_indexes = [i for i in range(self.list_view.count())]
        new_indexes = []
        for i in total_indexes:
            if i not in selected_indexes:
                new_indexes.append(i)
        self.list_view.clearSelection()
        for i in new_indexes:
            self.list_view.item(i).setSelected(True)
        self.status_bar.showMessage("Invert selection: " + str(new_indexes))

    def click_delete(self):
        selected = self.list_view.selectedItems()
        delete_names = []
        for s in selected:
            s_index = self.list_view.indexFromItem(s).row()
            del_item = self.list_view.takeItem(s_index)
            delete_names.append(del_item.text())
        if len(delete_names) == 0:
            self.status_bar.showMessage("Nothing to delete")
        else:
            self.status_bar.showMessage("Delete items: " +
                                        ", ".join(delete_names))

    def click_add_files(self):
        files_dialog = QFileDialog()
        files_dialog.setNameFilter("Images (*.jpg *.jpeg *.bmp *.png *.tiff)")
        files_dialog.setFileMode(QFileDialog.ExistingFiles)
        if files_dialog.exec_():
            files = files_dialog.selectedFiles()
            self.add_items(files)
class FilterDock(QDockWidget):

    def __init__(self, platforms, regions, genres, years):
        super(FilterDock, self).__init__()

        # QDockWidget settings
        self.setAllowedAreas(Qt.BottomDockWidgetArea)
        self.setFeatures(QDockWidget.DockWidgetClosable)
        self.setFixedHeight(150)
        self.setVisible(False)
        self.setWindowTitle("Filter options")

        # The selected items for each widget are saved in a set-dictionary
        self._selections = defaultdict(set)

        #  Widget settings
        # Platform widgets
        self._platformLabel = QLabel("Platform")
        self._platforms = QListWidget()
        self._platforms.addItems(platforms)
        self._platforms.setSelectionMode(QAbstractItemView.MultiSelection)
        self._platforms.setMaximumWidth(200)
        self._platformVBox = QVBoxLayout()
        self._platformVBox.addWidget(self._platformLabel, 0)
        self._platformVBox.addWidget(self._platforms, 1)

        # Region widgets
        self._regionLabel = QLabel("Region")
        self._regions = QListWidget()
        self._regions.addItems(regions)
        self._regions.setSelectionMode(QAbstractItemView.MultiSelection)
        self._regions.setMaximumWidth(200)
        self._regionVBox = QVBoxLayout()
        self._regionVBox.addWidget(self._regionLabel, 0)
        self._regionVBox.addWidget(self._regions, 1)

        # Genre widgets
        self._genreLabel = QLabel("Genre")
        self._genres = QListWidget()
        self._genres.addItems(genres)
        self._genres.setSelectionMode(QAbstractItemView.MultiSelection)
        self._genres.setMaximumWidth(300)
        self._genreVBox = QVBoxLayout()
        self._genreVBox.addWidget(self._genreLabel, 0)
        self._genreVBox.addWidget(self._genres, 1)

        # Year widgets
        self._yearLabel = QLabel("Year")
        self._years = QListWidget()
        self._years.addItems(years)
        self._years.setSelectionMode(QAbstractItemView.MultiSelection)
        self._years.setMaximumWidth(75)
        self._yearsVbox = QVBoxLayout()
        self._yearsVbox.addWidget(self._yearLabel, 0)
        self._yearsVbox.addWidget(self._years, 1)

        # Inventory widgets
        self._itemType = {1: "Game", 2: "Console", 3: "Accessory"}
        self._item = QCheckBox(self._itemType[1])
        self._item.setTristate(True)
        self._item.setCheckState(Qt.PartiallyChecked)
        self._manual = QCheckBox("Manual")
        self._manual.setTristate(True)
        self._manual.setCheckState(Qt.PartiallyChecked)
        self._box = QCheckBox("Box")
        self._box.setTristate(True)
        self._box.setCheckState(Qt.PartiallyChecked)
        self._inventoryLabelsVBox = QVBoxLayout()
        self._inventorySelectionsVBox = QVBoxLayout()
        self._inventorySelectionsVBox.addStretch(3)
        self._inventorySelectionsVBox.addWidget(self._item, 0)
        self._inventorySelectionsVBox.addWidget(self._box, 1)
        self._inventorySelectionsVBox.addWidget(self._manual, 2)
        self._inventorySelectionsVBox.setAlignment(Qt.AlignLeft)
        self._haveHBox = QHBoxLayout()
        self._haveHBox.addLayout(self._inventoryLabelsVBox, 0)
        self._haveHBox.addLayout(self._inventorySelectionsVBox, 1)
        self._inventoryGroup = QGroupBox("Inventory")
        self._inventoryGroup.setMaximumWidth(120)
        self._inventoryGroup.setLayout(self._haveHBox)

        # Clear and Apply button widgets
        self._clearBtn = QPushButton("Clear selection")
        self._clearBtn.setMaximumSize(self._clearBtn.sizeHint())
        self._clearBtn.clicked.connect(self._clearFilters)
        self._btnHBox = QHBoxLayout()
        self._btnHBox.setAlignment(Qt.AlignBottom | Qt.AlignRight)
        self._btnHBox.addWidget(self._clearBtn, 0)

        # General layout
        mainHBox = QHBoxLayout()
        mainHBox.setAlignment(Qt.AlignLeft)
        mainHBox.addLayout(self._platformVBox, 0)
        mainHBox.addLayout(self._regionVBox, 0)
        mainHBox.addLayout(self._genreVBox, 0)
        mainHBox.addLayout(self._yearsVbox, 0)
        mainHBox.addWidget(self._inventoryGroup, 0)
        mainHBox.addLayout(self._btnHBox, 0)
        mainWidget = QWidget()
        mainWidget.setLayout(mainHBox)
        self.setWidget(mainWidget)

    def _clearFilters(self):
        self._platforms.clearSelection()
        self._regions.clearSelection()
        self._genres.clearSelection()
        self._years.clearSelection()
        self._item.setCheckState(Qt.PartiallyChecked)
        self._box.setCheckState(Qt.PartiallyChecked)
        self._manual.setCheckState(Qt.PartiallyChecked)
        logger.info("Cleared all filters.")

    def getSelections(self):
        self._selections = defaultdict(set)  # Reset selections
        if len(self._platforms.selectedItems()) > 0:
            platforms = [x.text() for x in self._platforms.selectedItems()]
            for platform in platforms:
                self._selections["Platform"].add(platform)
        if len(self._regions.selectedItems()) > 0:
            regions = [x.text() for x in self._regions.selectedItems()]
            for region in regions:
                self._selections["Region"].add(region)
        if len(self._genres.selectedItems()) > 0:
            genres = [x.text() for x in self._genres.selectedItems()]
            for genre in genres:
                self._selections["Genre"].add(genre)
        if len(self._years.selectedItems()) > 0:
            years = [x.text() for x in self._years.selectedItems()]
            for year in years:
                self._selections["Year"].add(year)
        if self._item.checkState() is not Qt.PartiallyChecked:
            self._selections[self._item.text()].add("Yes" if self._item.isChecked() else "No")
        if self._manual.checkState() is not Qt.PartiallyChecked:
            self._selections["Manual"].add("Yes" if self._manual.isChecked() else "No")
        if self._box.checkState() is not Qt.PartiallyChecked:
            self._selections["Box"].add("Yes" if self._box.isChecked() else "No")

        return self._selections

    def setItemType(self, itemType: int):
        if 0 < itemType < 4:
            if self._item.text() in self._selections:
                # Delete previous item entry so we don't search for the wrong type in the wrong table
                del self._selections[self._item.text()]
            self._item.setText(self._itemType[itemType])

    def toggleVisibility(self):
        self.setVisible(False if self.isVisible() else True)

    def updatePlatforms(self, platforms):
        self._platforms.clear()
        self._platforms.addItems(platforms)
        logger.info("Updated platforms list.")

    def updateRegions(self, regions):
        self._regions.clear()
        self._regions.addItems(regions)
        logger.info("Updated regions list.")

    def updateGenres(self, genres):
        self._genres.clear()
        self._genres.addItems(genres)
        logger.info("Updated genres list.")

    def updateYears(self, years):
        self._years.clear()
        self._years.addItems(years)
        logger.info("Updated years list.")