Ejemplo n.º 1
0
class DoubleSpin(QWidget):
    #a custom widget containing 2 QSpinBoxes in a row
    #is used for pair user input (like x,y or width, height)
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        layout = QHBoxLayout()
        self.sbx = QSpinBox()
        self.sby = QSpinBox()
        self.sbx.setRange(0, 1000)
        self.sby.setRange(0, 1000)
        lb = QLabel('x')
        lb.setSizePolicy(Qt.QSizePolicy.Minimum, Qt.QSizePolicy.Minimum)
        layout.addWidget(lb)
        self.sbx.setSizePolicy(Qt.QSizePolicy.Maximum, Qt.QSizePolicy.Maximum)
        layout.addWidget(self.sbx)
        lby = QLabel('y')
        lby.setSizePolicy(Qt.QSizePolicy.Minimum, Qt.QSizePolicy.Minimum)
        layout.addWidget(lby)
        layout.setAlignment(Qt.Qt.AlignLeft)
        layout.addWidget(self.sby)
        self.setLayout(layout)

    def setX(self, x):
        self.sbx.setValue(x)

    def setY(self, y):
        self.sby.setValue(y)

    def getValues(self):
        return (self.sbx.value(), self.sby.value())
Ejemplo n.º 2
0
    class GenerateLabelsDialog(QDialog):
        #Generate labels dialog class
        def __init__(self, p=None):
            QDialog.__init__(self, p)
            self.setWindowTitle("Generate page layout...")
            self.layout = QFormLayout()

            self.numberOfLabelsSpinBox = QSpinBox()
            self.numberOfLabelsSpinBox.setRange(1, 200)
            self.numberOfLabelsSpinBox.setValue(
                generate_settings['defaultNumberOfLabels'])
            self.layout.addRow("Number of labels", self.numberOfLabelsSpinBox)

            self.firstLabelArticleNumberSB = QSpinBox()
            self.firstLabelArticleNumberSB.setRange(0, 9999)
            self.firstLabelArticleNumberSB.setValue(
                generate_settings['firstLabelArticleNumber'])
            self.layout.addRow("First label article number",
                               self.firstLabelArticleNumberSB)

            self.weekNrYearLE = QLineEdit()
            self.weekNrYearLE.setText(generate_settings['weekNrYear'])
            self.layout.addRow("Week nr/ year", self.weekNrYearLE)

            self.lotNameLE = QLineEdit()
            self.lotNameLE.setText(generate_settings['lotName'])
            self.layout.addRow("Lot", self.lotNameLE)

            self.generatePB = QPushButton("Generate")
            self.generatePB.clicked.connect(self.onGenerate)
            self.layout.addRow("", self.generatePB)
            self.cancelPB = QPushButton("Cancel")
            self.cancelPB.clicked.connect(self.close)
            self.layout.addRow("", self.cancelPB)
            self.setLayout(self.layout)

        def onGenerate(self):
            generate_settings[
                'defaultNumberOfLabels'] = self.numberOfLabelsSpinBox.value()
            generate_settings[
                'firstLabelArticleNumber'] = self.firstLabelArticleNumberSB.value(
                )
            generate_settings['weekNrYear'] = self.weekNrYearLE.text()
            generate_settings['lotName'] = self.lotNameLE.text()
            self.accept()
class MainWidget(QWidget):
    def __init__(self):
        super().__init__()

        self._label_info = QLabel()

        self._button_append = QPushButton('Add')
        self._button_append.clicked.connect(self._on_append_clicked)

        self._spin_box_numbers = QSpinBox()
        self._spin_box_numbers.setRange(1, 1_000_000)
        self._spin_box_numbers.setValue(1_000_000)

        h_layout = QHBoxLayout()
        h_layout.addWidget(self._button_append)
        h_layout.addWidget(self._spin_box_numbers)
        h_layout.addWidget(QLabel('objects'))

        main_layout = QVBoxLayout()
        main_layout.addWidget(self._label_info)
        main_layout.addLayout(h_layout)
        self.setLayout(main_layout)

        self._items = []

        pid = current_process().pid
        self._process = psutil.Process(pid)

        self._timer = QTimer()
        self._timer.timeout.connect(self.update_memory_info)
        self._timer.start(500)

        self.update_memory_info()

    def _on_append_clicked(self):
        row = [0 for _ in range(self._spin_box_numbers.value())]
        self._items.append(row)

    def update_memory_info(self):
        memory_bytes = self._process.memory_info().rss

        self._label_info.setText(
            f'Current memory: {memory_bytes} bytes\n'
            f'Current memory: {memory_bytes // 1024} KB\n'
            f'Current memory: {memory_bytes // 1024 // 1024} MB')
Ejemplo n.º 4
0
class ConfigWidget(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.l = QHBoxLayout()
        self.setLayout(self.l)

        self.label = QLabel("Max number of last issues to download:")
        self.l.addWidget(self.label)

        self.max_number = QSpinBox(self)
        self.max_number.setValue(prefs["max_numbers"])
        self.max_number.setMinimum(0)
        self.l.addWidget(self.max_number)
        self.label.setBuddy(self.max_number)

    def save_settings(self):
        prefs["max_numbers"] = self.max_number.value()
        prefs.commit()
Ejemplo n.º 5
0
class ExtendedGroupBox(DeviceOptionsGroupBox):
    """The options group for KoboTouchExtended."""
    def __init__(self, parent, device):
        """Set up driver config options group."""
        super(ExtendedGroupBox, self).__init__(
            parent,
            device,
            _("Extended driver")  # noqa: F821
        )

        self.options_layout = QGridLayout()
        self.options_layout.setObjectName("options_layout")
        self.setLayout(self.options_layout)

        self.extra_features_checkbox = create_checkbox(
            _("Enable Extended Kobo Features"),  # noqa: F821
            _("Choose whether to enable extra customizations"),  # noqa: F821
            device.get_pref("extra_features"),
        )

        self.upload_encumbered_checkbox = create_checkbox(
            _("Upload DRM-encumbered ePub files"),  # noqa: F821
            _(  # noqa: F821
                "Select this to upload ePub files encumbered by DRM. If this "
                "is not selected, it is a fatal error to upload an encumbered "
                "file"),
            device.get_pref("upload_encumbered"),
        )

        self.skip_failed_checkbox = create_checkbox(
            _("Silently Ignore Failed Conversions"),  # noqa: F821
            _(  # noqa: F821
                "Select this to not upload any book that fails conversion to "
                "kepub. If this is not selected, the upload process will be "
                "stopped at the first book that fails. If this is selected, "
                "failed books will be silently removed from the upload queue."
            ),
            device.get_pref("skip_failed"),
        )

        self.hyphenate_checkbox = create_checkbox(
            _("Hyphenate Files"),  # noqa: F821
            _(  # noqa: F821
                "Select this to add a CSS file which enables hyphenation. The "
                "language used will be the language defined for the book in "
                "calibre. Please see the README file for directions on "
                "updating hyphenation dictionaries."),
            device.get_pref("hyphenate"),
        )

        self.smarten_punctuation_checkbox = create_checkbox(
            _("Smarten Punctuation"),  # noqa: F821
            _("Select this to smarten punctuation in the ePub"),  # noqa: F821
            device.get_pref("smarten_punctuation"),
        )

        self.clean_markup_checkbox = create_checkbox(
            _("Clean up ePub Markup"),  # noqa: F821
            _("Select this to clean up the internal ePub markup."
              ),  # noqa: F821
            device.get_pref("clean_markup"),
        )

        self.file_copy_dir_checkbox = create_checkbox(
            _("Copy generated KePub files to a directory"),  # noqa: F821
            _(  # noqa: F821
                "Enter an absolute directory path to copy all generated KePub "
                "files into for debugging purposes."),
            device.get_pref("file_copy_dir"),
        )
        self.file_copy_dir_label = QLabel(
            _("Copy generated KePub files to a directory")  # noqa: F821
        )
        self.file_copy_dir_edit = QLineEdit(self)
        self.file_copy_dir_edit.setToolTip(
            _(  # noqa: F821
                "Enter an absolute directory path to copy all generated KePub "
                "files into for debugging purposes."))
        self.file_copy_dir_edit.setText(device.get_pref("file_copy_dir"))
        self.file_copy_dir_label.setBuddy(self.file_copy_dir_edit)

        self.full_page_numbers_checkbox = create_checkbox(
            _("Use full book page numbers"),  # noqa: F821
            _(  # noqa: F821
                "Select this to show page numbers for the whole book, instead "
                "of each chapter. This will also affect regular ePub page "
                "number display!"),
            device.get_pref("full_page_numbers"),
        )

        self.disable_hyphenation_checkbox = create_checkbox(
            _("Disable hyphenation"),  # noqa: F821
            _("Select this to disable hyphenation for books."),  # noqa: F821
            device.get_pref("disable_hyphenation"),
        )

        self.opt_kepub_hyphenate_chars_label = QLabel(
            _("Minimum word length to hyphenate") + ":"  # noqa: F821
        )

        self.opt_kepub_hyphenate_chars = QSpinBox(self)
        self.opt_kepub_hyphenate_chars_label.setBuddy(
            self.opt_kepub_hyphenate_chars)
        self.opt_kepub_hyphenate_chars.setObjectName(
            "opt_kepub_hyphenate_chars")
        self.opt_kepub_hyphenate_chars.setSpecialValueText(
            _("Disabled"))  # noqa: F821
        self.opt_kepub_hyphenate_chars.valueChanged.connect(
            functools.partial(
                common.intValueChanged,
                self.opt_kepub_hyphenate_chars,
                _("character"),  # noqa: F821
                _("characters"),  # noqa: F821
            ))
        self.opt_kepub_hyphenate_chars.setValue(
            device.get_pref("hyphenate_chars"))

        self.opt_kepub_hyphenate_chars_before_label = QLabel(
            _("Minimum characters before hyphens") + ":"  # noqa: F821
        )

        self.opt_kepub_hyphenate_chars_before = QSpinBox(self)
        self.opt_kepub_hyphenate_chars_before_label.setBuddy(
            self.opt_kepub_hyphenate_chars_before)
        self.opt_kepub_hyphenate_chars_before.setObjectName(
            "opt_kepub_hyphenate_chars_before")
        self.opt_kepub_hyphenate_chars_before.valueChanged.connect(
            functools.partial(
                common.intValueChanged,
                self.opt_kepub_hyphenate_chars_before,
                _("character"),  # noqa: F821
                _("characters"),  # noqa: F821
            ))
        self.opt_kepub_hyphenate_chars_before.setMinimum(2)
        self.opt_kepub_hyphenate_chars_before.setValue(
            device.get_pref("hyphenate_chars_before"))

        self.opt_kepub_hyphenate_chars_after_label = QLabel(
            _("Minimum characters after hyphens") + ":"  # noqa: F821
        )

        self.opt_kepub_hyphenate_chars_after = QSpinBox(self)
        self.opt_kepub_hyphenate_chars_after_label.setBuddy(
            self.opt_kepub_hyphenate_chars_after)
        self.opt_kepub_hyphenate_chars_after.setObjectName(
            "opt_kepub_hyphenate_chars_after")
        self.opt_kepub_hyphenate_chars_after.valueChanged.connect(
            functools.partial(
                common.intValueChanged,
                self.opt_kepub_hyphenate_chars_after,
                _("character"),  # noqa: F821
                _("characters"),  # noqa: F821
            ))
        self.opt_kepub_hyphenate_chars_after.setMinimum(2)
        self.opt_kepub_hyphenate_chars_after.setValue(
            device.get_pref("hyphenate_chars_after"))

        self.opt_kepub_hyphenate_limit_lines_label = QLabel(
            _("Maximum consecutive hyphenated lines") + ":"  # noqa: F821
        )

        self.opt_kepub_hyphenate_limit_lines = QSpinBox(self)
        self.opt_kepub_hyphenate_limit_lines_label.setBuddy(
            self.opt_kepub_hyphenate_limit_lines)
        self.opt_kepub_hyphenate_limit_lines.setObjectName(
            "opt_kepub_hyphenate_limit_lines")
        self.opt_kepub_hyphenate_limit_lines.setSpecialValueText(
            _("Disabled")  # noqa: F821
        )
        self.opt_kepub_hyphenate_limit_lines.valueChanged.connect(
            functools.partial(
                common.intValueChanged,
                self.opt_kepub_hyphenate_limit_lines,
                _("line"),  # noqa: F821
                _("lines"),  # noqa: F821
            ))
        self.opt_kepub_hyphenate_limit_lines.setValue(
            device.get_pref("hyphenate_limit_lines"))

        self.options_layout.addWidget(self.extra_features_checkbox, 0, 0, 1, 1)
        self.options_layout.addWidget(self.upload_encumbered_checkbox, 0, 1, 1,
                                      1)
        self.options_layout.addWidget(self.skip_failed_checkbox, 1, 0, 1, 1)
        self.options_layout.addWidget(self.hyphenate_checkbox, 1, 1, 1, 1)
        self.options_layout.addWidget(self.smarten_punctuation_checkbox, 2, 1,
                                      1, 1)
        self.options_layout.addWidget(self.clean_markup_checkbox, 3, 0, 1, 1)
        self.options_layout.addWidget(self.file_copy_dir_label, 4, 0, 1, 1)
        self.options_layout.addWidget(self.file_copy_dir_edit, 4, 1, 1, 1)
        self.options_layout.addWidget(self.full_page_numbers_checkbox, 5, 0, 1,
                                      1)
        self.options_layout.addWidget(self.disable_hyphenation_checkbox, 5, 1,
                                      1, 1)
        self.options_layout.addWidget(self.opt_kepub_hyphenate_chars_label, 6,
                                      0, 1, 1)
        self.options_layout.addWidget(self.opt_kepub_hyphenate_chars, 6, 1, 1,
                                      1)
        self.options_layout.addWidget(
            self.opt_kepub_hyphenate_chars_before_label, 7, 0, 1, 1)
        self.options_layout.addWidget(self.opt_kepub_hyphenate_chars_before, 7,
                                      1, 1, 1)
        self.options_layout.addWidget(
            self.opt_kepub_hyphenate_chars_after_label, 8, 0, 1, 1)
        self.options_layout.addWidget(self.opt_kepub_hyphenate_chars_after, 8,
                                      1, 1, 1)
        self.options_layout.addWidget(
            self.opt_kepub_hyphenate_limit_lines_label, 9, 0, 1, 1)
        self.options_layout.addWidget(self.opt_kepub_hyphenate_limit_lines, 9,
                                      1, 1, 1)
        self.options_layout.setRowStretch(10, 2)

    @property
    def extra_features(self):
        """Determine if Kobo extra features are enabled."""
        return self.extra_features_checkbox.isChecked()

    @property
    def upload_encumbered(self):
        """Determine if DRM-encumbered files will be uploaded."""
        return self.upload_encumbered_checkbox.isChecked()

    @property
    def skip_failed(self):
        """Determine if failed conversions will be skipped."""
        return self.skip_failed_checkbox.isChecked()

    @property
    def hyphenate(self):
        """Determine if hyphenation should be enabled."""
        return self.hyphenate_checkbox.isChecked()

    @property
    def smarten_punctuation(self):
        """Determine if punctuation should be converted to smart punctuation."""
        return self.smarten_punctuation_checkbox.isChecked()

    @property
    def clean_markup(self):
        """Determine if additional markup cleanup will be done."""
        return self.clean_markup_checkbox.isChecked()

    @property
    def full_page_numbers(self):
        """Determine if full-book page numbers will be displayed."""
        return self.full_page_numbers_checkbox.isChecked()

    @property
    def disable_hyphenation(self):
        """Determine if hyphenation should be disabled."""
        return self.disable_hyphenation_checkbox.isChecked()

    @property
    def file_copy_dir(self):
        """Determine where to copy converted KePub books to."""
        return self.file_copy_dir_edit.text().strip()

    @property
    def hyphenate_chars(self):
        return self.opt_kepub_hyphenate_chars.value()

    @property
    def hyphenate_chars_before(self):
        return self.opt_kepub_hyphenate_chars_before.value()

    @property
    def hyphenate_chars_after(self):
        return self.opt_kepub_hyphenate_chars_after.value()

    @property
    def hyphenate_limit_lines(self):
        return self.opt_kepub_hyphenate_limit_lines.value()
Ejemplo n.º 6
0
class GcodeUI(object):
    def __init__(self, ui, layout):
        self.main_ui = ui
        self.layout = layout
        super(GcodeUI, self).__init__()
        self.isOutlineMode = True
        self.isLaserMode = True
        self.handler = GcodeHandler(self)
        self.set_ui()
        self.connect_slot()
        self.gcode = ''

    def set_ui(self):
        self._set_up_frame_ui()
        self._set_middle_frame_ui()
        self._set_down_frame_ui()

    def _set_up_frame_ui(self):
        self.up_frame = QFrame()
        self.up_frame.setMinimumHeight(300)
        self.up_frame.setMaximumHeight(500)
        self.up_layout = QHBoxLayout(self.up_frame)
        up_left_frame = QFrame()
        # up_left_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2)
        # up_left_frame.setMaximumWidth(self.geometry().width() / 2)
        up_right_frame = QFrame()
        # up_right_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2)
        # up_right_frame.setMaximumWidth(self.geometry().width() / 2)
        self.up_left_layout = QHBoxLayout(up_left_frame)
        self.up_right_layout = QHBoxLayout(up_right_frame)
        self.up_layout.addWidget(up_left_frame)
        # self.up_layout.addWidget(up_right_frame)
        self.layout.addWidget(self.up_frame)

        self.label_img = QLabel()
        # self.label_img.setMaximumHeight(320)
        # self.label_img.setMaximumWidth(480)
        # self.label_img.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        # self.label_img.setScaledContents(True)

        img = QImage()
        if img.load(os.path.join(icon_path, 'tmp.svg')):
            self.label_img.setPixmap(QPixmap.fromImage(img))
            with open(os.path.join(icon_path, 'tmp.svg'), 'rb') as f:
                self.handler.source = f.read()

        self.up_left_layout.addWidget(self.label_img)

        self.label_img_preview = QLabel()
        # self.label_img_preview.setMaximumHeight(320)
        # self.label_img_preview.setMaximumWidth(480)
        self.label_img_preview.setDisabled(True)
        # # self.label_img_preview.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        # # self.label_img_preview.setScaledContents(True)
        # data = np.zeros(320 * 240)
        # img = QImage(data, 320, 240, QImage.Format_RGB888)
        # pixmap = QPixmap.fromImage(img)
        # self.label_img_preview.setPixmap(pixmap)
        self.up_right_layout.addWidget(self.label_img_preview)
        # self.up_frame.hide()

    def _set_middle_frame_ui(self):
        middle_frame = QFrame()
        self.middle_layout = QHBoxLayout(middle_frame)
        middle_left_frame = QFrame()
        # middle_left_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2 - 20)
        middle_right_frame = QFrame()
        # middle_right_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2 - 20)
        self.middle_left_layout = QGridLayout(middle_left_frame)
        self.middle_right_layout = QGridLayout(middle_right_frame)

        self.middle_layout.addWidget(middle_left_frame)
        self.middle_layout.addWidget(middle_right_frame)
        self.layout.addWidget(middle_frame)

        row = 0
        self.checkbox_outline = QRadioButton('OutLine')
        self.checkbox_gray = QRadioButton('Gray')
        self.checkbox_gray.hide()
        self.btn_load_img = QPushButton('LoadImage')
        self.checkbox_outline.toggle()
        self.isOutlineMode = True
        self.checkbox_outline.setDisabled(True)
        self.middle_left_layout.addWidget(self.checkbox_outline, row, 0)
        self.middle_left_layout.addWidget(self.checkbox_gray, row, 1)
        self.middle_left_layout.addWidget(self.btn_load_img, row, 2)

        row += 1
        label_x_home = QLabel('x_home:')
        self.slider_x_home = QSlider(QtCore.Qt.Horizontal)
        self.slider_x_home.setMinimum(0)
        self.slider_x_home.setMaximum(2000)
        self.slider_x_home.setValue(1500)
        self.spinbox_x_home = QDoubleSpinBox()
        self.spinbox_x_home.setDecimals(1)
        self.spinbox_x_home.setSingleStep(0.1)
        self.spinbox_x_home.setMinimum(0.0)
        self.spinbox_x_home.setMaximum(200.0)
        self.spinbox_x_home.setValue(150.0)
        self.slider_x_home.mouseReleaseEvent = functools.partial(
            self.mouseReleaseEvent,
            source=self.slider_x_home.mouseReleaseEvent)
        self.spinbox_x_home.focusOutEvent = functools.partial(
            self.focusOutEvent, source=self.spinbox_x_home.focusOutEvent)
        self.middle_left_layout.addWidget(label_x_home, row, 0)
        self.middle_left_layout.addWidget(self.slider_x_home, row, 1)
        self.middle_left_layout.addWidget(self.spinbox_x_home, row, 2)

        row += 1
        label_y_home = QLabel('y_home:')
        self.slider_y_home = QSlider(QtCore.Qt.Horizontal)
        self.slider_y_home.setMinimum(-1500)
        self.slider_y_home.setMaximum(1500)
        self.slider_y_home.setValue(0)
        self.spinbox_y_home = QDoubleSpinBox()
        self.spinbox_y_home.setDecimals(1)
        self.spinbox_y_home.setSingleStep(0.1)
        self.spinbox_y_home.setMinimum(-150.0)
        self.spinbox_y_home.setMaximum(150.0)
        self.spinbox_y_home.setValue(0.0)
        self.slider_y_home.mouseReleaseEvent = functools.partial(
            self.mouseReleaseEvent,
            source=self.slider_y_home.mouseReleaseEvent)
        self.spinbox_y_home.focusOutEvent = functools.partial(
            self.focusOutEvent, source=self.spinbox_y_home.focusOutEvent)
        self.middle_left_layout.addWidget(label_y_home, row, 0)
        self.middle_left_layout.addWidget(self.slider_y_home, row, 1)
        self.middle_left_layout.addWidget(self.spinbox_y_home, row, 2)

        row += 1
        label_z_home = QLabel('z_home:')
        self.slider_z_home = QSlider(QtCore.Qt.Horizontal)
        self.slider_z_home.setMinimum(0)
        self.slider_z_home.setMaximum(1500)
        self.slider_z_home.setValue(900)
        self.spinbox_z_home = QDoubleSpinBox()
        self.spinbox_z_home.setDecimals(1)
        self.spinbox_z_home.setSingleStep(0.1)
        self.spinbox_z_home.setMinimum(0.0)
        self.spinbox_z_home.setMaximum(150.0)
        self.spinbox_z_home.setValue(90.0)
        self.slider_z_home.mouseReleaseEvent = functools.partial(
            self.mouseReleaseEvent,
            source=self.slider_z_home.mouseReleaseEvent)
        self.spinbox_z_home.focusOutEvent = functools.partial(
            self.focusOutEvent, source=self.spinbox_z_home.focusOutEvent)
        self.middle_left_layout.addWidget(label_z_home, row, 0)
        self.middle_left_layout.addWidget(self.slider_z_home, row, 1)
        self.middle_left_layout.addWidget(self.spinbox_z_home, row, 2)

        row += 1
        label_x_offset = QLabel('x_offset:')
        self.slider_x_offset = QSlider(QtCore.Qt.Horizontal)
        self.slider_x_offset.setMinimum(-5000)
        self.slider_x_offset.setMaximum(5000)
        self.slider_x_offset.setValue(0)
        self.spinbox_x_offset = QDoubleSpinBox()
        self.spinbox_x_offset.setSingleStep(0.1)
        self.spinbox_x_offset.setDecimals(1)
        self.spinbox_x_offset.setMinimum(-500.0)
        self.spinbox_x_offset.setMaximum(500.0)
        self.spinbox_x_offset.setValue(0.0)
        self.slider_x_offset.mouseReleaseEvent = functools.partial(
            self.mouseReleaseEvent,
            source=self.slider_x_offset.mouseReleaseEvent)
        self.spinbox_x_offset.focusOutEvent = functools.partial(
            self.focusOutEvent, source=self.spinbox_x_offset.focusOutEvent)
        self.middle_left_layout.addWidget(label_x_offset, row, 0)
        self.middle_left_layout.addWidget(self.slider_x_offset, row, 1)
        self.middle_left_layout.addWidget(self.spinbox_x_offset, row, 2)

        row += 1
        label_y_offset = QLabel('y_offset:')
        self.slider_y_offset = QSlider(QtCore.Qt.Horizontal)
        self.slider_y_offset.setMinimum(-5000)
        self.slider_y_offset.setMaximum(5000)
        self.slider_y_offset.setValue(0)
        self.spinbox_y_offset = QDoubleSpinBox()
        self.spinbox_y_offset.setDecimals(1)
        self.spinbox_y_offset.setSingleStep(0.1)
        self.spinbox_y_offset.setMinimum(-500.0)
        self.spinbox_y_offset.setMaximum(500.0)
        self.spinbox_y_offset.setValue(0.0)
        self.slider_y_offset.mouseReleaseEvent = functools.partial(
            self.mouseReleaseEvent,
            source=self.slider_y_offset.mouseReleaseEvent)
        self.spinbox_y_offset.focusOutEvent = functools.partial(
            self.focusOutEvent, source=self.spinbox_y_offset.focusOutEvent)
        self.middle_left_layout.addWidget(label_y_offset, row, 0)
        self.middle_left_layout.addWidget(self.slider_y_offset, row, 1)
        self.middle_left_layout.addWidget(self.spinbox_y_offset, row, 2)

        row += 1
        label_z_offset = QLabel('z_offset:')
        self.slider_z_offset = QSlider(QtCore.Qt.Horizontal)
        self.slider_z_offset.setMinimum(-1000)
        self.slider_z_offset.setMaximum(1500)
        self.slider_z_offset.setValue(900)
        self.spinbox_z_offset = QDoubleSpinBox()
        self.spinbox_z_offset.setDecimals(1)
        self.spinbox_z_offset.setSingleStep(0.1)
        self.spinbox_z_offset.setMinimum(-100.0)
        self.spinbox_z_offset.setMaximum(150.0)
        self.spinbox_z_offset.setValue(90.0)
        self.slider_z_offset.mouseReleaseEvent = functools.partial(
            self.mouseReleaseEvent,
            source=self.slider_z_offset.mouseReleaseEvent)
        self.spinbox_z_offset.focusOutEvent = functools.partial(
            self.focusOutEvent, source=self.spinbox_z_offset.focusOutEvent)
        self.middle_left_layout.addWidget(label_z_offset, row, 0)
        self.middle_left_layout.addWidget(self.slider_z_offset, row, 1)
        self.middle_left_layout.addWidget(self.spinbox_z_offset, row, 2)

        row += 1
        label_pen_up = QLabel('pen_up:')
        self.slider_pen_up = QSlider(QtCore.Qt.Horizontal)
        self.slider_pen_up.setMinimum(0)
        self.slider_pen_up.setMaximum(500)
        self.slider_pen_up.setValue(200)
        self.spinbox_pen_up = QDoubleSpinBox()
        self.spinbox_pen_up.setDecimals(1)
        self.spinbox_pen_up.setSingleStep(0.1)
        self.spinbox_pen_up.setMinimum(0.0)
        self.spinbox_pen_up.setMaximum(50.0)
        self.spinbox_pen_up.setValue(20.0)
        self.slider_pen_up.mouseReleaseEvent = functools.partial(
            self.mouseReleaseEvent,
            source=self.slider_pen_up.mouseReleaseEvent)
        self.spinbox_pen_up.focusOutEvent = functools.partial(
            self.focusOutEvent, source=self.spinbox_pen_up.focusOutEvent)
        self.slider_pen_up.setDisabled(True)
        self.spinbox_pen_up.setDisabled(True)
        self.middle_left_layout.addWidget(label_pen_up, row, 0)
        self.middle_left_layout.addWidget(self.slider_pen_up, row, 1)
        self.middle_left_layout.addWidget(self.spinbox_pen_up, row, 2)

        row = 0
        self.checkbox_laser = QRadioButton('Laser')
        self.checkbox_pen = QRadioButton('Pen')
        self.checkbox_laser.toggle()
        self.isLaserMode = True
        self.middle_right_layout.addWidget(self.checkbox_laser, row, 0)
        self.middle_right_layout.addWidget(self.checkbox_pen, row, 1)

        row += 1
        label_drawing_feedrate = QLabel('drawing_feedrate:')
        self.slider_drawing_feedrate = QSlider(QtCore.Qt.Horizontal)
        self.slider_drawing_feedrate.setMinimum(5)
        self.slider_drawing_feedrate.setMaximum(1000)
        self.slider_drawing_feedrate.setValue(100)
        self.spinbox_drawing_feedrate = QSpinBox()
        self.spinbox_drawing_feedrate.setMinimum(5)
        self.spinbox_drawing_feedrate.setMaximum(1000)
        self.spinbox_drawing_feedrate.setValue(100)
        self.slider_drawing_feedrate.mouseReleaseEvent = functools.partial(
            self.mouseReleaseEvent,
            source=self.slider_drawing_feedrate.mouseReleaseEvent)
        self.spinbox_drawing_feedrate.focusOutEvent = functools.partial(
            self.focusOutEvent,
            source=self.spinbox_drawing_feedrate.focusOutEvent)
        self.middle_right_layout.addWidget(label_drawing_feedrate, row, 0)
        self.middle_right_layout.addWidget(self.slider_drawing_feedrate, row,
                                           1)
        self.middle_right_layout.addWidget(self.spinbox_drawing_feedrate, row,
                                           2)

        row += 1
        label_moving_feedrate = QLabel('moving_feedrate:')
        self.slider_moving_feedrate = QSlider(QtCore.Qt.Horizontal)
        self.slider_moving_feedrate.setMinimum(5)
        self.slider_moving_feedrate.setMaximum(20000)
        self.slider_moving_feedrate.setValue(100)
        self.spinbox_moving_feedrate = QSpinBox()
        self.spinbox_moving_feedrate.setMinimum(5)
        self.spinbox_moving_feedrate.setMaximum(20000)
        self.spinbox_moving_feedrate.setValue(100)
        self.slider_moving_feedrate.mouseReleaseEvent = functools.partial(
            self.mouseReleaseEvent,
            source=self.slider_moving_feedrate.mouseReleaseEvent)
        self.spinbox_moving_feedrate.focusOutEvent = functools.partial(
            self.focusOutEvent,
            source=self.spinbox_moving_feedrate.focusOutEvent)
        self.middle_right_layout.addWidget(label_moving_feedrate, row, 0)
        self.middle_right_layout.addWidget(self.slider_moving_feedrate, row, 1)
        self.middle_right_layout.addWidget(self.spinbox_moving_feedrate, row,
                                           2)

        row += 1
        label_scale = QLabel('scale:')
        self.slider_scale = QSlider(QtCore.Qt.Horizontal)
        self.slider_scale.setMinimum(1)
        self.slider_scale.setMaximum(100)
        self.slider_scale.setValue(10)
        self.spinbox_scale = QDoubleSpinBox()
        self.spinbox_scale.setDecimals(1)
        self.spinbox_scale.setSingleStep(0.1)
        self.spinbox_scale.setMinimum(0.1)
        self.spinbox_scale.setMaximum(10.0)
        self.spinbox_scale.setValue(1.0)
        # self.slider_scale.setDisabled(True)
        # self.spinbox_scale.setDisabled(True)
        self.slider_scale.mouseReleaseEvent = functools.partial(
            self.mouseReleaseEvent, source=self.slider_scale.mouseReleaseEvent)
        self.spinbox_scale.focusOutEvent = functools.partial(
            self.focusOutEvent, source=self.spinbox_scale.focusOutEvent)

        self.middle_right_layout.addWidget(label_scale, row, 0)
        self.middle_right_layout.addWidget(self.slider_scale, row, 1)
        self.middle_right_layout.addWidget(self.spinbox_scale, row, 2)

        row += 1
        label_resolution = QLabel('resolution:')
        self.slider_resolution = QSlider(QtCore.Qt.Horizontal)
        self.slider_resolution.setMinimum(1)
        self.slider_resolution.setMaximum(100)
        self.slider_resolution.setValue(10)
        self.spinbox_resolution = QDoubleSpinBox()
        self.spinbox_resolution.setMinimum(0.1)
        self.spinbox_resolution.setMaximum(10.0)
        self.spinbox_resolution.setSingleStep(0.1)
        self.spinbox_resolution.setDecimals(1)
        self.spinbox_resolution.setValue(1.0)
        self.slider_resolution.setDisabled(True)
        self.spinbox_resolution.setDisabled(True)
        self.middle_right_layout.addWidget(label_resolution, row, 0)
        self.middle_right_layout.addWidget(self.slider_resolution, row, 1)
        self.middle_right_layout.addWidget(self.spinbox_resolution, row, 2)

        row += 1
        self.btn_generate_gcode = QPushButton('Generate_Gcode')
        self.middle_right_layout.addWidget(self.btn_generate_gcode, row, 0)

        row += 1
        self.label_x_min = QLabel('')
        self.label_x_max = QLabel('')
        self.middle_right_layout.addWidget(self.label_x_min, row, 0)
        self.middle_right_layout.addWidget(self.label_x_max, row, 1)

        row += 1
        self.label_y_min = QLabel('')
        self.label_y_max = QLabel('')
        self.middle_right_layout.addWidget(self.label_y_min, row, 0)
        self.middle_right_layout.addWidget(self.label_y_max, row, 1)

    def _set_down_frame_ui(self):
        self.down_frame = QFrame()
        self.down_layout = QHBoxLayout(self.down_frame)
        self.layout.addWidget(self.down_frame)

        self.textEdit = QTextEdit()
        self.down_layout.addWidget(self.textEdit)
        # self.down_frame.hide()

    def select_engrave_mode(self, event):
        self.isOutlineMode = event
        # print('outline: {}, laser: {}'.format(self.isOutlineMode, self.isLaserMode))

    def select_end_type(self, event):
        self.isLaserMode = event
        self.slider_pen_up.setDisabled(self.isLaserMode)
        self.spinbox_pen_up.setDisabled(self.isLaserMode)
        self.generate_gcode()
        # print('outline: {}, laser: {}'.format(self.isOutlineMode, self.isLaserMode))

    def connect_slot(self):
        self.checkbox_outline.toggled.connect(self.select_engrave_mode)
        self.checkbox_laser.toggled.connect(self.select_end_type)
        self.btn_load_img.clicked.connect(self.load_image)

        self.slider_x_home.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.spinbox_x_home,
                              scale=.1))
        self.spinbox_x_home.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.slider_x_home,
                              scale=10))

        self.slider_y_home.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.spinbox_y_home,
                              scale=.1))
        self.spinbox_y_home.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.slider_y_home,
                              scale=10))

        self.slider_z_home.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.spinbox_z_home,
                              scale=.1))
        self.spinbox_z_home.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.slider_z_home,
                              scale=10))

        self.slider_x_offset.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.spinbox_x_offset,
                              scale=.1))
        self.spinbox_x_offset.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.slider_x_offset,
                              scale=10))

        self.slider_y_offset.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.spinbox_y_offset,
                              scale=.1))
        self.spinbox_y_offset.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.slider_y_offset,
                              scale=10))

        self.slider_z_offset.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.spinbox_z_offset,
                              scale=.1))
        self.spinbox_z_offset.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.slider_z_offset,
                              scale=10))

        self.slider_pen_up.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.spinbox_pen_up,
                              scale=.1))
        self.spinbox_pen_up.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.slider_pen_up,
                              scale=10))

        self.slider_scale.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.spinbox_scale,
                              scale=.1))
        self.spinbox_scale.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.slider_scale,
                              scale=10))

        self.slider_resolution.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.spinbox_resolution,
                              scale=.1))
        self.spinbox_resolution.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.slider_resolution,
                              scale=10))

        self.slider_drawing_feedrate.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.spinbox_drawing_feedrate,
                              scale=1))
        self.spinbox_drawing_feedrate.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.slider_drawing_feedrate,
                              scale=1))

        self.slider_moving_feedrate.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.spinbox_moving_feedrate,
                              scale=1))
        self.spinbox_moving_feedrate.valueChanged.connect(
            functools.partial(self.slider_spinbox_related,
                              slave=self.slider_moving_feedrate,
                              scale=1))

        self.btn_generate_gcode.clicked.connect(
            functools.partial(self.generate_gcode, flag=True))

    def slider_spinbox_related(self, value, master=None, slave=None, scale=1):
        try:
            slave.setValue(value * scale)
        except Exception as e:
            print(e)

    def mouseReleaseEvent(self, event, source=None):
        try:
            self.generate_gcode()
        except Exception as e:
            print(e)
        source(event)

    def focusOutEvent(self, event, source=None):
        try:
            self.generate_gcode()
        except Exception as e:
            print(e)
        source(event)

    def generate_gcode(self, flag=False):
        if self.handler.template is None and flag:
            self.handler.svg_to_gcode()
        if self.handler.template:
            pen_up = self.spinbox_pen_up.value() if not self.isLaserMode else 0
            config = {
                'x_home': self.spinbox_x_home.value(),
                'y_home': self.spinbox_y_home.value(),
                'z_home': self.spinbox_z_home.value(),
                'z_offset': self.spinbox_z_offset.value(),
                'pen_up': pen_up,
                'z_offset_pen_up': self.spinbox_z_offset.value() + pen_up,
                'moving_feedrate': self.spinbox_moving_feedrate.value(),
                'drawing_feedrate': self.spinbox_drawing_feedrate.value(),
            }
            self.gcode = self.handler.template.format(**config)
            self.change_gcode()
            # self.textEdit.setText(self.gcode)

    def change_gcode(self):
        if self.gcode:
            x_offset = self.spinbox_x_offset.value()
            y_offset = self.spinbox_y_offset.value()
            z_offset = self.spinbox_z_offset.value()
            moving_feedrate = self.spinbox_moving_feedrate.value()
            drawing_feedrate = self.spinbox_drawing_feedrate.value()
            scale = self.spinbox_scale.value()

            lines = self.gcode.split('\n')
            for i, line in enumerate(lines):
                List = line.strip().split(' ')
                line = ''
                for l in List:
                    if l.startswith('F'):
                        if line.startswith(('G01', 'G1')):
                            l = 'F{}'.format(drawing_feedrate)
                        elif line.startswith(('G00', 'G0')):
                            l = 'F{}'.format(moving_feedrate)
                    elif l.startswith('X'):
                        x = float(l[1:]) * scale + x_offset
                        l = 'X{0:.2f}'.format(x)
                    elif l.startswith('Y'):
                        y = float(l[1:]) * scale + y_offset
                        l = 'Y{0:.2f}'.format(y)
                    # elif l.startswith('Z'):
                    #     z = float(l[1:]) + z_offset
                    #     l = 'Z{0:.2f}'.format(z)
                    line += l + ' '
                line = line.strip()
                lines[i] = line
            self.calc_gcode(lines)
            gcode = '\n'.join(lines)
            self.textEdit.setText(gcode)

    def calc_gcode(self, lines):
        x_list = []
        y_list = []
        for i, line in enumerate(lines):
            if line.startswith(tuple(['G0', 'G1', 'G00', 'G01'])):
                List = line.strip().split(' ')
                for l in List:
                    if l.startswith('X'):
                        x = float(l[1:])
                        x_list.append(x)
                    elif l.startswith('Y'):
                        y = float(l[1:])
                        y_list.append(y)
        if len(x_list) > 0:
            x_min = np.min(x_list)
            x_max = np.max(x_list)
            self.label_x_min.setText('X(min): ' + str(x_min))
            self.label_x_max.setText('X(max): ' + str(x_max))
            # print('x_min: {}, x_max: {}, x_distance: {}'.format(x_min, x_max, x_max - x_min))
        if len(y_list) > 0:
            y_min = np.min(y_list)
            y_max = np.max(y_list)
            self.label_y_min.setText('Y(min): ' + str(y_min))
            self.label_y_max.setText('Y(max): ' + str(y_max))
            # print('y_min: {}, y_max: {}, y_distance: {}'.format(y_min, y_max, y_max - y_min))

    def load_image(self):
        fname = QFileDialog.getOpenFileName(self.main_ui.window, 'Open file',
                                            '', '*.svg')
        if fname and fname[0]:
            img = QImage()
            if img.load(fname[0]):
                self.label_img.setPixmap(QPixmap.fromImage(img))
                with open(fname[0], 'rb') as f:
                    self.handler.source = f.read()
                    self.handler.template = None
                    self.gcode = None
                    self.up_frame.show()
Ejemplo n.º 7
0
class AddEmptyBookDialog(QDialog):

    def __init__(self, parent, db, author, series=None, title=None):
        QDialog.__init__(self, parent)
        self.db = db

        self.setWindowTitle(_('How many empty books?'))

        self._layout = QGridLayout(self)
        self.setLayout(self._layout)

        self.qty_label = QLabel(_('How many empty books should be added?'))
        self._layout.addWidget(self.qty_label, 0, 0, 1, 2)

        self.qty_spinbox = QSpinBox(self)
        self.qty_spinbox.setRange(1, 10000)
        self.qty_spinbox.setValue(1)
        self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2)

        self.author_label = QLabel(_('Set the author of the new books to:'))
        self._layout.addWidget(self.author_label, 2, 0, 1, 2)

        self.authors_combo = EditWithComplete(self)
        self.authors_combo.setSizeAdjustPolicy(
                self.authors_combo.AdjustToMinimumContentsLengthWithIcon)
        self.authors_combo.setEditable(True)
        self._layout.addWidget(self.authors_combo, 3, 0, 1, 1)
        self.initialize_authors(db, author)

        self.clear_button = QToolButton(self)
        self.clear_button.setIcon(QIcon(I('trash.png')))
        self.clear_button.setToolTip(_('Reset author to Unknown'))
        self.clear_button.clicked.connect(self.reset_author)
        self._layout.addWidget(self.clear_button, 3, 1, 1, 1)

        self.series_label = QLabel(_('Set the series of the new books to:'))
        self._layout.addWidget(self.series_label, 4, 0, 1, 2)

        self.series_combo = EditWithComplete(self)
        self.series_combo.setSizeAdjustPolicy(
                self.authors_combo.AdjustToMinimumContentsLengthWithIcon)
        self.series_combo.setEditable(True)
        self._layout.addWidget(self.series_combo, 5, 0, 1, 1)
        self.initialize_series(db, series)

        self.sclear_button = QToolButton(self)
        self.sclear_button.setIcon(QIcon(I('trash.png')))
        self.sclear_button.setToolTip(_('Reset series'))
        self.sclear_button.clicked.connect(self.reset_series)
        self._layout.addWidget(self.sclear_button, 5, 1, 1, 1)

        self.title_label = QLabel(_('Set the title of the new books to:'))
        self._layout.addWidget(self.title_label, 6, 0, 1, 2)

        self.title_edit = QLineEdit(self)
        self.title_edit.setText(title or '')
        self._layout.addWidget(self.title_edit, 7, 0, 1, 1)

        self.tclear_button = QToolButton(self)
        self.tclear_button.setIcon(QIcon(I('trash.png')))
        self.tclear_button.setToolTip(_('Reset title'))
        self.tclear_button.clicked.connect(self.title_edit.clear)
        self._layout.addWidget(self.tclear_button, 7, 1, 1, 1)

        self.format_label = QLabel(_('Also create an empty ebook in format:'))
        self._layout.addWidget(self.format_label, 8, 0, 1, 2)
        c = self.format_value = QComboBox(self)
        from calibre.ebooks.oeb.polish.create import valid_empty_formats
        possible_formats = [''] + sorted(x.upper() for x in valid_empty_formats)
        c.addItems(possible_formats)
        c.setToolTip(_('Also create an empty book format file that you can subsequently edit'))
        if gprefs.get('create_empty_epub_file', False):
            # Migration of the check box
            gprefs.set('create_empty_format_file', 'epub')
            del gprefs['create_empty_epub_file']
        use_format = gprefs.get('create_empty_format_file', '').upper()
        try:
            c.setCurrentIndex(possible_formats.index(use_format))
        except Exception:
            pass
        self._layout.addWidget(c, 9, 0, 1, 1)

        button_box = self.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)
        self._layout.addWidget(button_box, 10, 0, 1, -1)
        self.resize(self.sizeHint())

    def accept(self):
        gprefs['create_empty_format_file'] = self.format_value.currentText().lower()
        return QDialog.accept(self)

    def reset_author(self, *args):
        self.authors_combo.setEditText(_('Unknown'))

    def reset_series(self):
        self.series_combo.setEditText('')

    def initialize_authors(self, db, author):
        au = author
        if not au:
            au = _('Unknown')
        self.authors_combo.show_initial_value(au.replace('|', ','))

        self.authors_combo.set_separator('&')
        self.authors_combo.set_space_before_sep(True)
        self.authors_combo.set_add_separator(tweaks['authors_completer_append_separator'])
        self.authors_combo.update_items_cache(db.all_author_names())

    def initialize_series(self, db, series):
        self.series_combo.show_initial_value(series or '')
        self.series_combo.update_items_cache(db.all_series_names())
        self.series_combo.set_separator(None)

    @property
    def qty_to_add(self):
        return self.qty_spinbox.value()

    @property
    def selected_authors(self):
        return string_to_authors(unicode(self.authors_combo.text()))

    @property
    def selected_series(self):
        return unicode(self.series_combo.text())

    @property
    def selected_title(self):
        return self.title_edit.text().strip()
Ejemplo n.º 8
0
class UArmUI(object):
    def __init__(self, ui, layout):
        self.main_ui = ui
        self.layout = layout
        super(UArmUI, self).__init__()
        self.handler = UArmHandler(self)
        self.lang = self.main_ui.lang
        self.status = 0
        self.set_ui()
        self.set_disable(True)

    def set_ui(self):
        self._set_common_top_ui()
        self._set_tab()
        self._set_common_down_ui()
        self.connect_slot()

    def _set_common_top_ui(self):
        top_frame = QFrame()
        top_frame.setMaximumHeight(60)
        top_layout = QVBoxLayout(top_frame)
        self.layout.addWidget(top_frame)

        common_top_frame = QFrame()
        common_top_frame.setMinimumHeight(50)
        common_top_frame.setMaximumHeight(50)
        common_top_layout = QHBoxLayout(common_top_frame)
        top_layout.addWidget(common_top_frame)
        common_top_layout.addStretch(0)

        label = QLabel(i18n[self.lang]['Type'] + ':')
        self.label_type = QLabel('')
        self.label_type.setStyleSheet('''color: gray;font:bold;''')
        common_top_layout.addWidget(label)
        common_top_layout.addWidget(self.label_type)

        label = QLabel(i18n[self.lang]['Mode'] + ':')
        self.label_mode = QLabel('')
        self.label_mode.setStyleSheet('''color: gray;font:bold;''')
        common_top_layout.addWidget(label)
        common_top_layout.addWidget(self.label_mode)

        label = QLabel(i18n[self.lang]['HardwareVersion'] + ':')
        self.label_hard_version = QLabel('')
        self.label_hard_version.setStyleSheet('''color: gray;font:bold;''')
        common_top_layout.addWidget(label)
        common_top_layout.addWidget(self.label_hard_version)

        label = QLabel(i18n[self.lang]['FirmwareVersion'] + ':')
        self.label_firm_version = QLabel('')
        self.label_firm_version.setStyleSheet('''color: gray;font:bold;''')
        common_top_layout.addWidget(label)
        common_top_layout.addWidget(self.label_firm_version)

        label_1 = QLabel(i18n[self.lang]['Connected'] + ':')
        self.label_connected = QLabel()
        img = QImage()
        self.label_connected.setMaximumHeight(20)
        self.label_connected.setMaximumWidth(20)
        self.label_connected.setScaledContents(True)
        if img.load(disconnect_icon_path):
            self.label_connected.setPixmap(QPixmap.fromImage(img))

        self.lnt_addr = QLineEdit('COM12')
        self.lnt_addr.setMaximumWidth(50)
        self.lnt_addr.setMinimumWidth(30)
        self.btn_connect = QPushButton(i18n[self.lang]['Connect'])
        # self.btn_connect.setMaximumWidth(50)

        # common_top_layout.addStretch(0)
        common_top_layout.setSpacing(10)
        common_top_layout.addWidget(label_1)
        common_top_layout.addWidget(self.label_connected)
        common_top_layout.addWidget(self.lnt_addr)
        common_top_layout.addWidget(self.btn_connect)

    def _set_common_down_ui(self):
        slider_frame = QFrame()
        slider_layout = QGridLayout(slider_frame)
        self.layout.addWidget(slider_frame)

        label = QLabel(i18n[self.lang]['Speed'] + ':')
        self.slider_speed = QSlider(Qt.Horizontal)
        self.spinbox_speed = QSpinBox()
        self.slider_speed.setMinimum(1)
        self.slider_speed.setMaximum(100000)
        self.slider_speed.setValue(10000)
        self.spinbox_speed.setSingleStep(1)
        self.spinbox_speed.setMinimum(1)
        self.spinbox_speed.setMaximum(100000)
        self.spinbox_speed.setValue(10000)
        slider_layout.addWidget(label, 0, 0)
        slider_layout.addWidget(self.slider_speed, 0, 1)
        slider_layout.addWidget(self.spinbox_speed, 0, 2)

        # label = QLabel(i18n[self.lang]['Acc'] + ':')
        # self.slider_acc = QSlider(Qt.Horizontal)
        # self.spinbox_acc = QSpinBox()
        # self.slider_acc.setMinimum(1)
        # self.slider_acc.setMaximum(100000)
        # self.slider_acc.setValue(5000)
        # self.spinbox_acc.setSingleStep(1)
        # self.spinbox_acc.setMinimum(1)
        # self.spinbox_acc.setMaximum(100000)
        # self.spinbox_acc.setValue(5000)
        # slider_layout.addWidget(label, 0, 3)
        # slider_layout.addWidget(self.slider_acc, 0, 4)
        # slider_layout.addWidget(self.spinbox_acc, 0, 5)

        btn_frame = QFrame()
        btn_layout = QGridLayout(btn_frame)
        self.layout.addWidget(btn_frame)

        self.btn_get_device_info = QPushButton(i18n[self.lang]['GetDeviceInfo'])
        self.btn_get_position = QPushButton(i18n[self.lang]['GetPosition'])
        self.btn_get_polar = QPushButton(i18n[self.lang]['GetPolar'])
        self.btn_get_servo_angle = QPushButton(i18n[self.lang]['GetServoAngle'])
        self.btn_get_mode = QPushButton(i18n[self.lang]['GetMode'])

        btn_layout.addWidget(self.btn_get_device_info, 0, 0)
        btn_layout.addWidget(self.btn_get_position, 0, 1)
        btn_layout.addWidget(self.btn_get_polar, 0, 2)
        btn_layout.addWidget(self.btn_get_servo_angle, 0, 3)
        btn_layout.addWidget(self.btn_get_mode, 0, 4)

        self.combobox_servo = QComboBox()
        self.combobox_servo.setStyleSheet('''color: blue;''')
        for item in ['axis-1', 'axis-2', 'axis-3', 'axis-all']:
            self.combobox_servo.addItem(item)
        self.combobox_servo.setCurrentIndex(0)
        btn_layout.addWidget(self.combobox_servo, 0, 0)

        self.btn_servo_attach = QPushButton(i18n[self.lang]['ServoAttach'])
        self.btn_servo_detach = QPushButton(i18n[self.lang]['ServoDetach'])
        self.combobox_mode = QComboBox()
        self.combobox_mode.setStyleSheet('''color: blue;''')
        for item in ['normal', 'laser', '3D', 'pen']:
            self.combobox_mode.addItem(item)
            self.combobox_mode.setCurrentIndex(0)
        self.btn_set_mode = QPushButton(i18n[self.lang]['SetMode'])

        btn_layout.addWidget(self.combobox_servo, 1, 0)
        btn_layout.addWidget(self.btn_servo_attach, 1, 1)
        btn_layout.addWidget(self.btn_servo_detach, 1, 2)
        btn_layout.addWidget(self.combobox_mode, 1, 3)
        btn_layout.addWidget(self.btn_set_mode, 1, 4)

        self.btn_reset = QPushButton(i18n[self.lang]['Reset'])
        self.btn_pump_on = QPushButton(i18n[self.lang]['PumpOn'])
        self.btn_pump_off = QPushButton(i18n[self.lang]['PumpOff'])
        self.btn_gripper_catch = QPushButton(i18n[self.lang]['GripperCatch'])
        self.btn_gripper_release = QPushButton(i18n[self.lang]['GripperRelease'])
        btn_layout.addWidget(self.btn_reset, 2, 0)
        btn_layout.addWidget(self.btn_pump_on, 2, 1)
        btn_layout.addWidget(self.btn_pump_off, 2, 2)
        btn_layout.addWidget(self.btn_gripper_catch, 2, 3)
        btn_layout.addWidget(self.btn_gripper_release, 2, 4)

    @staticmethod
    def slider_spinbox_related(value, master=None, slave=None, scale=1):
        try:
            slave.setValue(value * scale)
        except Exception as e:
            print(e)

    def connect_slot(self):
        self.btn_connect.clicked.connect(self.connect)
        self.slider_speed.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.spinbox_speed, scale=1))
        self.spinbox_speed.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.slider_speed, scale=1))
        # self.slider_acc.valueChanged.connect(
        #     functools.partial(self.slider_spinbox_related, slave=self.spinbox_acc, scale=1))
        # self.spinbox_acc.valueChanged.connect(
        #     functools.partial(self.slider_spinbox_related, slave=self.slider_acc, scale=1))
        self.btn_get_device_info.clicked.connect(self.get_device_info)
        self.btn_get_position.clicked.connect(self.get_position)
        self.btn_get_polar.clicked.connect(self.get_polar)
        self.btn_get_servo_angle.clicked.connect(self.get_servo_angle)
        self.btn_get_mode.clicked.connect(self.get_mode)

        self.btn_servo_attach.clicked.connect(self.set_servo_attach)
        self.btn_servo_detach.clicked.connect(self.set_servo_detach)
        self.btn_set_mode.clicked.connect(self.set_mode)

        self.btn_reset.clicked.connect(self.reset)
        self.btn_pump_on.clicked.connect(self.pump_on)
        self.btn_pump_off.clicked.connect(self.pump_off)
        self.btn_gripper_catch.clicked.connect(self.gripper_catch)
        self.btn_gripper_release.clicked.connect(self.gripper_release)

    def reset_flag(self):
        self.cartesian_ui.reset_flag()
        self.axis_ui.reset_flag()

    def update_connect_status(self, item):
        try:
            img = QImage()
            if item and self.status != 1:
                self.status = 1
                logger.info('connect to {} success'.format(self.handler.port))
                if img.load(connect_icon_path):
                    self.label_connected.setPixmap(QPixmap.fromImage(img))
                    self.btn_connect.setText(i18n[self.lang]['Disconnect'])
                    self.btn_connect.setStyleSheet('''color: red;font:bold;''')
                self.set_disable(False)
            elif not item and self.status != 0:
                self.status = 0
                logger.info('disconnect from {0} or failed connect {0}'.format(self.handler.port))
                self.handler.cmd_que.queue.clear()
                if img.load(disconnect_icon_path):
                    self.label_connected.setPixmap(QPixmap.fromImage(img))
                    self.btn_connect.setText(i18n[self.lang]['Connect'])
                    self.btn_connect.setStyleSheet('''color: green;font:bold;''')
                self.set_disable(True)
        except Exception as e:
            print(e)

    def connect(self):
        try:
            if str(self.btn_connect.text()) == i18n[self.lang]['Connect']:
                addr = self.lnt_addr.text().strip()
                if addr == 'auto':
                    addr = None
                self.btn_connect.setText('Connecting')
                self.status = 2
                self.btn_connect.setStyleSheet('''color: orange;font:bold;''')
                self.handler.connect(addr)
                # if self.window.connect(addr, report_type=report_type):
                #     self.btn_connect.setText(self.disconnect_label)
                #     self.btn_connect.setStyleSheet('''color: red;font:bold;''')
            elif str(self.btn_connect.text()) == i18n[self.lang]['Disconnect']:
                self.handler.disconnect()
                self.btn_connect.setText(i18n[self.lang]['Connect'])
                self.btn_connect.setStyleSheet('''color: green;font:bold;''')
        except Exception as e:
            print(e)

    def get_device_info(self, event):
        try:
            item = {
                'cmd': 'get_device_info',
            }
            self.handler.put_cmd_que(item)
        except Exception as e:
            print(e)

    def get_mode(self, event):
        try:
            item = {
                'cmd': 'get_mode',
            }
            self.handler.put_cmd_que(item)
        except Exception as e:
            print(e)

    def get_position(self, event):
        try:
            item = {
                'cmd': 'get_position',
            }
            self.handler.put_cmd_que(item)
        except Exception as e:
            print(e)

    def get_polar(self, event):
        try:
            item = {
                'cmd': 'get_polar',
            }
            self.handler.put_cmd_que(item)
        except Exception as e:
            print(e)

    def get_servo_angle(self, event):
        try:
            item = {
                'cmd': 'get_servo_angle',
            }
            self.handler.put_cmd_que(item)
        except Exception as e:
            print(e)

    def set_servo_attach(self, event):
        try:
            text = self.combobox_servo.currentText()
            if text == 'axis-all':
                servo_id = None
            else:
                servo_id = int(self.combobox_servo.currentIndex())
            item = {
                'cmd': 'set_servo_attach',
                'kwargs': {
                    'servo_id': servo_id
                }
            }
            self.handler.put_cmd_que(item)
        except Exception as e:
            print(e)

    def set_servo_detach(self, event):
        try:
            text = self.combobox_servo.currentText()
            if text == 'axis-all':
                servo_id = None
            else:
                servo_id = int(self.combobox_servo.currentIndex())
            item = {
                'cmd': 'set_servo_detach',
                'kwargs': {
                    'servo_id': servo_id
                }
            }
            self.handler.put_cmd_que(item)
        except Exception as e:
            print(e)

    def pump_on(self, event):
        try:
            item = {
                'cmd': 'set_pump',
                'kwargs': {
                    'on': True
                }
            }
            self.handler.put_cmd_que(item)
        except Exception as e:
            print(e)

    def pump_off(self, event):
        try:
            item = {
                'cmd': 'set_pump',
                'kwargs': {
                    'on': False
                }
            }
            self.handler.put_cmd_que(item)
        except Exception as e:
            print(e)

    def gripper_catch(self, event):
        try:
            item = {
                'cmd': 'set_gripper',
                'kwargs': {
                    'catch': True
                }
            }
            self.handler.put_cmd_que(item)
        except Exception as e:
            print(e)

    def gripper_release(self, event):
        try:
            item = {
                'cmd': 'set_gripper',
                'kwargs': {
                    'catch': False
                }
            }
            self.handler.put_cmd_que(item)
        except Exception as e:
            print(e)

    def set_mode(self, event):
        try:
            mode = self.combobox_mode.currentIndex()
            item = {
                'cmd': 'set_mode',
                'kwargs': {
                    'mode': int(mode)
                }
            }
            self.handler.put_cmd_que(item)
        except Exception as e:
            print(e)

    def reset(self, event):
        try:
            self.handler.cmd_que.queue.clear()
            item = {
                'cmd': 'reset',
                'kwargs': {
                    'speed': self.spinbox_speed.value(),
                    'wait': False,
                }
            }
            self.handler.put_cmd_que(item)
            self.reset_flag()
        except Exception as e:
            print(e)

    @staticmethod
    def slider_spinbox_related(value, master=None, slave=None, scale=1):
        try:
            slave.setValue(value * scale)
        except Exception as e:
            print(e)

    def _set_tab(self):
        tab_widget = QTabWidget()
        tab_widget.setMaximumHeight(self.main_ui.window.geometry().height() // 2)
        self.layout.addWidget(tab_widget)

        toolBox1 = QToolBox()
        toolBox2 = QToolBox()

        groupBox1 = QGroupBox()
        groupBox2 = QGroupBox()

        toolBox1.addItem(groupBox1, "")
        toolBox2.addItem(groupBox2, "")

        tab_widget.addTab(toolBox1, i18n[self.lang]['Angle'])
        tab_widget.addTab(toolBox2, i18n[self.lang]['Coordinate'])

        joint_layout = QVBoxLayout(groupBox1)
        cartesian_layout = QVBoxLayout(groupBox2)

        self.cartesian_ui = CoordinateUI(self, cartesian_layout)
        self.axis_ui = AngleUI(self, joint_layout)

    def update_device_info(self, device_info):
        if device_info is not None:
            self.label_type.setText(str(device_info.get('device_type', None)))
            self.label_hard_version.setText(str(device_info.get('hardware_version', None)))
            self.label_firm_version.setText(str(device_info.get('firmware_version', None)))

    def update_mode(self, mode):
        if mode is not None:
            if mode == 0:
                mode_str = 'Normal'
            elif mode == 1:
                mode_str = 'Laser'
            elif mode == 2:
                mode_str = '3D'
            elif mode == 3:
                mode_str = 'Pen'
            else:
                mode_str = self.label_mode.text()
            self.label_mode.setText(mode_str)

    def set_disable(self, disable):
        try:
            self.btn_get_device_info.setDisabled(disable)
            self.btn_get_position.setDisabled(disable)
            self.btn_get_polar.setDisabled(disable)
            self.btn_get_servo_angle.setDisabled(disable)
            self.btn_get_mode.setDisabled(disable)
            self.combobox_servo.setDisabled(disable)
            self.combobox_mode.setDisabled(disable)
            self.btn_servo_attach.setDisabled(disable)
            self.btn_servo_detach.setDisabled(disable)
            self.btn_reset.setDisabled(disable)
            self.btn_pump_on.setDisabled(disable)
            self.btn_pump_off.setDisabled(disable)
            self.btn_gripper_catch.setDisabled(disable)
            self.btn_gripper_release.setDisabled(disable)

            self.slider_speed.setDisabled(disable)
            self.spinbox_speed.setDisabled(disable)
            # self.slider_acc.setDisabled(disable)
            # self.spinbox_acc.setDisabled(disable)

            self.axis_ui.set_disable(disable)
            self.cartesian_ui.set_disable(disable)
        except Exception as e:
            print(e)
Ejemplo n.º 9
0
class LibraryCodesTab(QWidget):
    def __init__(self, mygui, myguidb, mymainprefs, myparam_dict, myuiexit,
                 mysavedialoggeometry):
        super(LibraryCodesTab, self).__init__()
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.gui = mygui
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.guidb = myguidb
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.lib_path = self.gui.library_view.model().db.library_path
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.mytabprefs = mymainprefs
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.param_dict = myparam_dict
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.ui_exit = myuiexit
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.save_dialog_geometry = mysavedialoggeometry
        #-----------------------------------------------------
        #-----------------------------------------------------
        font = QFont()
        font.setBold(False)
        font.setPointSize(10)
        #-----------------------------------------------------
        self.layout_top = QVBoxLayout()
        self.layout_top.setSpacing(0)
        self.layout_top.setAlignment(Qt.AlignLeft)
        self.setLayout(self.layout_top)
        #-----------------------------------------------------
        self.scroll_area_frame = QScrollArea()
        self.scroll_area_frame.setAlignment(Qt.AlignLeft)
        self.scroll_area_frame.setWidgetResizable(True)
        self.scroll_area_frame.ensureVisible(400, 400)

        self.layout_top.addWidget(
            self.scroll_area_frame
        )  # the scroll area is now the child of the parent of self.layout_top

        # NOTE: the self.scroll_area_frame.setWidget(self.scroll_widget) is at the end of the init() AFTER all children have been created and assigned to a layout...

        #-----------------------------------------------------
        self.scroll_widget = QWidget()
        self.layout_top.addWidget(
            self.scroll_widget
        )  # causes automatic reparenting of QWidget to the parent of self.layout_top, which is:  self .
        #-----------------------------------------------------
        self.layout_frame = QVBoxLayout()
        self.layout_frame.setSpacing(0)
        self.layout_frame.setAlignment(Qt.AlignLeft)

        self.scroll_widget.setLayout(
            self.layout_frame
        )  # causes automatic reparenting of any widget later added to self.layout_frame to the parent of self.layout_frame, which is:  QWidget .

        #-----------------------------------------------------
        self.lc_groupbox = QGroupBox('Settings:')
        self.lc_groupbox.setMaximumWidth(400)
        self.lc_groupbox.setToolTip(
            "<p style='white-space:wrap'>The settings that control 'Library Codes'.  Using only ISBN or ISSN or Author/Title, Library Codes for selected books will be derived using the Current Settings."
        )
        self.layout_frame.addWidget(self.lc_groupbox)

        self.lc_layout = QGridLayout()
        self.lc_groupbox.setLayout(self.lc_layout)
        #-----------------------------------------------------
        #-----------------------------------------------------
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.spacing0 = QLabel()
        self.layout_frame.addWidget(self.spacing0)
        self.spacing0.setMaximumHeight(20)
        #-----------------------------------------------------
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.button_box = QDialogButtonBox()
        self.button_box.setOrientation(Qt.Horizontal)
        self.button_box.setCenterButtons(True)

        self.layout_frame.addWidget(self.button_box)
        #-----------------------------------------------------
        #-----------------------------------------------------
        #-----------------------------------------------------
        #-----------------------------------------------------
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.push_button_save_only = QPushButton("Save")
        self.push_button_save_only.clicked.connect(self.save_settings)
        self.push_button_save_only.setDefault(True)
        self.push_button_save_only.setFont(font)
        self.push_button_save_only.setToolTip(
            "<p style='white-space:wrap'>Save all user settings.")
        self.button_box.addButton(self.push_button_save_only, 0)

        self.push_button_exit_only = QPushButton("Exit")
        self.push_button_exit_only.clicked.connect(self.exit_only)
        self.push_button_exit_only.setDefault(False)
        self.push_button_exit_only.setFont(font)
        self.push_button_exit_only.setToolTip(
            "<p style='white-space:wrap'>Exit immediately without saving anything."
        )
        self.button_box.addButton(self.push_button_exit_only, 0)
        #-----------------------------------------------------
        #-----------------------------------------------------
        #-----------------------------------------------------
        #-----------------------------------------------------

        r = 4

        self.ddc_labelname = QLineEdit(self)
        self.ddc_labelname.setText(self.mytabprefs['DDC'])
        self.ddc_labelname.setFont(font)
        self.ddc_labelname.setToolTip(
            "<p style='white-space:wrap'>Custom Column Search/Lookup #name for DDC.<br><br>See:  https://www.oclc.org/dewey/features/summaries.en.html"
        )
        self.ddc_labelname.setMaximumWidth(100)
        self.lc_layout.addWidget(self.ddc_labelname, r, 0)

        self.ddc_activate_checkbox = QCheckBox(
            "Activate 'Dewey Decimal Code' Classification?")
        self.ddc_activate_checkbox.setToolTip(
            "<p style='white-space:wrap'>Do you want to derive DDC?")
        r = r + 1
        self.lc_layout.addWidget(self.ddc_activate_checkbox, r, 0)
        if prefs['DDC_IS_ACTIVE'] == unicode_type(S_TRUE):
            self.ddc_activate_checkbox.setChecked(True)
        else:
            self.ddc_activate_checkbox.setChecked(False)
        #-----------------------------------------------------
        self.spacing1 = QLabel()
        r = r + 1
        self.lc_layout.addWidget(self.spacing1, r, 0)
        self.spacing1.setMaximumHeight(10)
        #-----------------------------------------------------
        self.lcc_labelname = QLineEdit(self)
        self.lcc_labelname.setText(self.mytabprefs['LCC'])
        self.lcc_labelname.setFont(font)
        self.lcc_labelname.setToolTip(
            "<p style='white-space:wrap'>Custom Column Search/Lookup #name for LCC.<br><br>See: http://www.loc.gov/catdir/cpso/lcco/ "
        )
        self.lcc_labelname.setMaximumWidth(100)
        r = r + 4
        self.lc_layout.addWidget(self.lcc_labelname, r, 0)

        self.lcc_activate_checkbox = QCheckBox(
            "Activate 'Library of Congress Code' Classification?")
        self.lcc_activate_checkbox.setToolTip(
            "<p style='white-space:wrap'>Do you want to derive LCC?")
        r = r + 1
        self.lc_layout.addWidget(self.lcc_activate_checkbox, r, 0)
        if prefs['LCC_IS_ACTIVE'] == unicode_type(S_TRUE):
            self.lcc_activate_checkbox.setChecked(True)
        else:
            self.lcc_activate_checkbox.setChecked(False)
        #-----------------------------------------------------
        self.spacing2 = QLabel("")
        r = r + 1
        self.lc_layout.addWidget(self.spacing2, r, 0)
        self.spacing2.setMaximumHeight(10)
        #-----------------------------------------------------

        self.fast_labelname = QLineEdit(self)
        self.fast_labelname.setText(self.mytabprefs['FAST'])
        self.fast_labelname.setFont(font)
        self.fast_labelname.setToolTip(
            "<p style='white-space:wrap'>Custom Column Search/Lookup #name for FAST Tag Values. "
        )
        self.fast_labelname.setMinimumWidth(100)
        self.fast_labelname.setMaximumWidth(100)
        r = r + 4
        self.lc_layout.addWidget(self.fast_labelname, r, 0)

        self.fast_activate_checkbox = QCheckBox("Activate 'FAST' Tags?")
        self.fast_activate_checkbox.setToolTip(
            "<p style='white-space:wrap'>Do you want to derive FAST Tags?\
                                                                                                                    <br><br>Text.  Behaves like Tags. Not Names.<br><br>"
        )
        r = r + 1
        self.lc_layout.addWidget(self.fast_activate_checkbox, r, 0)
        if prefs['FAST_IS_ACTIVE'] == unicode_type(S_TRUE):
            self.fast_activate_checkbox.setChecked(True)
        else:
            self.fast_activate_checkbox.setChecked(False)

        #-----------------------------------------------------
        self.spacing6 = QLabel("")
        r = r + 1
        self.lc_layout.addWidget(self.spacing6, r, 0)
        self.spacing6.setMaximumHeight(10)
        #-----------------------------------------------------

        self.oclc_labelname = QLineEdit(self)
        self.oclc_labelname.setText(self.mytabprefs['OCLC'])
        self.oclc_labelname.setFont(font)
        self.oclc_labelname.setToolTip(
            "<p style='white-space:wrap'>Custom Column Search/Lookup #name for OCLC-OWI.<br><br>See: #http://classify.oclc.org/classify2/   "
        )
        self.oclc_labelname.setMaximumWidth(100)
        r = r + 4
        self.lc_layout.addWidget(self.oclc_labelname, r, 0)

        self.oclc_activate_checkbox = QCheckBox(
            "Activate 'Online Computer Library Center' Work ID Code?")
        self.oclc_activate_checkbox.setToolTip(
            "<p style='white-space:wrap'>Do you want to derive OCLC-OWI?")
        r = r + 1
        self.lc_layout.addWidget(self.oclc_activate_checkbox, r, 0)
        if self.mytabprefs['OCLC_IS_ACTIVE'] == unicode_type(S_TRUE):
            self.oclc_activate_checkbox.setChecked(True)
        else:
            self.oclc_activate_checkbox.setChecked(False)
        #-----------------------------------------------------
        self.spacing5 = QLabel("")
        r = r + 1
        self.lc_layout.addWidget(self.spacing5, r, 0)
        self.spacing5.setMaximumHeight(10)
        #-----------------------------------------------------
        self.lc_author_details_labelname = QLineEdit(self)
        self.lc_author_details_labelname.setText(
            self.mytabprefs['EXTRA_AUTHOR_DETAILS'])
        self.lc_author_details_labelname.setFont(font)
        self.lc_author_details_labelname.setToolTip(
            "<p style='white-space:wrap'>Custom Column Search/Lookup #name for 'LC Extra Author Details'.\
                                                                                                                              <br><br>Text.  Behaves like Tags. Not Names.<br><br>"
        )
        self.lc_author_details_labelname.setMaximumWidth(100)
        r = r + 4
        self.lc_layout.addWidget(self.lc_author_details_labelname, r, 0)

        self.lc_author_details_checkbox = QCheckBox(
            "Activate 'Library Codes Extra Author Details'?")
        self.lc_author_details_checkbox.setToolTip(
            "<p style='white-space:wrap'>Do you want to add (never delete or replace) any available Tag-like values to this Custom Column if they are associated with the OCLC-OWI Identifier?"
        )
        r = r + 1
        self.lc_layout.addWidget(self.lc_author_details_checkbox, r, 0)
        if self.mytabprefs['EXTRA_AUTHOR_DETAILS_IS_ACTIVE'] == unicode_type(
                S_TRUE):
            self.lc_author_details_checkbox.setChecked(True)
        else:
            self.lc_author_details_checkbox.setChecked(False)
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.spacing4 = QLabel()
        r = r + 1
        self.lc_layout.addWidget(self.spacing4, r, 0)
        self.spacing4.setMaximumHeight(10)
        #-----------------------------------------------------
        font.setBold(False)
        font.setPointSize(7)
        #-----------------------------------------------------
        self.push_button_autoadd_custom_columns = QPushButton(
            "Automatically Add Activated Custom Columns?")
        self.push_button_autoadd_custom_columns.clicked.connect(
            self.autoadd_custom_columns)
        self.push_button_autoadd_custom_columns.setDefault(False)
        self.push_button_autoadd_custom_columns.setFont(font)
        self.push_button_autoadd_custom_columns.setToolTip(
            "<p style='white-space:wrap'>Do you want to automatically add the Custom Columns selected above?<br><br>If you have any issues, please add them manually."
        )
        r = r + 4
        self.lc_layout.addWidget(self.push_button_autoadd_custom_columns, r, 0)
        self.push_button_autoadd_custom_columns.setMaximumWidth(250)
        #-----------------------------------------------------
        self.lc_custom_columns_generation_label = QLabel()
        r = r + 1
        self.lc_layout.addWidget(self.lc_custom_columns_generation_label, r, 0)
        self.lc_custom_columns_generation_label.setText(
            "                                                              ")
        self.lc_custom_columns_generation_label.setMaximumHeight(10)
        self.lc_custom_columns_generation_label.setFont(font)

        self.oclc_identifier_only_checkbox = QCheckBox(
            "Always Create OCLC-OWI as an 'Identifier' (à la ISBN)?")
        self.oclc_identifier_only_checkbox.setToolTip(
            "<p style='white-space:wrap'>Do you want to update Calibre's Identifiers for an Identifier of 'OCLC-OWI',\
                                                                                                                                 regardless of whether you want its own Custom Column updated?\
                                                                                                                                <br><br>REQUIRED to derive DDC/LCC using Author/Title."
        )
        r = r + 2
        self.lc_layout.addWidget(self.oclc_identifier_only_checkbox, r, 0)
        if prefs['OCLC_IDENTIFIER'] == unicode_type(S_TRUE):
            self.oclc_identifier_only_checkbox.setChecked(True)
        else:
            self.oclc_identifier_only_checkbox.setChecked(False)

        #-----------------------------------------------------
        self.spacing3 = QLabel("")
        r = r + 1
        self.lc_layout.addWidget(self.spacing3, r, 0)
        self.spacing3.setMaximumHeight(10)
        #-----------------------------------------------------
        font.setBold(False)
        font.setPointSize(10)
        #-----------------------------------------------------
        self.lc_genre_labelname = QLineEdit(self)
        self.lc_genre_labelname.setText(self.mytabprefs['GENRE'])
        self.lc_genre_labelname.setFont(font)
        self.lc_genre_labelname.setToolTip(
            "<p style='white-space:wrap'>Custom Column Search/Lookup #name for 'Genre'.\
                                                                                                                              <br><br>Text.  Behaves like Tags.<br><br>"
        )
        self.lc_genre_labelname.setMaximumWidth(100)
        r = r + 1
        self.lc_layout.addWidget(self.lc_genre_labelname, r, 0)

        self.lc_checkbox_buttongroup = QButtonGroup()
        self.lc_checkbox_buttongroup.setExclusive(True)

        self.lc_genre_ddc_checkbox = QCheckBox(
            "Update 'Genre' using DDC-to-Genre Mappings?")
        self.lc_genre_ddc_checkbox.setToolTip(
            "<p style='white-space:wrap'>Do you want LC to update 'Genre' using the DDC-to-Genre mapping in Table _lc_genre_mapping?"
        )
        r = r + 1
        self.lc_layout.addWidget(self.lc_genre_ddc_checkbox, r, 0)

        self.lc_genre_lcc_checkbox = QCheckBox(
            "Update 'Genre' using LCC-to-Genre Mappings?")
        self.lc_genre_lcc_checkbox.setToolTip(
            "<p style='white-space:wrap'>Do you want LC to update 'Genre' using the LCC-to-Genre mapping in Table _lc_genre_mapping?"
        )
        r = r + 1
        self.lc_layout.addWidget(self.lc_genre_lcc_checkbox, r, 0)

        self.lc_genre_inactive_checkbox = QCheckBox(
            "Do not update 'Genre' at all")
        self.lc_genre_inactive_checkbox.setToolTip(
            "<p style='white-space:wrap'>Do no 'Genre' processing at all?")
        r = r + 1
        self.lc_layout.addWidget(self.lc_genre_inactive_checkbox, r, 0)

        self.lc_checkbox_buttongroup.addButton(self.lc_genre_ddc_checkbox)
        self.lc_checkbox_buttongroup.addButton(self.lc_genre_lcc_checkbox)
        self.lc_checkbox_buttongroup.addButton(self.lc_genre_inactive_checkbox)

        if self.mytabprefs['GENRE_DDC_IS_ACTIVE'] == unicode_type(S_TRUE):
            self.lc_genre_ddc_checkbox.setChecked(True)
        elif self.mytabprefs['GENRE_LCC_IS_ACTIVE'] == unicode_type(S_TRUE):
            self.lc_genre_lcc_checkbox.setChecked(True)
        elif self.mytabprefs['GENRE_IS_INACTIVE'] == unicode_type(S_TRUE):
            self.lc_genre_inactive_checkbox.setChecked(True)

        self.lc_exact_match_checkbox = QCheckBox(
            "DDC: Require an 'Exact Match', not a 'Best Match'?")
        self.lc_exact_match_checkbox.setToolTip(
            "<p style='white-space:wrap'>Check this checkbox if you want an exact DDC match to be required in Table _lc_genre_mapping.  Otherwise, a 'best match' will be used via progressive shortening from right to left, but not past any decimal point.  If there is no decimal point in a book's DDC, then no progressive shortening will be performed at all."
        )
        r = r + 1
        self.lc_layout.addWidget(self.lc_exact_match_checkbox, r, 0)

        if self.mytabprefs['GENRE_EXACT_MATCH'] == unicode_type(S_TRUE):
            self.lc_exact_match_checkbox.setChecked(True)

        self.spin_lcc = QSpinBox(self)
        self.spin_lcc.setMinimum(1)
        self.spin_lcc.setMaximum(50)
        self.spin_lcc.setProperty('value', prefs['GENRE_LCC_MATCH_LENGTH'])
        self.spin_lcc.setMaximumWidth(250)
        self.spin_lcc.setSuffix("    LCC: Maximum Length to Match")
        self.spin_lcc.setToolTip(
            "<p style='white-space:nowrap'>Maximum number of characters in the LCC that should be used to map to the 'Genre', starting from the left.  A maximum of 1 guarantees a (broad) match.\
                                                                                                   <br><br>LCCs are structured with either 1 or 2 beginning letters, so 2-character LCCs have special matching logic.\
                                                                                                   <br><br>Example:   Assume maximum = 2 for a LCC of 'Q1':  Q1 would be attempted.  If it failed, because the 2nd digit is a number, 'Q' would be attempted.\
                                                                                                   <br><br>Example:   Assume maximum = 2 for a LCC of 'PN1969.C65':  PN would be attempted.  If it failed, nothing else would be attempted.\
                                                                                                   <br><br>Example:   Assume maximum = 4 for a LCC of 'PN1969.C65':  PN19 would be attempted.  If it failed, nothing else would be attempted.\
                                                                                                   <br><br>Example:   Assume maximum = 4 for a LCC of 'Q1':  Q1 would be attempted.  If it failed, because the 2nd digit is a number, 'Q' would be attempted.\
                                                                                                   <br><br>Example:   Assume maximum = 4 for a LCC of 'Q389':  Q389 would be attempted.  If it failed, nothing else would be attempted."
        )
        r = r + 2
        self.lc_layout.addWidget(self.spin_lcc, r, 0)

        #-----------------------------------------------------
        #-----------------------------------------------------
        #-----------------------------------------------------
        #-----------------------------------------------------
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.scroll_widget.resize(self.sizeHint())
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.scroll_area_frame.setWidget(
            self.scroll_widget
        )  # now that all widgets have been created and assigned to a layout...
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.scroll_area_frame.resize(self.sizeHint())
        #-----------------------------------------------------
        #-----------------------------------------------------
        self.resize(self.sizeHint())

    #-----------------------------------------------------------------------------------------
    def validate(self):
        return True

    #-----------------------------------------------------------------------------------------
    def autoadd_custom_columns(self):
        number_active = self.save_settings()
        if number_active == 0:
            return error_dialog(
                self.gui,
                _('Automatically Add Custom Columns'),
                _('No Activated Library Codes Custom Columns Found.  Nothing to Add.'
                  ),
                show=True)
        self.cli_param_list = self.create_cli_parameters()
        is_valid, restart_required = self.create_new_lc_custom_columns(
            self.cli_param_list)
        if is_valid:
            if restart_required:
                self.lc_custom_columns_generation_label.setText(
                    "Addition of Custom Columns Complete.  Restart Calibre Now."
                )
                self.repaint()
                info_dialog(
                    self.gui, 'Automatically Add Custom Columns',
                    'All Selected Custom Customs Were Added If They Did Not Already Exist.  Please Restart Calibre now.'
                ).show()
            else:
                self.lc_custom_columns_generation_label.setText(
                    "Selected Custom Columns Already Exist.  Nothing Done.")
                self.repaint()
        else:
            self.lc_custom_columns_generation_label.setText(
                "Not Completed.  Please Restart Calibre, then Add Manually.")
            self.repaint()
            msg = "Fatal error experienced in adding new Custom Columns."
            error_dialog(self.gui,
                         _('Automatically Add Custom Columns'),
                         _(msg),
                         show=True)

    #-----------------------------------------------------------------------------------------
    def create_cli_parameters(self):

        try:
            del self.cli_param_list
        except:
            pass

        self.cli_param_list = []
        temp_list = []
        cc_taglike_list = []
        cc_fast_name = ""

        if self.mytabprefs['DDC_IS_ACTIVE'] == unicode_type(S_TRUE):
            cc = self.mytabprefs['DDC']
            if cc > '#':
                cc = cc.replace('#', "").strip()
                cc = unicode_type(cc)
                temp_list.append(cc)
            else:
                error_dialog(self.gui,
                             _('Automatically Add Custom Columns'),
                             _('Illogical DDC Settings.  Please Correct.'),
                             show=True)
                return self.cli_param_list

        if self.mytabprefs['LCC_IS_ACTIVE'] == unicode_type(S_TRUE):
            cc = self.mytabprefs['LCC']
            if cc > '#':
                cc = cc.replace('#', "").strip()
                cc = unicode_type(cc)
                temp_list.append(cc)
            else:
                error_dialog(self.gui,
                             _('Automatically Add Custom Columns'),
                             _('Illogical LCC Settings.  Please Correct.'),
                             show=True)
                return self.cli_param_list

        if self.mytabprefs['FAST_IS_ACTIVE'] == unicode_type(S_TRUE):
            cc = self.mytabprefs['FAST']
            if cc > '#':
                cc = cc.replace('#', "").strip()
                cc = unicode_type(cc)
                temp_list.append(cc)
                cc_taglike_list.append(cc)
                cc_fast_name = cc
            else:
                error_dialog(self.gui,
                             _('Automatically Add Custom Columns'),
                             _('Illogical FAST Settings.  Please Correct.'),
                             show=True)
                return self.cli_param_list

        if self.mytabprefs['OCLC_IS_ACTIVE'] == unicode_type(S_TRUE):
            cc = self.mytabprefs['OCLC']
            if cc > '#':
                cc = cc.replace('#', "").strip()
                cc = unicode_type(cc)
                temp_list.append(cc)
            else:
                error_dialog(self.gui,
                             _('Automatically Add Custom Columns'),
                             _('Illogical OCLC Settings.  Please Correct.'),
                             show=True)
                return self.cli_param_list

        if self.mytabprefs['EXTRA_AUTHOR_DETAILS_IS_ACTIVE'] == unicode_type(
                S_TRUE):
            cc = self.mytabprefs['EXTRA_AUTHOR_DETAILS']
            if cc > '#':
                cc = cc.replace('#', "").strip()
                cc = unicode_type(cc)
                temp_list.append(cc)
                cc_taglike_list.append(cc)
            else:
                error_dialog(
                    self.gui,
                    _('Automatically Add Custom Columns'),
                    _('Illogical LC Extra Author Details Settings.  Please Correct.'
                      ),
                    show=True)
                return self.cli_param_list
        else:
            pass

        if len(temp_list) == 0:
            del temp_list
            error_dialog(self.gui,
                         _('Automatically Add Custom Columns'),
                         _('Nothing to do.  Please Review Settings.'),
                         show=True)
            return self.cli_param_list

        cc_to_add_list = []

        # for each cc currently set to active, create a parameter...but only if the cc does NOT already exist...
        my_db, my_cursor, is_valid = self.apsw_connect_to_library()
        if not is_valid:
            error_dialog(self.gui,
                         _('Automatically Add Custom Columns'),
                         _('Database Connection Error.  Restart Calibre.'),
                         show=True)
            return

        self.lc_custom_columns_generation_label.setText(
            "...Adding Custom Columns...")
        self.repaint()

        mysql = "SELECT label,name FROM custom_columns"
        my_cursor.execute(mysql)
        tmp_rows = my_cursor.fetchall()
        if not tmp_rows:
            for cc in temp_list:
                cc_to_add_list.append(cc)
            #END FOR
        else:
            if len(tmp_rows) == 0:
                for cc in temp_list:
                    cc_to_add_list.append(cc)
                #END FOR
            else:
                for cc in temp_list:
                    label_already_exists = False
                    for row in tmp_rows:
                        label, name = row
                        if unicode_type(label) == unicode_type(cc):
                            label_already_exists = True
                            break
                        else:
                            continue
                    #END FOR
                    if not label_already_exists:
                        cc_to_add_list.append(cc)
                #END FOR
                del tmp_rows
                del temp_list

        if len(cc_to_add_list) == 0:
            return self.cli_param_list

        cc_to_add_list.sort()

        for label in cc_to_add_list:
            label = unicodedata.normalize('NFKD',
                                          label).encode('ascii', 'ignore')
            label = unicode_type(label)
            label = label.lower()
            name = label.upper()
            datatype = 'text'
            if label in cc_taglike_list:
                is_multiple = "--is-multiple"
                if label == cc_fast_name:
                    name = "FAST Tags"
                else:
                    name = '"LC Extra Author Details"'
                param = is_multiple + '|||' + label + '|||' + name + '|||' + datatype
            else:
                param = label + '|||' + name + '|||' + datatype
            param = param.replace("[LIBRARY]", self.lib_path)
            self.cli_param_list.append(param)
        #END FOR

        del cc_to_add_list

        return self.cli_param_list

    #-----------------------------------------------------------------------------------------
    #-----------------------------------------------------------------------------------------
    def apsw_connect_to_library(self):

        my_db = self.gui.library_view.model().db

        self.lib_path = my_db.library_path
        self.lib_path = self.lib_path.replace(os.sep, '/')
        if isbytestring(self.lib_path):
            self.lib_path = self.lib_path.decode(filesystem_encoding)

        path = my_db.library_path
        if isbytestring(path):
            path = path.decode(filesystem_encoding)
        path = path.replace(os.sep, '/')
        path = os.path.join(path, 'metadata.db')
        path = path.replace(os.sep, '/')

        if isbytestring(path):
            path = path.decode(filesystem_encoding)

        if path.endswith("/"):
            path = path[0:-1]

        if path.count("metadata.db") == 0:
            path = path + "/metadata.db"

        try:
            my_db = apsw.Connection(path)
            is_valid = True
        except Exception as e:
            if DEBUG: print("path to metadata.db is: ", path)
            if DEBUG: print("error: ", as_unicode(e))
            is_valid = False
            return None, None, is_valid

        my_cursor = my_db.cursor()

        mysql = "PRAGMA main.busy_timeout = 5000;"  #PRAGMA busy_timeout = milliseconds;
        my_cursor.execute(mysql)

        return my_db, my_cursor, is_valid

    #-----------------------------------------------------------------------------------------
    def exit_only(self):
        self.save_dialog_geometry()  #  inherited from SizePersistedDialog
        self.ui_exit()

    #-----------------------------------------------------------------------------------------
    def save_settings(self):

        self.save_dialog_geometry()  #  inherited from SizePersistedDialog

        self.mytabprefs['DDC'] = self.ddc_labelname.text()
        self.mytabprefs['LCC'] = self.lcc_labelname.text()
        self.mytabprefs['FAST'] = self.fast_labelname.text()
        self.mytabprefs['OCLC'] = self.oclc_labelname.text()

        self.mytabprefs['DDC_IS_ACTIVE'] = unicode_type(
            self.ddc_activate_checkbox.isChecked())
        self.mytabprefs['LCC_IS_ACTIVE'] = unicode_type(
            self.lcc_activate_checkbox.isChecked())
        self.mytabprefs['FAST_IS_ACTIVE'] = unicode_type(
            self.fast_activate_checkbox.isChecked())
        self.mytabprefs['OCLC_IS_ACTIVE'] = unicode_type(
            self.oclc_activate_checkbox.isChecked())
        self.mytabprefs['OCLC_IDENTIFIER'] = unicode_type(
            self.oclc_identifier_only_checkbox.isChecked())

        label = self.mytabprefs['DDC']
        label = unicode_type(label)
        label = unicodedata.normalize('NFKD', label).encode('ascii', 'ignore')
        label = label.lower().strip()
        if not label.startswith("#"):
            label = "#" + label
        if label == "#":
            label = ""
            self.ddc_activate_checkbox.setChecked(False)
        self.mytabprefs['DDC'] = unicode_type(label)

        label = self.mytabprefs['LCC']
        label = unicode_type(label)
        label = unicodedata.normalize('NFKD', label).encode('ascii', 'ignore')
        label = label.lower().strip()
        if not label.startswith("#"):
            label = "#" + label
        if label == "#":
            label = ""
            self.lcc_activate_checkbox.setChecked(False)
        self.mytabprefs['LCC'] = unicode_type(label)

        label = self.mytabprefs['FAST']
        label = unicode_type(label)
        label = unicodedata.normalize('NFKD', label).encode('ascii', 'ignore')
        label = label.lower().strip()
        if not label.startswith("#"):
            label = "#" + label
        if label == "#":
            label = ""
            self.fast_activate_checkbox.setChecked(False)
        self.mytabprefs['FAST'] = unicode_type(label)

        label = self.mytabprefs['OCLC']
        label = unicode_type(label)
        label = unicodedata.normalize('NFKD', label).encode('ascii', 'ignore')
        label = label.lower().strip()
        if not label.startswith("#"):
            label = "#" + label
        if label == "#":
            label = ""
            self.oclc_activate_checkbox.setChecked(False)
        self.mytabprefs['OCLC'] = unicode_type(label)

        if self.mytabprefs['DDC'] == unicode_type(
                "") and self.mytabprefs['LCC'] == unicode_type(
                    "") and self.mytabprefs['FAST'] == unicode_type(
                        "") and self.mytabprefs['OCLC'] == unicode_type(""):
            self.mytabprefs['DDC'] = unicode_type("#ddc")
            self.mytabprefs['LCC'] = unicode_type("#lcc")
            self.mytabprefs['FAST'] = unicode_type("#fast")
            self.mytabprefs['OCLC'] = unicode_type("#oclc_owi")
        else:
            if self.mytabprefs['DDC'] == unicode_type(
                    "") and self.mytabprefs['LCC'] == unicode_type(""):
                self.oclc_identifier_only_checkbox.setChecked(False)
        #---------------------------------------

        s = unicode_type(self.lc_genre_labelname.text())
        s = s.strip()
        if s.startswith("#") and len(s) > 1:
            self.mytabprefs['GENRE'] = unicode_type(s)
            self.mytabprefs['GENRE_DDC_IS_ACTIVE'] = unicode_type(
                self.lc_genre_ddc_checkbox.isChecked())
            self.mytabprefs['GENRE_LCC_IS_ACTIVE'] = unicode_type(
                self.lc_genre_lcc_checkbox.isChecked())
            self.mytabprefs['GENRE_IS_INACTIVE'] = unicode_type(
                self.lc_genre_inactive_checkbox.isChecked())
            self.mytabprefs['GENRE_EXACT_MATCH'] = unicode_type(
                self.lc_exact_match_checkbox.isChecked())
            self.mytabprefs['GENRE_LCC_MATCH_LENGTH'] = self.spin_lcc.value()
        else:
            self.mytabprefs['GENRE'] = unicode_type("#genre")
            self.lc_genre_labelname.setText(unicode_type("#genre"))
            self.lc_genre_ddc_checkbox.setChecked(False)
            self.lc_genre_lcc_checkbox.setChecked(False)
            self.lc_genre_inactive_checkbox.setChecked(True)
            self.mytabprefs['GENRE_DDC_IS_ACTIVE'] = unicode_type(S_FALSE)
            self.mytabprefs['GENRE_LCC_IS_ACTIVE'] = unicode_type(S_FALSE)
            self.mytabprefs['GENRE_IS_INACTIVE'] = unicode_type(S_TRUE)
            self.mytabprefs['GENRE_EXACT_MATCH'] = unicode_type(S_TRUE)
            self.mytabprefs['GENRE_LCC_MATCH_LENGTH'] = 2
            self.repaint()
            sleep(2)

        #---------------------------------------
        #~ for k,v in self.mytabprefs.iteritems():
        for k, v in iteritems(self.mytabprefs):
            v = unicode_type(v)
            v = v.strip()
            prefs[k] = v
        #END FOR
        prefs

        #---------------------------------------

        self.ddc_labelname.setText(self.mytabprefs['DDC'])
        self.lcc_labelname.setText(self.mytabprefs['LCC'])
        self.fast_labelname.setText(self.mytabprefs['FAST'])
        self.oclc_labelname.setText(self.mytabprefs['OCLC'])
        self.repaint()
        sleep(0)

        #~ for k,v in self.mytabprefs.iteritems():
        for k, v in iteritems(self.mytabprefs):
            self.param_dict[k] = v
        #END FOR

        number_active = 0

        if self.mytabprefs['DDC_IS_ACTIVE'] == unicode_type(S_TRUE):
            number_active = number_active + 1
        if self.mytabprefs['LCC_IS_ACTIVE'] == unicode_type(S_TRUE):
            number_active = number_active + 1
        if self.mytabprefs['FAST_IS_ACTIVE'] == unicode_type(S_TRUE):
            number_active = number_active + 1
        if self.mytabprefs['OCLC_IS_ACTIVE'] == unicode_type(S_TRUE):
            number_active = number_active + 1

        self.ddc_name = self.mytabprefs['DDC'].replace("#", "").strip()
        self.lcc_name = self.mytabprefs['LCC'].replace("#", "").strip()
        self.fast_name = self.mytabprefs['FAST'].replace("#", "").strip()
        self.oclc_name = self.mytabprefs['OCLC'].replace("#", "").strip()

        if self.oclc_identifier_only_checkbox.isChecked():
            self.oclc_identifier_is_desired = True
        else:
            self.oclc_identifier_is_desired = False

        return number_active

    #-----------------------------------------------------------------------------------------
    #-----------------------------------------------------------------------------------------
    def create_new_lc_custom_columns(self, execution_param_list):

        if len(self.cli_param_list) == 0:
            return True, False  # successful since the labels already exist; no restart is required.

        dbpath = self.lib_path

        was_successful = True
        restart_required = True

        for param in execution_param_list:
            try:
                lc_cli_add_custom_column(self.guidb, param, dbpath)
            except Exception as e:
                if DEBUG: print("Exception: ", as_unicode(e))
                was_successful = False
                break
        #END FOR

        return was_successful, restart_required

    #-----------------------------------------------------------------------------------------
    #-----------------------------------------------------------------------------------------
    #-----------------------------------------------------------------------------------------
    #-----------------------------------------------------------------------------------------
    #-----------------------------------------------------------------------------------------
    #-----------------------------------------------------------------------------------------


#END of library_codes_dialog.py
Ejemplo n.º 10
0
class BulkSeries(BulkBase):
    def setup_ui(self, parent):
        self.make_widgets(parent, EditWithComplete)
        values = self.all_values = list(self.db.all_custom(num=self.col_id))
        values.sort(key=sort_key)
        self.main_widget.setSizeAdjustPolicy(
            self.main_widget.AdjustToMinimumContentsLengthWithIcon)
        self.main_widget.setMinimumContentsLength(25)
        self.widgets.append(QLabel('', parent))
        w = QWidget(parent)
        layout = QHBoxLayout(w)
        layout.setContentsMargins(0, 0, 0, 0)
        self.remove_series = QCheckBox(parent)
        self.remove_series.setText(_('Remove series'))
        layout.addWidget(self.remove_series)
        self.idx_widget = QCheckBox(parent)
        self.idx_widget.setText(_('Automatically number books'))
        layout.addWidget(self.idx_widget)
        self.force_number = QCheckBox(parent)
        self.force_number.setText(_('Force numbers to start with '))
        layout.addWidget(self.force_number)
        self.series_start_number = QSpinBox(parent)
        self.series_start_number.setMinimum(1)
        self.series_start_number.setMaximum(9999999)
        self.series_start_number.setProperty("value", 1)
        layout.addWidget(self.series_start_number)
        layout.addItem(
            QSpacerItem(20, 10, QSizePolicy.Expanding, QSizePolicy.Minimum))
        self.widgets.append(w)
        self.idx_widget.stateChanged.connect(self.check_changed_checkbox)
        self.force_number.stateChanged.connect(self.check_changed_checkbox)
        self.series_start_number.valueChanged.connect(
            self.check_changed_checkbox)
        self.remove_series.stateChanged.connect(self.check_changed_checkbox)
        self.ignore_change_signals = False

    def check_changed_checkbox(self):
        self.a_c_checkbox.setChecked(True)

    def initialize(self, book_id):
        self.idx_widget.setChecked(False)
        self.main_widget.set_separator(None)
        self.main_widget.update_items_cache(self.all_values)
        self.main_widget.setEditText('')
        self.a_c_checkbox.setChecked(False)

    def getter(self):
        n = unicode(self.main_widget.currentText()).strip()
        i = self.idx_widget.checkState()
        f = self.force_number.checkState()
        s = self.series_start_number.value()
        r = self.remove_series.checkState()
        return n, i, f, s, r

    def commit(self, book_ids, notify=False):
        if not self.a_c_checkbox.isChecked():
            return
        val, update_indices, force_start, at_value, clear = self.gui_val
        val = None if clear else self.normalize_ui_val(val)
        if clear or val != '':
            extras = []
            for book_id in book_ids:
                if clear:
                    extras.append(None)
                    continue
                if update_indices:
                    if force_start:
                        s_index = at_value
                        at_value += 1
                    elif tweaks['series_index_auto_increment'] != 'const':
                        s_index = self.db.get_next_cc_series_num_for(
                            val, num=self.col_id)
                    else:
                        s_index = 1.0
                else:
                    s_index = self.db.get_custom_extra(book_id,
                                                       num=self.col_id,
                                                       index_is_id=True)
                extras.append(s_index)
            self.db.set_custom_bulk(book_ids,
                                    val,
                                    extras=extras,
                                    num=self.col_id,
                                    notify=notify)
Ejemplo n.º 11
0
class ConfigWidget(QWidget):
    """Configuration widget for managing calibre-comicvine config."""
    def __init__(self):
        QWidget.__init__(self)
        self.layout = QGridLayout()
        self.layout.setSpacing(10)
        self.setLayout(self.layout)

        self.index = 0

        self.api_key = QLineEdit(self)
        self.api_key.setText(PREFS['api_key'])
        self.add_labeled_widget('&API key:', self.api_key)

        # Worker threads is the maximum number of worker threads to spawn.
        # Restricted to 1+
        self.worker_threads = QSpinBox(self)
        self.worker_threads.setMinimum(1)
        self.worker_threads.setValue(PREFS['worker_threads'])
        self.add_labeled_widget('&Worker threads:', self.worker_threads)

        # Request interval represents wait time between batches of requests.
        self.request_interval = QSpinBox(self)
        self.request_interval.setMinimum(0)
        self.request_interval.setValue(PREFS['request_interval'])
        self.add_labeled_widget('&Request interval (seconds):',
                                self.request_interval)

        # Request batch is the maximum number of requests to run at a time.
        # Restricted to 1+
        self.request_batch_size = QSpinBox(self)
        self.request_batch_size.setMinimum(1)
        self.request_batch_size.setValue(PREFS['request_batch_size'])
        self.add_labeled_widget('&Request batch size:',
                                self.request_batch_size)

        # Retries is the number of times to retry if we get any error
        # from comicvine besides a rate limit error.
        self.retries = QSpinBox(self)
        self.retries.setMinimum(0)
        self.retries.setValue(PREFS['retries'])
        self.add_labeled_widget('&Retries:', self.retries)

        # Search volume limit is the max number of volumes to return from
        # a volume search.
        self.search_volume_limit = QSpinBox(self)
        self.search_volume_limit.setMinimum(10)
        self.search_volume_limit.setMaximum(10000)
        self.search_volume_limit.setSingleStep(10)
        self.search_volume_limit.setValue(PREFS['search_volume_limit'])
        self.add_labeled_widget('&search_volume_limit:',
                                self.search_volume_limit)

    def add_labeled_widget(self, label_text, widget):
        """
        Add a configuration widget, incrementing the index for the next widget.
        """
        self.index += 1
        label = QLabel(label_text)
        label.setBuddy(widget)
        self.layout.addWidget(label, self.index, 0)
        self.layout.addWidget(widget, self.index, 1)

    def save_settings(self):
        """Apply new settings value."""
        PREFS['api_key'] = unicode(self.api_key.text())
        PREFS['worker_threads'] = self.worker_threads.value()
        PREFS['request_interval'] = self.request_interval.value()
        PREFS['request_batch_size'] = self.request_batch_size.value()
        PREFS['retries'] = self.retries.value()
        PREFS['search_volume_limit'] = self.search_volume_limit.value()
Ejemplo n.º 12
0
class TwoPlots(QWidget):
    ''' Widget to plot 2 curves x(t) & y(t), or Vx(t) & Vy(t)'''

    Ylabels = {
        "position": ("X [pixel]", "Y [pixel]"),
        "velocity": ("VX [pixel/s]", "VY [pixel/s]"),
        "position_mm": ("X [mm]", "Y [mm]"),
        "velocity_mm": ("VX [mm/s]", "VY [mm/s]")
    }

    CurveLabels = {
        "position": ("X(t) [{}]", "Y(t) [{}]"),
        "velocity": ("VX(t) {}", "VY(t) {}")
    }

    def __init__(self, mainWindow, quantity):

        # appel du constructeur de la classe de base :
        QWidget.__init__(self, mainWindow)

        self.mw = mainWindow  # la fenêtre de l'application principale

        # Attributs (objets persistants)
        self.__quantity = quantity  # "position" or "velocity"
        self.__data1 = None  # data for the first plot
        self.__data2 = None  # data for tthe second
        self.__figure = None  # figure tracé
        self.__axes1 = None  # système d'axes tracé 1
        self.__axes2 = None  # système d'axes tracé 2
        self.__canvas = None  # pour le tracé matplot.lib
        self.__toolbar = None  # barre d'outils tracé
        self.__time = None  # abcissa values for plot
        self.__xlim = None  # xmin, xmay tracé
        self.__xlabel = None  # étiquette axe X (n° image ou temps [s])
        self.__ylim1 = None  # ymin, ymax tracé x(t)
        self.__ylim2 = None  # ymin, ymax tracé y(t)

        self.btn_imageSize = QRadioButton("ImageSize", self)
        self.btn_autoSize = QRadioButton("AutoSize", self)

        self.btn_smooth_Vx = QCheckBox("Lissage Vx", self)
        self.btn_smooth_Vy = QCheckBox("Lissage Vy", self)
        self.x_mav_nb_pts = QSpinBox(parent=self)  # X velocity moving average
        self.y_mav_nb_pts = QSpinBox(parent=self)  # Y velocity moving average

        self.__initUI()  # Initialisation de l'interface utilisateur

    def __initUI(self):

        if self.__quantity == "position":

            for w in (self.btn_smooth_Vx, self.btn_smooth_Vy,
                      self.x_mav_nb_pts, self.y_mav_nb_pts):
                w.setVisible(False)
                w.setEnabled(False)

            group = QButtonGroup(self)
            group.addButton(self.btn_imageSize)
            group.addButton(self.btn_autoSize)

            self.btn_imageSize.toggled.connect(self.__ImageSizePlotXYLim)
            self.btn_imageSize.setEnabled(False)
            texte = "Tracé avec les bornes min et max de l'image"
            self.btn_imageSize.setStatusTip(texte)
            self.btn_imageSize.setChecked(True)

            self.btn_autoSize.toggled.connect(self.__AutoSizePlotXYLim)
            self.btn_autoSize.setEnabled(False)
            texte = "Tracé avec les bornes min et max de la "
            texte += "trajectoire calculée"
            self.btn_autoSize.setStatusTip(texte)

        elif self.__quantity == "velocity":

            for w in (self.btn_imageSize, self.btn_autoSize):
                w.setVisible(False)
                w.setEnabled(False)

            self.btn_smooth_Vx.stateChanged.connect(self.__smooth_Vx_wanted)
            self.btn_smooth_Vy.stateChanged.connect(self.__smooth_Vy_wanted)

            self.x_mav_nb_pts.setEnabled(False)
            self.y_mav_nb_pts.setEnabled(False)
            self.x_mav_nb_pts.setRange(3, 100)
            self.y_mav_nb_pts.setRange(3, 100)
            self.x_mav_nb_pts.setSingleStep(2)
            self.y_mav_nb_pts.setSingleStep(2)
            self.x_mav_nb_pts.valueChanged.connect(self.__smooth_vX)
            self.y_mav_nb_pts.valueChanged.connect(self.__smooth_vY)

        vbox = QVBoxLayout()
        self.setLayout(vbox)

        # Ligne 1 : tracé de l'image
        self.setLayout(vbox)
        self.__figure = Figure()
        self.__axes1 = self.__figure.add_subplot(211)
        self.__axes2 = self.__figure.add_subplot(212)
        self.__figure.subplots_adjust(left=0.120,
                                      right=0.99,
                                      bottom=0.11,
                                      top=0.98)
        self.__canvas = FigureCanvas(self.__figure)
        self.__toolbar = NavigationToolbar(self.__canvas, self)
        #self.__toolbar.setMinimumWidth(450)
        vbox.addWidget(self.__canvas)

        hbox = QHBoxLayout()
        hbox.addWidget(self.__toolbar)
        hbox.addStretch()

        if self.__quantity == "position":
            hbox.addWidget(self.btn_imageSize)
            hbox.addWidget(self.btn_autoSize)

        elif self.__quantity == "velocity":
            vb = QVBoxLayout()
            hb = QHBoxLayout()
            hb.addWidget(self.btn_smooth_Vx)
            hb.addWidget(self.x_mav_nb_pts)
            vb.addLayout(hb)
            hb = QHBoxLayout()
            hb.addWidget(self.btn_smooth_Vy)
            hb.addWidget(self.y_mav_nb_pts)
            vb.addLayout(hb)
            hbox.addLayout(vb)

        vbox.addLayout(hbox)

    def reset(self):
        if self.__quantity == "velocity":
            for w in (self.btn_smooth_Vx, self.btn_smooth_Vy,
                      self.x_mav_nb_pts, self.y_mav_nb_pts):
                w.setVisible(True)
                w.setEnabled(True)
            self.x_mav_nb_pts.setValue(self.x_mav_nb_pts.minimum())
            self.y_mav_nb_pts.setValue(self.y_mav_nb_pts.minimum())
            self.btn_smooth_Vx.setCheckState(Qt.Unchecked)
            self.btn_smooth_Vy.setCheckState(Qt.Unchecked)

    def __smooth_Vx_wanted(self, checked):
        if checked:
            self.x_mav_nb_pts.setEnabled(True)
        else:
            self.x_mav_nb_pts.setEnabled(False)
        self.Plot()

    def __smooth_Vy_wanted(self, checked):
        if checked:
            self.y_mav_nb_pts.setEnabled(True)
        else:
            self.y_mav_nb_pts.setEnabled(False)
        self.Plot()

    def __smooth_vX(self, nb_pts):
        if self.btn_smooth_Vx.isChecked():
            self.Plot()
        else:
            pass

    def __smooth_vY(self, nb_pts):
        if self.btn_smooth_Vy.isChecked():
            self.Plot()
        else:
            pass

    def __compute_velocity(self, U, plot_id):
        """Computes the velocity with the centered finite difference of order 1 :
           V[i] = (U[i+1] - U[i-1])/(T[i+1] - T[i-1])  for i in [1,N-1]
           V[0] = (U[1] - U[0])/(T[1] - T[0])
           V[-1] = (U[-1] - U[-2])/(T[-1] - T[-2])
        """
        V = U.copy()
        T = self.__time
        V[0] = (U[1] - U[0]) / (T[1] - T[0])
        V[-1] = (U[-1] - U[-2]) / (T[-1] - T[-2])
        V[1:-1] = (U[2:] - U[:-2]) / (T[2:] - T[:-2])

        if plot_id == "x":
            if self.btn_smooth_Vx.isChecked():
                N = self.x_mav_nb_pts.value()
                V = self.__smooth_data(V, N)
        elif plot_id == "y":
            if self.btn_smooth_Vy.isChecked():
                N = self.y_mav_nb_pts.value()
                V = self.__smooth_data(V, N)
        return V

    def __smooth_data(self, U, nb_pts):
        """Computes the nb_pts moving average on U."""
        N = nb_pts
        V = U.copy()
        V.fill(np.nan)
        mav = deque(maxlen=N)
        # initialize the mav (moving average)
        for e in U[:N]:
            mav.append(e)
        # move!
        index, count = N // 2, 0
        while count < V.shape[0] - N:
            V[index] = np.mean(mav)
            mav.append(U[N + count])
            count += 1
            index += 1

        return V

    def Plot(self):

        target_pos = self.mw.target_pos
        if target_pos is None:
            return
        else:
            self.__data1, self.__data2, I = target_pos
        scale = self.mw.imageTab.pix_to_mm_coeff

        if self.__quantity == "position":
            self.btn_imageSize.setEnabled(True)
            self.btn_autoSize.setEnabled(True)
        elif self.__quantity == "velocity":
            pass

        # Effacement automatiqe si demandé à chaque nouveau tracé :
        if self.mw.flags["autoClearTraj"]:
            if self.__axes1 is not None: self.__axes1.clear()
            if self.__axes2 is not None: self.__axes2.clear()

        # Récupération du nom de l'alagorithme de traitement :
        algo = self.mw.imageTab.btn_algo.currentText()

        # Récupération de la valeur de FP (Frame per seconde) pour calcul
        # du pas de temps et des abscisses :
        deltaT = None
        if self.mw.imageTab.video_FPS is not None:
            deltaT = 1. / self.mw.imageTab.video_FPS
            self.__time = np.array(I) * deltaT
            self.__xlabel = "temps [s]"
        else:
            self.__time = np.array(I)
            self.__xlabel = "image #"

        if self.__quantity == "velocity":
            if deltaT is not None:
                self.__data1 = self.__compute_velocity(self.__data1, "x")
                self.__data2 = self.__compute_velocity(self.__data2, "y")
                if self.btn_smooth_Vx.isChecked():
                    N = self.x_mav_nb_pts.value()
                if self.btn_smooth_Vy.isChecked():
                    N = self.y_mav_nb_pts.value()
                self.__AutoSizePlotXYLim()
            else:
                self.__data1, self.__data2 = None, None
            self.mw.target_veloc = np.array([self.__data1, self.__data2])
        else:
            self.__ImageSizePlotXYLim()

        if self.__data1 is None or self.__data2 is None: return

        curveLabelX, curveLabelY = TwoPlots.CurveLabels[self.__quantity]
        if self.__quantity == "position":
            Xlabel, Ylabel = curveLabelX.format(algo), curveLabelY.format(algo)
        else:
            Xlabel, Ylabel = curveLabelX.format(""), curveLabelY.format("")

        color = 'b' if self.mw.target_RGB is None else self.mw.target_RGB / 255

        # tracé de courbe x(t)
        self.__axes1.plot(self.__time,
                          self.__data1 * scale,
                          color=color,
                          marker='o',
                          markersize=2,
                          linewidth=.4,
                          label=Xlabel)
        self.__axes1.grid(True)
        #self.__axes1.legend(fontsize=9, framealpha=0.7,
        #                   bbox_to_anchor=(-0.1, 1.1), loc='upper left')
        self.__axes1.legend(loc='best', fontsize=10)

        # tracé de courbe y(t)
        self.__axes2.plot(self.__time,
                          self.__data2 * scale,
                          color=color,
                          marker='o',
                          markersize=2,
                          linewidth=.4,
                          label=Ylabel)
        self.__axes2.grid(True)
        #self.__axes2.legend(fontsize=9, framealpha=0.7,
        #                   bbox_to_anchor=(1.1, 1.1), loc='upper right')
        self.__axes2.legend(loc='best', fontsize=10)

        self.__canvas.draw()

    def __AutoSizePlotXYLim(self):

        if self.mw.target_pos is None: return

        y1label, y2label = TwoPlots.Ylabels[self.__quantity]
        self.__xlim = np.array(
            [np.nanmin(self.__time),
             np.nanmax(self.__time)])

        scale = self.mw.imageTab.pix_to_mm_coeff

        if not self.btn_smooth_Vx.isChecked():
            self.__ylim1 = np.array(
                [np.nanmin(self.__data1),
                 np.nanmax(self.__data1)]) * scale
            offset = (self.__ylim1[1] - self.__ylim1[0]) / 10
            self.__ylim1 += np.array([-offset, offset])
        else:
            #self.__ylim1 = self.__axes1.get_ylim()
            pass

        if not self.btn_smooth_Vy.isChecked():
            self.__ylim2 = np.array(
                [np.nanmin(self.__data2),
                 np.nanmax(self.__data2)]) * scale
            offset = (self.__ylim2[1] - self.__ylim2[0]) / 10
            self.__ylim2 += np.array([-offset, offset])
        else:
            #self.__ylim2 = self.__axes2.get_ylim()
            pass

        if self.mw.imageTab.valid_scale:
            y1label, y2label = TwoPlots.Ylabels[self.__quantity + "_mm"]

        self.__axes1.set_xlim(*self.__xlim)
        self.__axes2.set_xlim(*self.__xlim)
        self.__axes1.set_ylim(*self.__ylim1)
        self.__axes2.set_ylim(*self.__ylim2)
        self.__axes1.set_ylabel(y1label)
        self.__axes2.set_ylabel(y2label)
        self.__axes2.set_xlabel(self.__xlabel)

        self.__canvas.draw()

    def __ImageSizePlotXYLim(self):

        if self.mw.target_pos is None: return

        scale = self.mw.imageTab.pix_to_mm_coeff

        y1label, y2label = TwoPlots.Ylabels[self.__quantity]
        w, h = self.mw.imageTab.video_size
        self.__xlim = np.array(
            [np.nanmin(self.__time),
             np.nanmax(self.__time)])
        self.__ylim1 = np.array([0, w - 1], dtype=float) * scale
        self.__ylim2 = np.array([0, h - 1], dtype=float) * scale

        if self.mw.imageTab.valid_scale:
            y1label, y2label = TwoPlots.Ylabels[self.__quantity + "_mm"]

        self.__axes1.set_xlim(*self.__xlim)
        self.__axes2.set_xlim(*self.__xlim)
        self.__axes1.set_ylim(*self.__ylim1)
        self.__axes2.set_ylim(*self.__ylim2)
        self.__axes1.set_ylabel(y1label)
        self.__axes2.set_ylabel(y2label)
        self.__axes2.set_xlabel(self.__xlabel)

        self.__canvas.draw()

    def ClearAxes(self):
        if self.__axes1 is not None: self.__axes1.clear()
        if self.__axes2 is not None: self.__axes2.clear()
        self.__canvas.draw()
Ejemplo n.º 13
0
class ImageDisplay(QWidget):

    video_infos     = ['vidéo : {}','nb frames : {}','taille : {}','FPS : {}','durée : {:.2f} sec']
    video_keys      = ['videoname','nframes','size','fps','duration']
    algo_traj       = ['barycentre','minmax']

    def __init__(self, mainWindow):

        # acall the base class constructor:
        super().__init__(mainWindow)

        self.mw = mainWindow

        # Attributs (objets persistants)
        self.img_lbl = QLabel(self)           # to display the current image
        self.img_lbl.installEventFilter(self) # filter to catch evenements
        self.selectTargetRect = None          # display a rectangle to show teh target color selection

        self.rubberBand  = QRubberBand(QRubberBand.Line, self)

        # Boutons pour avancer/reculer
        self.btn_prev  = QPushButton(QIcon("icones/go-prev.png"),  "", self)
        self.btn_next  = QPushButton(QIcon("icones/go-next.png"), "", self)
        self.btn_first = QPushButton(QIcon("icones/go-first.png"),  "", self)
        self.btn_last  = QPushButton(QIcon("icones/go-last.png"), "", self)
        self.btn_traj  = QPushButton(QIcon("icones/extract.png"), "Extraire...", self)
        self.btn_clear = QPushButton(QIcon("icones/clear.png"), "Effacer courbes...", self)
        self.btn_exportCSV = QPushButton(QIcon("icones/exportCSV.png"), "Export CSV", self)
        self.btn_algo      = QComboBox(self)
        self.image_index   = QLabel(self)
        
        # widget QSpinBox
        self.images_step      = QSpinBox(parent=self)
        self.images_firstRank = QSpinBox(parent=self) 
        self.images_lastRank  = QSpinBox(parent=self) 

        # QLabel to display the target color
        self.target_color_label = QLabel("target color",parent=self) 
        self.picked_color       = QLabel(self)
    
        self.video_path     = None  # Chemin de la dernière vidéo
        self.images_dir     = None  # Dossier contenant les images
        self.__img_idx      = None  # Rang de l'image affichée
        self.img_path       = None  # nom du chemin de l'image courante
        self.nb_img         = None  # nombre d'images

        self.video_name     = None  # nom de la video ("aaaaaa.mp4")
        self.video_nframes  = None  # nombre d'images dans la video
        self.video_size     = None  # taille (width, height) des images
        self.video_FPS      = None  # nombre d'images par seconde
        self.video_duration = None  # durée de la video en secondes
        self.videoLabels    = []    # liste de QLabel contenant les infos vidéo
        self.dico_video     = {}    # dictionnaire des méta-données

        self.dico_unit      = {}    # dictionary "pixels", "mm"
        self.scale_pixel    = None  # nombre de pixels pour conversion en mm
        self.scale_mm       = None  # nbre de mm pour scale_pixel
        self.valid_scale    = False # données de l'échelle valides ou pas
        self.pix_to_mm_coeff= 1.    # le coefficient de converion pixels -> mm
        self.dicoScale      = {}    # dictionnaire des QWidget d'info scale

        self.lbl_epsilon    = None  # label epsilon
        self.epsi_spin      = None  # boite de choix de epsilon    

        # créer l'onglet de visualisation image """
        self.__initUI()
        self.scaleInfoVisible(False)
        self.__epsilonVisible(False)

    def __initUI(self):

        # Onglet "Visualisation images"
        vbox = QVBoxLayout()

        # Ligne 1 : extraction trajec
        self.picked_color.setFrameStyle(QFrame.StyledPanel | QFrame.Plain);
        
        line1 = QHBoxLayout()
        line1.addStretch(1)
        line1.addWidget(self.btn_algo)
        line1.addWidget(self.btn_traj)
        line1.addWidget(self.target_color_label)
        line1.addWidget(self.picked_color)
        line1.addWidget(self.btn_clear)
        line1.addWidget(self.btn_exportCSV)
        line1.addStretch(1)

        # Ligne 2 : infos video + visu image
        line2 = QHBoxLayout()

        # boîte d'infos sur la vidéo
        infoVBox = QVBoxLayout()
        for _ in ImageDisplay.video_infos:
            label = QLabel(self)
            label.setFrameStyle(QFrame.StyledPanel | QFrame.Plain);
            infoVBox.addWidget(label)
            self.videoLabels.append(label)
        infoVBox.addStretch()

        widget = QLabel("Conversion pixels -> mm", self)
        self.dicoScale['Pixels-mm'] = widget
        infoVBox.addWidget(widget)

        grid = QGridLayout()
        infoVBox.addLayout(grid)

        widget = QLabel("pixels  ",self)
        self.dicoScale['pixels'] = widget
        grid.addWidget(widget,1,1)

        self.scale_pixel = QLineEdit(self)
        self.dicoScale['pixelsForMM'] = self.scale_pixel
        grid.addWidget(self.scale_pixel,1,2)

        widget = QLabel("millimètres ",self)
        self.dicoScale['millimeters'] = widget
        grid.addWidget(widget,2,1)

        self.scale_mm = QLineEdit(self)
        self.dicoScale['mmForPixels'] = self.scale_mm
        grid.addWidget(self.scale_mm,2,2)

        self.lbl_epsilon = QLabel("Epsilon ",self)
        grid.addWidget(self.lbl_epsilon,5,1)

        self.epsi_spin = QSpinBox(self)
        self.epsi_spin.setRange(1,50)
        self.epsi_spin.setSingleStep(1)
        self.epsi_spin.setValue(10)
        grid.addWidget(self.epsi_spin,5,2)
        
        infoVBox.addStretch()

        line2.addLayout(infoVBox)
        line2.addStretch(1)
        line2.addWidget(self.img_lbl) # le QLabel por afficher l'image
        line2.addStretch(1)

        # line 3 : navigation boutons
        self.image_index.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        self.image_index.setText("       ")
        line3 = QHBoxLayout()
        line3.addStretch(1)
        line3.addWidget(self.btn_first)
        line3.addWidget(self.btn_prev)
        line3.addWidget(self.image_index)
        line3.addWidget(self.btn_next)
        line3.addWidget(self.btn_last)
        line3.addStretch(1)

        # line 4 : first , step, last image selection
        line4 = QHBoxLayout()
        line4.addStretch(1)
        line4.addWidget(self.images_firstRank)
        line4.addWidget(self.images_step)
        line4.addWidget(self.images_lastRank)
        line4.addStretch(1)

        vbox.addLayout(line1)
        vbox.addStretch(1)
        vbox.addLayout(line2)
        vbox.addStretch(1)
        vbox.addLayout(line3)
        vbox.addLayout(line4)

        self.setLayout(vbox)

        self.buttonsState()
        self.__buttonsConnect()
        self.__setVideoLabelVisible(False)

    def __setVideoLabelVisible(self, state):
        for label in self.videoLabels:
            label.setVisible(state)

    def __buttonsConnect(self):            
        self.btn_traj.clicked.connect(self.extract_trajectoire)
        self.btn_clear.clicked.connect(self.mw.clearPlots)
        self.btn_exportCSV.clicked.connect(self.mw.ExportCSV)
        self.btn_prev.clicked.connect(self.prev_image)
        self.btn_next.clicked.connect(self.next_image)
        self.btn_first.clicked.connect(self.first_image)
        self.btn_last.clicked.connect(self.last_image)
        self.images_step.valueChanged.connect(self.__step_changed)
        self.images_firstRank.valueChanged.connect(self.__first_rank_changed)
        self.images_lastRank.valueChanged.connect(self.__last_rank_changed)

    def buttonsState(self, importCSV=False):

        self.btn_traj.setEnabled(False)
        self.picked_color.setText("X")
        self.picked_color.setEnabled(False)
        
        self.btn_traj.setStatusTip('Extrait la trajectoire de la cible'+
            'dont la couleur a été choisie')

        self.target_color_label.setEnabled(False)
        self.picked_color.setStyleSheet('background-color : rgb(255, 255, 255)')
        
        self.btn_clear.setEnabled(False)
        self.btn_clear.setStatusTip('Nettoye tous les tracés des onglets'+
            '<trajectoire> et <X(t), Y(t)>')

        self.btn_exportCSV.setEnabled(False)
        texte = "Export des données dans un fichier CSV"
        self.btn_exportCSV.setStatusTip(texte)

        if not importCSV: self.btn_algo.addItems(ImageDisplay.algo_traj)
        self.btn_algo.setEnabled(False)

        self.btn_prev.setEnabled(False)
        self.btn_prev.setStatusTip("affiche l'image précédente")

        self.btn_next.setEnabled(False)
        self.btn_next.setStatusTip("affiche l'image suivante")

        self.btn_first.setEnabled(False)
        self.btn_first.setStatusTip("affiche la première image à traiter")

        self.btn_last.setEnabled(False)
        self.btn_last.setStatusTip("affiche la dernière image à traiter")

        # SpinBoxes parameters:
        self.images_step.setRange(1,1000)
        self.images_step.setSingleStep(1)
        self.images_step.setValue(1)
        self.images_step.setPrefix("step: ")
        self.images_step.setEnabled(False)
        self.images_step.setStatusTip("Fixe le pas pour passer d'une image à l'autre")
        
        self.images_firstRank.setRange(1,1000)
        self.images_firstRank.setSingleStep(1)
        self.images_firstRank.setValue(1)
        self.images_firstRank.setPrefix("first: ")
        self.images_firstRank.setEnabled(False)
        self.images_firstRank.setStatusTip("Fixe le rang de la première image à traiter")
        
        self.images_lastRank.setRange(1,10000)
        self.images_lastRank.setSingleStep(1)
        self.images_lastRank.setValue(1)
        self.images_lastRank.setPrefix("last: ")
        self.images_lastRank.setEnabled(False)
        self.images_lastRank.setStatusTip("Fixe le rang de la dernière image à traiter")

    def __first_rank_changed(self, val):
        if self.img_idx is None: return
        if self.img_idx < val:
            self.img_idx = val
            self.show_image()
            
    def __last_rank_changed(self, val):
        if self.img_idx is None: return
        if self.img_idx > val:
            self.img_idx = val
            self.show_image()

    def __step_changed(self, val):
        if self.img_idx is None: return

    def setTextInfoVideoGrid(self):
        
        for field, name, key in zip(self.videoLabels,
                                    ImageDisplay.video_infos,
                                    ImageDisplay.video_keys):
            mess = name.format(self.dico_video.get(key,'?'))
            field.setText(mess)
        self.__setVideoLabelVisible(True)            

    def scaleInfoVisible(self, state):
        for widget in self.dicoScale.values():
            widget.setVisible(state)

    def __epsilonVisible(self, state):
        self.lbl_epsilon.setVisible(state)
        self.epsi_spin.setVisible(state)

    def open_video(self):
        '''Lance un sélecteur de fichier pour choisir la vidéo à traiter.'''
        fname = QFileDialog.getOpenFileName(None,
                                            'Choisir une vidéo',
                                            self.mw.cur_dir,
                                            'Fichier vidéo (*.mp4)')
        if fname[0]  != '' :
            # un fichier vidéo a été chosi :
            vp = fname[0]
            if self.video_path == vp :
                name = os.path.basename(vp)
                rep = QMessageBox.question(self,        # widget parent de QMessageBox
                    'Question',                     # texte du bandeau de la fenêtre
                    'Voulez-vous recharger le fichier video {} ?'.format(name),
                    QMessageBox.Yes | QMessageBox.No,   # afficher les boutons Yes et No
                    QMessageBox.No)                     # bouton No sélectionné par défaut
                if rep == QMessageBox.No: return
            # fichier vidéo à traiter => faire le split des images :
            self.video_path = vp
            self.extract_images_from_video()


    def load_images_from_directory(self):
        '''Charge les images '*.png' contenue dans le répertoire
           des images choisi avec un sélecteur graphique.'''

        # Choix du répertoire avec un sélecteur de fichier :
        dname = QFileDialog.getExistingDirectory(None,
                                                 'Choisir un dossier images',
                                                 self.mw.image_dir)
        if dname != '' :
            # un répertoire valide a été choisi :
            self.video_path = None
            self.images_dir = dname + "/"

            try:
                # Lecture du fichier ascii des méta-données
                with open(self.images_dir + "metaData.txt", "r") as F:
                    data = F.read()
                exec('self.dico_video = '+data)
            except:
                rep = QMessageBox.critical(
                    None,             # widget parent de QMessageBox
                    'Erreur',    # bandeau de la fenêtre
                    'Pas de fichier de méta-données dans le répertoire'+\
                    ' <{}>'.format(os.path.basename(dname)),
                    QMessageBox.Ok)
                return



            print("méta données :", self.dico_video)

            self.parse_meta_data()
            self.setTextInfoVideoGrid()

            # Mettre à jour l'application avec les nouvelles images chargées :
            self.update_images()


    def extract_trajectoire(self):
        '''Méthode utilisée pour extraire la trajectoire du centre de la
           cible pour toutes les images de la vidéo.'''

        # Récupérer l'algorithme de calcul du centre de la cible :
        algo = self.btn_algo.currentText()

        # Définition de la liste dans laquelle on va récupérer les coordonnées
        # du centre cible pour toutes les images :
        target_pos = []

        # Création d'un objet ProgressBar qui va lancer le travail
        # d'extraction de la cible dans les images tout en affichant une
        # barre d'avancement :
        
        first = self.images_firstRank.value()
        last  = self.images_lastRank.value()
        step  = self.images_step.value()
        
        last = last - (last - first) % step
        first_last_step = (first, last, step)
        pg = ProgressBar(self.images_dir, self)
        pg.configure_for_target_extraction(self.mw.target_RGB,
                                           algo,
                                           self.epsi_spin.value(),
                                           target_pos,
                                           first_last_step)
        ret = pg.exec_() # lance la barre et le travail d'extraction...
        print("retour de pg.exec_() :",ret)

        if ret != 0:
            self.mw.target_pos = None
            return

        target_pos = np.array(target_pos)
        width, height = self.video_size
        # l'axe verticale est retourné et decalé:
        target_pos[1] = height - target_pos[1]
        self.scale_XY()

        self.mw.target_pos = target_pos
        self.display_plots()
        
        # remettre le bouton extraire_trajectoire disabled:
        self.btn_exportCSV.setEnabled(True)

    def display_plots(self):
        self.mw.clearPlots()
        
        # Plot trajectory (X(t), Y(t)) :
        self.mw.onePlot.setEnabled(True)
        self.mw.onePlot.Plot()

        # Plot curves X(t) and Y(t)
        self.mw.twoPlots_xy.setEnabled(True)
        self.mw.tabs.setCurrentWidget(self.mw.twoPlots_xy)
        self.mw.twoPlots_xy.Plot()

        # Plot curves VX(t) and VY(t)
        self.mw.twoPlots_VxVy.setEnabled(True)
        self.mw.tabs.setCurrentWidget(self.mw.twoPlots_xy)
        self.mw.twoPlots_VxVy.Plot()


    def extract_images_from_video(self) :
        # name of the video file without path and suffix:
        videoname = os.path.basename(self.video_path)[:-4]

        # directory where to put extracted iamges:
        self.images_dir = self.mw.image_dir + videoname + "/"

        if os.path.isdir(self.images_dir) :
            print("Effacement de tous les fichiers de '{}'"\
                  .format(self.images_dir))
            for fn in os.listdir(self.images_dir) :
                os.remove(self.images_dir+fn)
        else :
            os.mkdir(self.images_dir)

        video = cv2.VideoCapture(self.video_path)
        
        self.dico_video['nframes']   = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
        self.dico_video['size']      = (int(video.get(cv2.CAP_PROP_FRAME_WIDTH)),
                                        int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)))    
        self.dico_video['fps']       = int(video.get(cv2.CAP_PROP_FPS))
        self.dico_video['duration']  = video.get(cv2.CAP_PROP_FRAME_COUNT)/video.get(cv2.CAP_PROP_FPS)
        self.dico_video['videoname'] = os.path.basename(self.video_path)
                                            
        self.parse_meta_data()
        self.dico_video["videoname"] = videoname+".mp4"
        self.setTextInfoVideoGrid()

        # Création d'un objet ProgressBar qui va lancer le travail
        # d'extraction des images tout en affichant une barre d'avancement :
        pg = ProgressBar(self.images_dir, self)
        pg.configure_for_video_extraction(video, self.mw.image_fmt)
        ret = pg.exec_()
        print("retour de pg.exec_() :", ret)
        if ret != 0: return

        # MAJ de la liste des fichiers images :
        self.update_images()

        # écriture des méta-data dans le fichier 'nom_video'.info
        with open(self.mw.image_dir+videoname+"/metaData.txt", "w") as F:
            F.write(str(self.dico_video))

    def computeTargetColor(self, draw_selection=False):
        col_min,row_min,col_max,row_max = self.selection.getCoords()
        print("Pixels selectionnés : lignes [{},{}] colonnes [{},{}]".\
              format(row_min, row_max, col_min, col_max))

        tab = imread(self.img_path)
        self.target_pix = tab[row_min:row_max+1, col_min:col_max+1, :]
        R = round(self.target_pix[:,:,0].mean())
        G = round(self.target_pix[:,:,1].mean())
        B = round(self.target_pix[:,:,2].mean())
        self.mw.target_RGB = np.array([R, G, B], dtype=int)
        print("RGB sélection dans <{}> :".format(os.path.basename(self.img_path)),
              self.mw.target_RGB)

        draw_selection = self.mw.flags["drawTargetSelection"]
        if draw_selection:
            self.show_image()
            print("drawTargetSelection")
            #if self.selectTargetRect is not None : del self.selectTargetRect
            # create painter instance with pixmap
            self.selectTargetRect = QPainter(self.img_lbl.pixmap())

            # set rectangle color and thickness
            self.penRectangle = QPen(QColor(0,0,0))
            self.penRectangle.setWidth(2)

            # draw rectangle on painter
            self.selectTargetRect.begin(self)
            self.selectTargetRect.setPen(self.penRectangle)
            self.selectTargetRect.drawRect(col_min,row_min,
                                          col_max-col_min,row_max-row_min)
            self.selectTargetRect.setOpacity(0.1)
            self.selectTargetRect.end()
            #self.show_image()

        self.btn_traj.setEnabled(True)
        self.btn_algo.setEnabled(True)
        self.btn_clear.setEnabled(True)
        self.target_color_label.setEnabled(True)
        self.picked_color.setStyleSheet('background-color : rgb({},{},{})'.format(R, G, B))

    @property
    def img_idx(self): return self.__img_idx

    @img_idx.setter
    def img_idx(self, index):
        self.__img_idx = index
        self.image_index.setText(str(index))
                                 
    def update_images(self) :
        '''Méthode à exécuter quand de nouvelles images sont apparues
           après une extraction d'images depuis une vidéo par exemple.
           Cette méthode :
           - met à jour des attributs qui dépendant de la liste des images,
           - met à jour l'état de certains boutons
           - fait afficher la première image et un message d'information.'''

        if self.images_dir is None :
            self.__img_idx = None
            #self.btn_prev.setEnabled(False)
            self.btn_prev.setStatusTip("")
            #self.btn_next.setEnabled(False)
            self.btn_next.setStatusTip("")
            self.images_step.setEnabled(False)
            self.images_firstRank.setEnabled(False)
            self.images_lastRank.setEnabled(False)
            
        else :
            self.buttonsState()
            self.mw.clearPlots()
            self.mw.twoPlots_VxVy.reset()
            
            # liste des noms des fichiers image pour avoir leur nombre :
            file_names = [ f for f in os.listdir(self.images_dir) \
                           if f.endswith('.png')]
            file_names.sort()
            self.nb_img = len(file_names)

              # Update spinBox:
            self.images_step.setEnabled(True)
            self.images_firstRank.setEnabled(True)
            self.images_lastRank.setEnabled(True)

            self.images_firstRank.setValue(1)
            self.images_step.setValue(1)
            self.images_lastRank.setValue(self.nb_img)

            self.images_firstRank.setMaximum(self.nb_img)
            self.images_lastRank.setMaximum(self.nb_img)
            self.images_step.setMaximum(self.nb_img)

            # MAJ des boutons prev et next
            self.img_idx = self.images_firstRank.value()
            self.btn_prev.setEnabled(True)
            self.btn_first.setEnabled(True)

            self.btn_prev.setStatusTip("charge l'image précédente")

            self.btn_next.setEnabled(True)
            self.btn_last.setEnabled(True)
            self.btn_next.setStatusTip("afficher "+self.mw.image_fmt.format(\
                self.img_idx+self.images_step.value()))
          
            self.show_image()
            self.scaleInfoVisible(True)
            self.__epsilonVisible(True)
            self.mw.tabs.setCurrentWidget(self)

            self.scale_mm.clear()
            self.scale_mm.setText("???")
            self.scale_pixel.clear()
            try:
                text = str(self.video_size[1])
            except:
                text = ""
            self.scale_pixel.setText(text)

            self.mw.twoPlots_VxVy.reset()
            

            if self.mw.flags["displayInfo"]:
                rep = QMessageBox.information(
                    None,             # widget parent de QMessageBox
                    'Information',    # bandeau de la fenêtre
                    'Vous pouvez maintenant sélectionner une couleur de cible'+\
                    'avec la souris...',
                    QMessageBox.Ok)
                

    def show_image(self):
        '''Affiche l'image dont le numéro est donné par l'attribut 'img_idx'.'''
        if self.img_idx is None :
            self.img_path = ''
        else :
            self.img_path = self.images_dir+self.mw.image_fmt.format(self.img_idx)
        pixmap = QPixmap(self.img_path)
        self.img_lbl.setPixmap(pixmap)
        self.img_lbl.setStatusTip(os.path.basename(self.img_path))

    def first_image(self) :
        if self.img_idx == None : return
        self.img_idx = self.images_firstRank.value()
        self.mw.statusBar().showMessage("")
        self.show_image()

    def prev_image(self) :
        if self.img_idx == None : return
        if self.img_idx >= self.images_firstRank.value() + self.images_step.value():
            self.img_idx -= self.images_step.value()
        self.mw.statusBar().showMessage("")
        self.show_image()

    def last_image(self) :
        if self.img_idx == None : return
        self.img_idx = self.images_lastRank.value() # rank of last image to process
        self.mw.statusBar().showMessage("")
        self.show_image()

    def next_image(self) :
        if self.img_idx == None : return
        if self.img_idx <= self.images_lastRank.value()-self.images_step.value():
            self.img_idx += self.images_step.value()
        self.mw.statusBar().showMessage("")
        self.show_image()

    def parse_meta_data(self):
        self.video_nframes  = self.dico_video.get('nframes', None)
        self.video_size     = self.dico_video.get('size', None)
        self.video_FPS      = self.dico_video.get('fps', None)
        self.video_duration = self.dico_video.get('duration', None)
        self.video_name     = self.dico_video.get('videoname',"none.mp4")

        if self.mw.flags["debug"]:
            info= " nb images    : {},\n taille image : {},\n FPS : {} image/sec,\n durée : {.2f} sec."
            info = info.format(self.video_nframes,
                               self.video_size,
                               self.video_FPS,
                               self.video_duration)
            QMessageBox.about(None,     # widget parent de QMessageBox
                              'Informations video {}'.format(self.video_name),
                              info)


    def eventFilter(self, object, event):
        if object == self.img_lbl :
            if event.type() == QEvent.MouseButtonPress:
                self.mousePressInLabel(event)
                return True
            elif event.type() == QEvent.MouseButtonRelease:
                self.mouseReleaseInLabel(event)
                return True
            elif event.type() == QEvent.MouseMove:
                self.mouseMoveInLabel(event)
                return True
        return False

    def mousePressInLabel(self, event):
        if event.button() == Qt.LeftButton:
            self.pt1 = event.pos()
            self.pt1_rect = self.img_lbl.mapTo(self, self.pt1)
            print("\nCoord. pt1 image :",self.pt1)
            self.rubberBand.setGeometry(QRect(self.pt1_rect, QSize()))
            self.rubberBand.show()
            self.mw.statusBar().showMessage('sélection en cours....')

    def mouseMoveInLabel(self, event):
        if not self.pt1.isNull():
            pt = self.img_lbl.mapTo(self,event.pos())
            self.rubberBand.setGeometry(QRect(self.pt1_rect, pt).normalized())

    def mouseReleaseInLabel(self, event):
        if event.button() == Qt.LeftButton:
            self.pt2 = event.pos()
            print("Coord. pt2 image :", self.pt2)
            self.rubberBand.hide()
            self.selection = QRect(self.pt1, self.pt2).normalized()
            print(self.selection)
            self.computeTargetColor()

    def scale_XY(self):

        self.valid_scale = False
        self.pix_to_mm_coeff = 1.
        
        try :
            pixels = float(self.scale_pixel.text())
            mm     = float(self.scale_mm.text())
        except :
            if self.mw.flags["displayInfo"]:
                info = 'Les données de conversion Pixels -> mm n\'ont pas été '
                info += 'complétées.. les ordonnées des tracés seront en pixels.'
                rep = QMessageBox.information(None,  # parent de QMessageBox
                        'Info',               # bandeau de la fenêtre
                        info, QMessageBox.Ok)
            return
        self.valid_scale = True
        self.pix_to_mm_coeff = mm/pixels
        print("valid scale : ", self.pix_to_mm_coeff)
Ejemplo n.º 14
0
class ConfigWidget(QWidget):
    """Configuration widget for managing calibre-comicvine config."""

    def __init__(self):
        QWidget.__init__(self)
        self.layout = QGridLayout()
        self.layout.setSpacing(10)
        self.setLayout(self.layout)

        self.index = 0

        self.api_key = QLineEdit(self)
        self.api_key.setText(PREFS['api_key'])
        self.add_labeled_widget('&API key:', self.api_key)

        # Worker threads is the maximum number of worker threads to spawn.
        # Restricted to 1+
        self.worker_threads = QSpinBox(self)
        self.worker_threads.setMinimum(1)
        self.worker_threads.setValue(PREFS['worker_threads'])
        self.add_labeled_widget('&Worker threads:', self.worker_threads)

        # Request interval represents wait time between batches of requests.
        self.request_interval = QSpinBox(self)
        self.request_interval.setMinimum(0)
        self.request_interval.setValue(PREFS['request_interval'])
        self.add_labeled_widget('&Request interval (seconds):',
                                self.request_interval)

        # Request batch is the maximum number of requests to run at a time.
        # Restricted to 1+
        self.request_batch_size = QSpinBox(self)
        self.request_batch_size.setMinimum(1)
        self.request_batch_size.setValue(PREFS['request_batch_size'])
        self.add_labeled_widget('&Request batch size:', self.request_batch_size)

        # Retries is the number of times to retry if we get any error
        # from comicvine besides a rate limit error.
        self.retries = QSpinBox(self)
        self.retries.setMinimum(0)
        self.retries.setValue(PREFS['retries'])
        self.add_labeled_widget('&Retries:', self.retries)

        # Search volume limit is the max number of volumes to return from
        # a volume search.
        self.search_volume_limit = QSpinBox(self)
        self.search_volume_limit.setMinimum(10)
        self.search_volume_limit.setMaximum(10000)
        self.search_volume_limit.setSingleStep(10)
        self.search_volume_limit.setValue(PREFS['search_volume_limit'])
        self.add_labeled_widget('&search_volume_limit:',
                                self.search_volume_limit)

    def add_labeled_widget(self, label_text, widget):
        """
        Add a configuration widget, incrementing the index for the next widget.
        """
        self.index += 1
        label = QLabel(label_text)
        label.setBuddy(widget)
        self.layout.addWidget(label, self.index, 0)
        self.layout.addWidget(widget, self.index, 1)

    def save_settings(self):
        """Apply new settings value."""
        PREFS['api_key'] = unicode(self.api_key.text())
        PREFS['worker_threads'] = self.worker_threads.value()
        PREFS['request_interval'] = self.request_interval.value()
        PREFS['request_batch_size'] = self.request_batch_size.value()
        PREFS['retries'] = self.retries.value()
        PREFS['search_volume_limit'] = self.search_volume_limit.value()
Ejemplo n.º 15
0
class ConfigWidget(QWidget):

    def __init__(self, plugin_action):
        QWidget.__init__(self)
        self.plugin_action = plugin_action
        layout = QVBoxLayout(self)
        self.setLayout(layout)
        self.help_anchor = "configuration"
        
        title_layout = ImageTitleLayout(self, 'images/icon.png', 'Sony Utilities Options')
        layout.addLayout(title_layout)

#        c = plugin_prefs[STORE_NAME]
        library_config = get_library_config(self.plugin_action.gui.current_db)

        custom_column_group = QGroupBox(_('Custom Columns'), self)
        layout.addWidget(custom_column_group )
        options_layout = QGridLayout()
        custom_column_group.setLayout(options_layout)

        avail_text_columns   = self.get_text_custom_columns()
        avail_number_columns = self.get_number_custom_columns()
        avail_rating_columns = self.get_rating_custom_columns()
        avail_date_columns   = self.get_date_custom_columns()
#        debug_print("avail_rating_columns=", avail_rating_columns)
#        debug_print("default columns=", self.plugin_action.gui.library_view.model().orig_headers)
        current_Location_column  = library_config.get(KEY_CURRENT_LOCATION_CUSTOM_COLUMN, DEFAULT_LIBRARY_VALUES[KEY_CURRENT_LOCATION_CUSTOM_COLUMN])
        precent_read_column      = library_config.get(KEY_PERCENT_READ_CUSTOM_COLUMN, DEFAULT_LIBRARY_VALUES[KEY_PERCENT_READ_CUSTOM_COLUMN])
        rating_column            = library_config.get(KEY_RATING_CUSTOM_COLUMN, DEFAULT_LIBRARY_VALUES[KEY_RATING_CUSTOM_COLUMN])
        last_read_column         = library_config.get(KEY_LAST_READ_CUSTOM_COLUMN, DEFAULT_LIBRARY_VALUES[KEY_LAST_READ_CUSTOM_COLUMN])

        store_on_connect         = get_plugin_pref(COMMON_OPTIONS_STORE_NAME, KEY_STORE_ON_CONNECT)
        prompt_to_store          = get_plugin_pref(COMMON_OPTIONS_STORE_NAME, KEY_PROMPT_TO_STORE)
        store_if_more_recent     = get_plugin_pref(COMMON_OPTIONS_STORE_NAME, KEY_STORE_IF_MORE_RECENT)
        do_not_store_if_reopened = get_plugin_pref(COMMON_OPTIONS_STORE_NAME, KEY_DO_NOT_STORE_IF_REOPENED)

#         do_check_for_firmware_updates = get_plugin_pref(UPDATE_OPTIONS_STORE_NAME, KEY_DO_UPDATE_CHECK)
#         do_early_firmware_updates     = get_plugin_pref(UPDATE_OPTIONS_STORE_NAME, KEY_DO_EARLY_FIRMWARE_CHECK)
#         self.update_check_last_time   = get_plugin_pref(UPDATE_OPTIONS_STORE_NAME, KEY_LAST_FIRMWARE_CHECK_TIME)

        do_daily_backup          = get_plugin_pref(BACKUP_OPTIONS_STORE_NAME, KEY_DO_DAILY_BACKUP)
        dest_directory           = get_plugin_pref(BACKUP_OPTIONS_STORE_NAME, KEY_BACKUP_DEST_DIRECTORY)
        copies_to_keep           = get_plugin_pref(BACKUP_OPTIONS_STORE_NAME, KEY_BACKUP_COPIES_TO_KEEP)
#        debug_print("current_Location_column=%s, precent_read_column=%s, rating_column=%s" % (current_Location_column, precent_read_column, rating_column))

        current_Location_label = QLabel(_('Current Reading Location Column:'), self)
        current_Location_label.setToolTip(_("Select a custom column to store the current reading location. The column type must be 'text'. Leave this blank if you do not want to store or restore the current reading location."))
        self.current_Location_combo = CustomColumnComboBox(self, avail_text_columns, current_Location_column)
        current_Location_label.setBuddy(self.current_Location_combo)
        options_layout.addWidget(current_Location_label, 0, 0, 1, 1)
        options_layout.addWidget(self.current_Location_combo, 0, 1, 1, 1)
        
        percent_read_label = QLabel(_('Percent Read Column:'), self)
        percent_read_label.setToolTip(_("Column used to store the current percent read. The column type must be a 'integer'. Leave this blank if you do not want to store or restore the percentage read."))
        self.percent_read_combo = CustomColumnComboBox(self, avail_number_columns, precent_read_column)
        percent_read_label.setBuddy(self.percent_read_combo)
        options_layout.addWidget(percent_read_label, 2, 0, 1, 1)
        options_layout.addWidget(self.percent_read_combo, 2, 1, 1, 1)

        rating_label = QLabel(_('Rating Column:'), self)
        rating_label.setToolTip(_("Column used to store the rating. The column type must be a 'integer'. Leave this blank if you do not want to store or restore the rating."))
        self.rating_combo = CustomColumnComboBox(self, avail_rating_columns, rating_column)
        rating_label.setBuddy(self.rating_combo)
        options_layout.addWidget(rating_label, 3, 0, 1, 1)
        options_layout.addWidget(self.rating_combo, 3, 1, 1, 1)

        last_read_label = QLabel(_('Last Read Column:'), self)
        last_read_label.setToolTip(_("Column used to store when the book was last read. The column type must be a 'Date'. Leave this blank if you do not want to store the last read timestamp."))
        self.last_read_combo = CustomColumnComboBox(self, avail_date_columns, last_read_column)
        last_read_label.setBuddy(self.last_read_combo)
        options_layout.addWidget(last_read_label, 4, 0, 1, 1)
        options_layout.addWidget(self.last_read_combo, 4, 1, 1, 1)

        auto_store_group = QGroupBox(_('Store on connect'), self)
        layout.addWidget(auto_store_group )
        options_layout = QGridLayout()
        auto_store_group.setLayout(options_layout)

        self.store_on_connect_checkbox = QCheckBox(_("Store current bookmarks on connect"), self)
        self.store_on_connect_checkbox.setToolTip(_("When this is checked, the library will be updated with the current bookmark for all books on the device."))
        self.store_on_connect_checkbox.setCheckState(Qt.Checked if store_on_connect else Qt.Unchecked)
        self.store_on_connect_checkbox.clicked.connect(self.store_on_connect_checkbox_clicked)
        options_layout.addWidget(self.store_on_connect_checkbox, 0, 0, 1, 3)

        self.prompt_to_store_checkbox = QCheckBox(_("Prompt to store any changes"), self)
        self.prompt_to_store_checkbox.setToolTip(_("Enable this to be prompted to save the changed bookmarks after an automatic store is done."))
        self.prompt_to_store_checkbox.setCheckState(Qt.Checked if prompt_to_store else Qt.Unchecked)
        self.prompt_to_store_checkbox.setEnabled(store_on_connect)
        options_layout.addWidget(self.prompt_to_store_checkbox, 1, 0, 1, 1)

        self.store_if_more_recent_checkbox = QCheckBox(_("Only if more recent"), self)
        self.store_if_more_recent_checkbox.setToolTip(_("Only store the reading position if the last read timestamp on the device is more recent than in the library."))
        self.store_if_more_recent_checkbox.setCheckState(Qt.Checked if store_if_more_recent else Qt.Unchecked)
        self.store_if_more_recent_checkbox.setEnabled(store_on_connect)
        options_layout.addWidget(self.store_if_more_recent_checkbox, 1, 1, 1, 1)

        self.do_not_store_if_reopened_checkbox = QCheckBox(_("Not if finished in library"), self)
        self.do_not_store_if_reopened_checkbox.setToolTip(_("Do not store the reading position if the library has the book as finished. This is if the percent read is 100%."))
        self.do_not_store_if_reopened_checkbox.setCheckState(Qt.Checked if do_not_store_if_reopened else Qt.Unchecked)
        self.do_not_store_if_reopened_checkbox.setEnabled(store_on_connect)
        options_layout.addWidget(self.do_not_store_if_reopened_checkbox, 1, 2, 1, 1)

#         update_options_group = QGroupBox(_('Firmware Update Options'), self)
#         layout.addWidget(update_options_group)
#         options_layout = QGridLayout()
#         update_options_group.setLayout(options_layout)
# 
#         self.do_update_check = QCheckBox(_('Check for Sony firmware updates daily?'), self)
#         self.do_update_check.setToolTip(_('If this is selected the plugin will check for Sony firmware updates when your Sony device is plugged in, once per 24-hour period.'))
#         self.do_update_check.setCheckState(Qt.Checked if do_check_for_firmware_updates else Qt.Unchecked)
#         options_layout.addWidget(self.do_update_check, 0, 0, 1, 1)
# 
#         self.do_early_firmware_check = QCheckBox(_('Use early firmware adopter affiliate?'), self)
#         self.do_early_firmware_check.setToolTip(_('WARNING: THIS OPTION RISKS DOWNLOADING THE WRONG FIRMWARE FOR YOUR DEVICE! YOUR DEVICE MAY NOT FUNCTION PROPERLY IF THIS HAPPENS! Choose this option to attempt to download Sony firmware updates before they are officially available for your device.'))
#         self.do_early_firmware_check.setCheckState(Qt.Checked if do_early_firmware_updates else Qt.Unchecked)
#         options_layout.addWidget(self.do_early_firmware_check, 0, 1, 1, 1)

        backup_options_group = QGroupBox(_('Device Database Backup'), self)
        layout.addWidget(backup_options_group)
        options_layout = QGridLayout()
        backup_options_group.setLayout(options_layout)

        self.do_daily_backp_checkbox = QCheckBox(_('Backup the device database daily'), self)
        self.do_daily_backp_checkbox.setToolTip(_('If this is selected the plugin will backup the device database the first time it is connected each day.'))
        self.do_daily_backp_checkbox.setCheckState(Qt.Checked if do_daily_backup else Qt.Unchecked)
        self.do_daily_backp_checkbox.clicked.connect(self.do_daily_backp_checkbox_clicked)
        options_layout.addWidget(self.do_daily_backp_checkbox, 0, 0, 1, 3)

        self.dest_directory_label = QLabel(_("Destination:"), self)
        self.dest_directory_label.setToolTip(_("Select the destination the annotations files are to be backed up in."))
        self.dest_directory_edit = QLineEdit(self)
        self.dest_directory_edit.setMinimumSize(150, 0)
        self.dest_directory_edit.setText(dest_directory)
        self.dest_directory_label.setBuddy(self.dest_directory_edit)
        self.dest_pick_button = QPushButton(_("..."), self)
        self.dest_pick_button.setMaximumSize(24, 20)
        self.dest_pick_button.clicked.connect(self._get_dest_directory_name)
        options_layout.addWidget(self.dest_directory_label, 1, 0, 1, 1)
        options_layout.addWidget(self.dest_directory_edit, 1, 1, 1, 1)
        options_layout.addWidget(self.dest_pick_button, 1, 2, 1, 1)

        self.copies_to_keep_checkbox = QCheckBox(_('Copies to keep'), self)
        self.copies_to_keep_checkbox.setToolTip(_("Select this to limit the number of backup kept. If not set, the backup files must be manually deleted."))
        self.copies_to_keep_spin = QSpinBox(self)
        self.copies_to_keep_spin.setMinimum(2)
        self.copies_to_keep_spin.setToolTip(_("The number of backup copies of the database to keep. The minimum is 2."))
        options_layout.addWidget(self.copies_to_keep_checkbox, 1, 3, 1, 1)
        options_layout.addWidget(self.copies_to_keep_spin, 1, 4, 1, 1)
        self.copies_to_keep_checkbox.clicked.connect(self.copies_to_keep_checkbox_clicked)
        if copies_to_keep == -1:
            self.copies_to_keep_checkbox.setCheckState(not Qt.Checked)
        else:
            self.copies_to_keep_checkbox.setCheckState(Qt.Checked)
            self.copies_to_keep_spin.setProperty('value', copies_to_keep)

        self.do_daily_backp_checkbox_clicked(do_daily_backup)

        other_options_group = QGroupBox(_('Other Options'), self)
        layout.addWidget(other_options_group )
        options_layout = QGridLayout()
        other_options_group.setLayout(options_layout)

        library_default_label = QLabel(_('&Library Button default:'), self)
        library_default_label.setToolTip(_('If plugin is placed as a toolbar button, choose a default action when clicked on'))
        self.library_default_combo = KeyComboBox(self, self.plugin_action.library_actions_map, unicode(get_plugin_pref(COMMON_OPTIONS_STORE_NAME, KEY_BUTTON_ACTION_LIBRARY)))
        library_default_label.setBuddy(self.library_default_combo)
        options_layout.addWidget(library_default_label, 0, 0, 1, 1)
        options_layout.addWidget(self.library_default_combo, 0, 1, 1, 2)

        device_default_label = QLabel(_('&Device Button default:'), self)
        device_default_label.setToolTip(_('If plugin is placed as a toolbar button, choose a default action when clicked on'))
        self.device_default_combo = KeyComboBox(self, self.plugin_action.device_actions_map, unicode(get_plugin_pref(COMMON_OPTIONS_STORE_NAME, KEY_BUTTON_ACTION_DEVICE)))
        device_default_label.setBuddy(self.device_default_combo)
        options_layout.addWidget(device_default_label, 1, 0, 1, 1)
        options_layout.addWidget(self.device_default_combo, 1, 1, 1, 2)

        keyboard_shortcuts_button = QPushButton(_('Keyboard shortcuts...'), self)
        keyboard_shortcuts_button.setToolTip(_('Edit the keyboard shortcuts associated with this plugin'))
        keyboard_shortcuts_button.clicked.connect(self.edit_shortcuts)
        layout.addWidget(keyboard_shortcuts_button)
        layout.addStretch(1)

    def store_on_connect_checkbox_clicked(self, checked):
        self.prompt_to_store_checkbox.setEnabled(checked)
        self.store_if_more_recent_checkbox.setEnabled(checked)
        self.do_not_store_if_reopened_checkbox.setEnabled(checked)

    def do_daily_backp_checkbox_clicked(self, checked):
        self.dest_directory_edit.setEnabled(checked)
        self.dest_pick_button.setEnabled(checked)
        self.dest_directory_label.setEnabled(checked)
        self.copies_to_keep_checkbox.setEnabled(checked)
        self.copies_to_keep_checkbox_clicked(checked and self.copies_to_keep_checkbox.checkState() == Qt.Checked)

    def copies_to_keep_checkbox_clicked(self, checked):
        self.copies_to_keep_spin.setEnabled(checked)

    # Called by Calibre before save_settings 
    def validate(self):
#        import traceback
#        traceback.print_stack()
        
        debug_print('BEGIN Validate')
        valid = True
        # Only save if we were able to get data to avoid corrupting stored data
#        if self.do_daily_backp_checkbox.checkState() == Qt.Checked and not len(self.dest_directory_edit.text()):
#            error_dialog(self, 'No destination directory',
#                            'If the automatic device backup is set, there must be a destination directory.',
#                            show=True, show_copy_button=False)
#            valid = False

        debug_print('END Validate, status = %s' % valid)
        return valid

    def save_settings(self):

        new_prefs = {}
        new_prefs[KEY_BUTTON_ACTION_DEVICE]     = unicode(self.device_default_combo.currentText())
        new_prefs[KEY_BUTTON_ACTION_LIBRARY]    = unicode(self.library_default_combo.currentText())
        new_prefs[KEY_STORE_ON_CONNECT]         = self.store_on_connect_checkbox.checkState() == Qt.Checked
        new_prefs[KEY_PROMPT_TO_STORE]          = self.prompt_to_store_checkbox.checkState() == Qt.Checked
        new_prefs[KEY_STORE_IF_MORE_RECENT]     = self.store_if_more_recent_checkbox.checkState() == Qt.Checked
        new_prefs[KEY_DO_NOT_STORE_IF_REOPENED] = self.do_not_store_if_reopened_checkbox.checkState() == Qt.Checked
        plugin_prefs[COMMON_OPTIONS_STORE_NAME] = new_prefs

        new_update_prefs = {}
#         new_update_prefs[KEY_DO_UPDATE_CHECK]          = self.do_update_check.checkState() == Qt.Checked
#         new_update_prefs[KEY_DO_EARLY_FIRMWARE_CHECK]  = self.do_early_firmware_check.checkState() == Qt.Checked
#         new_update_prefs[KEY_LAST_FIRMWARE_CHECK_TIME] = self.update_check_last_time
        plugin_prefs[UPDATE_OPTIONS_STORE_NAME]        = new_update_prefs

        backup_prefs = {}
        backup_prefs[KEY_DO_DAILY_BACKUP]       = self.do_daily_backp_checkbox.checkState() == Qt.Checked
        backup_prefs[KEY_BACKUP_DEST_DIRECTORY] = unicode(self.dest_directory_edit.text())
        backup_prefs[KEY_BACKUP_COPIES_TO_KEEP] = int(unicode(self.copies_to_keep_spin.value())) if self.copies_to_keep_checkbox.checkState() == Qt.Checked else -1 
        plugin_prefs[BACKUP_OPTIONS_STORE_NAME] = backup_prefs

        db = self.plugin_action.gui.current_db
        library_config = get_library_config(db)
        library_config[KEY_CURRENT_LOCATION_CUSTOM_COLUMN] = self.current_Location_combo.get_selected_column()
        library_config[KEY_PERCENT_READ_CUSTOM_COLUMN]     = self.percent_read_combo.get_selected_column()
        library_config[KEY_RATING_CUSTOM_COLUMN]           = self.rating_combo.get_selected_column()
        library_config[KEY_LAST_READ_CUSTOM_COLUMN]        = self.last_read_combo.get_selected_column()
        set_library_config(db, library_config)

    def get_number_custom_columns(self):
        column_types = ['float','int']
        return self.get_custom_columns(column_types)

    def get_rating_custom_columns(self):
        column_types = ['rating','int']
        custom_columns = self.get_custom_columns(column_types)
        ratings_column_name = self.plugin_action.gui.library_view.model().orig_headers['rating']
        custom_columns['rating'] = {'name': ratings_column_name}
        return custom_columns

    def get_text_custom_columns(self):
        column_types = ['text']
        return self.get_custom_columns(column_types)

    def get_date_custom_columns(self):
        column_types = ['datetime']
        return self.get_custom_columns(column_types)

    def get_custom_columns(self, column_types):
        custom_columns = self.plugin_action.gui.library_view.model().custom_columns
        available_columns = {}
        for key, column in custom_columns.iteritems():
            typ = column['datatype']
            if typ in column_types and not column['is_multiple']:
                available_columns[key] = column
        return available_columns

    def help_link_activated(self, url):
        self.plugin_action.show_help(anchor="configuration")

    def edit_shortcuts(self):
        d = KeyboardConfigDialog(self.plugin_action.gui, self.plugin_action.action_spec[0])
        if d.exec_() == d.Accepted:
            self.plugin_action.gui.keyboard.finalize()

    def _get_dest_directory_name(self):
        path = choose_dir(self, 'backup annotations destination dialog','Choose destination directory')
        if path:
            self.dest_directory_edit.setText(path)
Ejemplo n.º 16
0
class AddEmptyBookDialog(QDialog):
    def __init__(self, parent, db, author, series=None):
        QDialog.__init__(self, parent)
        self.db = db

        self.setWindowTitle(_('How many empty books?'))

        self._layout = QGridLayout(self)
        self.setLayout(self._layout)

        self.qty_label = QLabel(_('How many empty books should be added?'))
        self._layout.addWidget(self.qty_label, 0, 0, 1, 2)

        self.qty_spinbox = QSpinBox(self)
        self.qty_spinbox.setRange(1, 10000)
        self.qty_spinbox.setValue(1)
        self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2)

        self.author_label = QLabel(_('Set the author of the new books to:'))
        self._layout.addWidget(self.author_label, 2, 0, 1, 2)

        self.authors_combo = EditWithComplete(self)
        self.authors_combo.setSizeAdjustPolicy(
            self.authors_combo.AdjustToMinimumContentsLengthWithIcon)
        self.authors_combo.setEditable(True)
        self._layout.addWidget(self.authors_combo, 3, 0, 1, 1)
        self.initialize_authors(db, author)

        self.clear_button = QToolButton(self)
        self.clear_button.setIcon(QIcon(I('trash.png')))
        self.clear_button.setToolTip(_('Reset author to Unknown'))
        self.clear_button.clicked.connect(self.reset_author)
        self._layout.addWidget(self.clear_button, 3, 1, 1, 1)

        self.series_label = QLabel(_('Set the series of the new books to:'))
        self._layout.addWidget(self.series_label, 4, 0, 1, 2)

        self.series_combo = EditWithComplete(self)
        self.authors_combo.setSizeAdjustPolicy(
            self.authors_combo.AdjustToMinimumContentsLengthWithIcon)
        self.series_combo.setEditable(True)
        self._layout.addWidget(self.series_combo, 5, 0, 1, 1)
        self.initialize_series(db, series)

        self.sclear_button = QToolButton(self)
        self.sclear_button.setIcon(QIcon(I('trash.png')))
        self.sclear_button.setToolTip(_('Reset series'))
        self.sclear_button.clicked.connect(self.reset_series)
        self._layout.addWidget(self.sclear_button, 5, 1, 1, 1)

        self.create_epub = c = QCheckBox(
            _('Create an empty EPUB file as well'))
        c.setChecked(gprefs.get('create_empty_epub_file', False))
        c.setToolTip(
            _('Also create an empty EPUB file that you can subsequently edit'))
        self._layout.addWidget(c, 6, 0, 1, -1)

        button_box = self.bb = QDialogButtonBox(QDialogButtonBox.Ok
                                                | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)
        self._layout.addWidget(button_box, 7, 0, 1, -1)
        self.resize(self.sizeHint())

    def accept(self):
        oval = gprefs.get('create_empty_epub_file', False)
        if self.create_epub.isChecked() != oval:
            gprefs['create_empty_epub_file'] = self.create_epub.isChecked()
        return QDialog.accept(self)

    def reset_author(self, *args):
        self.authors_combo.setEditText(_('Unknown'))

    def reset_series(self):
        self.series_combo.setEditText('')

    def initialize_authors(self, db, author):
        au = author
        if not au:
            au = _('Unknown')
        self.authors_combo.show_initial_value(au.replace('|', ','))

        self.authors_combo.set_separator('&')
        self.authors_combo.set_space_before_sep(True)
        self.authors_combo.set_add_separator(
            tweaks['authors_completer_append_separator'])
        self.authors_combo.update_items_cache(db.all_author_names())

    def initialize_series(self, db, series):
        self.series_combo.show_initial_value(series or '')
        self.series_combo.update_items_cache(db.all_series_names())
        self.series_combo.set_separator(None)

    @property
    def qty_to_add(self):
        return self.qty_spinbox.value()

    @property
    def selected_authors(self):
        return string_to_authors(unicode(self.authors_combo.text()))

    @property
    def selected_series(self):
        return unicode(self.series_combo.text())
Ejemplo n.º 17
0
class AddEmptyBookDialog(QDialog):

    def __init__(self, parent, db, author, series=None, title=None, dup_title=None):
        QDialog.__init__(self, parent)
        self.db = db

        self.setWindowTitle(_('How many empty books?'))

        self._layout = QGridLayout(self)
        self.setLayout(self._layout)

        self.qty_label = QLabel(_('How many empty books should be added?'))
        self._layout.addWidget(self.qty_label, 0, 0, 1, 2)

        self.qty_spinbox = QSpinBox(self)
        self.qty_spinbox.setRange(1, 10000)
        self.qty_spinbox.setValue(1)
        self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2)

        self.author_label = QLabel(_('Set the author of the new books to:'))
        self._layout.addWidget(self.author_label, 2, 0, 1, 2)

        self.authors_combo = EditWithComplete(self)
        self.authors_combo.setSizeAdjustPolicy(
                self.authors_combo.AdjustToMinimumContentsLengthWithIcon)
        self.authors_combo.setEditable(True)
        self._layout.addWidget(self.authors_combo, 3, 0, 1, 1)
        self.initialize_authors(db, author)

        self.clear_button = QToolButton(self)
        self.clear_button.setIcon(QIcon(I('trash.png')))
        self.clear_button.setToolTip(_('Reset author to Unknown'))
        self.clear_button.clicked.connect(self.reset_author)
        self._layout.addWidget(self.clear_button, 3, 1, 1, 1)

        self.series_label = QLabel(_('Set the series of the new books to:'))
        self._layout.addWidget(self.series_label, 4, 0, 1, 2)

        self.series_combo = EditWithComplete(self)
        self.series_combo.setSizeAdjustPolicy(
                self.authors_combo.AdjustToMinimumContentsLengthWithIcon)
        self.series_combo.setEditable(True)
        self._layout.addWidget(self.series_combo, 5, 0, 1, 1)
        self.initialize_series(db, series)

        self.sclear_button = QToolButton(self)
        self.sclear_button.setIcon(QIcon(I('trash.png')))
        self.sclear_button.setToolTip(_('Reset series'))
        self.sclear_button.clicked.connect(self.reset_series)
        self._layout.addWidget(self.sclear_button, 5, 1, 1, 1)

        self.title_label = QLabel(_('Set the title of the new books to:'))
        self._layout.addWidget(self.title_label, 6, 0, 1, 2)

        self.title_edit = QLineEdit(self)
        self.title_edit.setText(title or '')
        self._layout.addWidget(self.title_edit, 7, 0, 1, 1)

        self.tclear_button = QToolButton(self)
        self.tclear_button.setIcon(QIcon(I('trash.png')))
        self.tclear_button.setToolTip(_('Reset title'))
        self.tclear_button.clicked.connect(self.title_edit.clear)
        self._layout.addWidget(self.tclear_button, 7, 1, 1, 1)

        self.format_label = QLabel(_('Also create an empty e-book in format:'))
        self._layout.addWidget(self.format_label, 8, 0, 1, 2)
        c = self.format_value = QComboBox(self)
        from calibre.ebooks.oeb.polish.create import valid_empty_formats
        possible_formats = [''] + sorted(x.upper() for x in valid_empty_formats)
        c.addItems(possible_formats)
        c.setToolTip(_('Also create an empty book format file that you can subsequently edit'))
        if gprefs.get('create_empty_epub_file', False):
            # Migration of the check box
            gprefs.set('create_empty_format_file', 'epub')
            del gprefs['create_empty_epub_file']
        use_format = gprefs.get('create_empty_format_file', '').upper()
        try:
            c.setCurrentIndex(possible_formats.index(use_format))
        except Exception:
            pass
        self._layout.addWidget(c, 9, 0, 1, 1)

        self.copy_formats = cf = QCheckBox(_('Also copy book &formats when duplicating a book'), self)
        cf.setToolTip(_(
            'Also copy all e-book files into the newly created duplicate'
            ' books.'))
        cf.setChecked(gprefs.get('create_empty_copy_dup_formats', False))
        self._layout.addWidget(cf, 10, 0, 1, -1)

        button_box = self.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)
        self._layout.addWidget(button_box, 11, 0, 1, -1)
        if dup_title:
            self.dup_button = b = button_box.addButton(_('&Duplicate current book'), button_box.ActionRole)
            b.clicked.connect(self.do_duplicate_book)
            b.setIcon(QIcon(I('edit-copy.png')))
            b.setToolTip(_(
                'Make the new empty book records exact duplicates\n'
                'of the current book "%s", with all metadata identical'
            ) % dup_title)
        self.resize(self.sizeHint())
        self.duplicate_current_book = False

    def do_duplicate_book(self):
        self.duplicate_current_book = True
        self.accept()

    def accept(self):
        self.save_settings()
        return QDialog.accept(self)

    def save_settings(self):
        gprefs['create_empty_format_file'] = self.format_value.currentText().lower()
        gprefs['create_empty_copy_dup_formats'] = self.copy_formats.isChecked()

    def reject(self):
        self.save_settings()
        return QDialog.reject(self)

    def reset_author(self, *args):
        self.authors_combo.setEditText(_('Unknown'))

    def reset_series(self):
        self.series_combo.setEditText('')

    def initialize_authors(self, db, author):
        au = author
        if not au:
            au = _('Unknown')
        self.authors_combo.show_initial_value(au.replace('|', ','))

        self.authors_combo.set_separator('&')
        self.authors_combo.set_space_before_sep(True)
        self.authors_combo.set_add_separator(tweaks['authors_completer_append_separator'])
        self.authors_combo.update_items_cache(db.all_author_names())

    def initialize_series(self, db, series):
        self.series_combo.show_initial_value(series or '')
        self.series_combo.update_items_cache(db.all_series_names())
        self.series_combo.set_separator(None)

    @property
    def qty_to_add(self):
        return self.qty_spinbox.value()

    @property
    def selected_authors(self):
        return string_to_authors(unicode_type(self.authors_combo.text()))

    @property
    def selected_series(self):
        return unicode_type(self.series_combo.text())

    @property
    def selected_title(self):
        return self.title_edit.text().strip()
Ejemplo n.º 18
0
class AddEmptyBookDialog(QDialog):

    def __init__(self, parent, db, author, series=None):
        QDialog.__init__(self, parent)
        self.db = db

        self.setWindowTitle(_('How many empty books?'))

        self._layout = QGridLayout(self)
        self.setLayout(self._layout)

        self.qty_label = QLabel(_('How many empty books should be added?'))
        self._layout.addWidget(self.qty_label, 0, 0, 1, 2)

        self.qty_spinbox = QSpinBox(self)
        self.qty_spinbox.setRange(1, 10000)
        self.qty_spinbox.setValue(1)
        self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2)

        self.author_label = QLabel(_('Set the author of the new books to:'))
        self._layout.addWidget(self.author_label, 2, 0, 1, 2)

        self.authors_combo = EditWithComplete(self)
        self.authors_combo.setSizeAdjustPolicy(
                self.authors_combo.AdjustToMinimumContentsLengthWithIcon)
        self.authors_combo.setEditable(True)
        self._layout.addWidget(self.authors_combo, 3, 0, 1, 1)
        self.initialize_authors(db, author)

        self.clear_button = QToolButton(self)
        self.clear_button.setIcon(QIcon(I('trash.png')))
        self.clear_button.setToolTip(_('Reset author to Unknown'))
        self.clear_button.clicked.connect(self.reset_author)
        self._layout.addWidget(self.clear_button, 3, 1, 1, 1)

        self.series_label = QLabel(_('Set the series of the new books to:'))
        self._layout.addWidget(self.series_label, 4, 0, 1, 2)

        self.series_combo = EditWithComplete(self)
        self.authors_combo.setSizeAdjustPolicy(
                self.authors_combo.AdjustToMinimumContentsLengthWithIcon)
        self.series_combo.setEditable(True)
        self._layout.addWidget(self.series_combo, 5, 0, 1, 1)
        self.initialize_series(db, series)

        self.sclear_button = QToolButton(self)
        self.sclear_button.setIcon(QIcon(I('trash.png')))
        self.sclear_button.setToolTip(_('Reset series'))
        self.sclear_button.clicked.connect(self.reset_series)
        self._layout.addWidget(self.sclear_button, 5, 1, 1, 1)

        self.create_epub = c = QCheckBox(_('Create an empty EPUB file as well'))
        c.setChecked(gprefs.get('create_empty_epub_file', False))
        c.setToolTip(_('Also create an empty EPUB file that you can subsequently edit'))
        self._layout.addWidget(c, 6, 0, 1, -1)

        button_box = self.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)
        self._layout.addWidget(button_box, 7, 0, 1, -1)
        self.resize(self.sizeHint())

    def accept(self):
        oval = gprefs.get('create_empty_epub_file', False)
        if self.create_epub.isChecked() != oval:
            gprefs['create_empty_epub_file'] = self.create_epub.isChecked()
        return QDialog.accept(self)

    def reset_author(self, *args):
        self.authors_combo.setEditText(_('Unknown'))

    def reset_series(self):
        self.series_combo.setEditText('')

    def initialize_authors(self, db, author):
        au = author
        if not au:
            au = _('Unknown')
        self.authors_combo.show_initial_value(au.replace('|', ','))

        self.authors_combo.set_separator('&')
        self.authors_combo.set_space_before_sep(True)
        self.authors_combo.set_add_separator(tweaks['authors_completer_append_separator'])
        self.authors_combo.update_items_cache(db.all_author_names())

    def initialize_series(self, db, series):
        self.series_combo.show_initial_value(series or '')
        self.series_combo.update_items_cache(db.all_series_names())
        self.series_combo.set_separator(None)

    @property
    def qty_to_add(self):
        return self.qty_spinbox.value()

    @property
    def selected_authors(self):
        return string_to_authors(unicode(self.authors_combo.text()))

    @property
    def selected_series(self):
        return unicode(self.series_combo.text())
Ejemplo n.º 19
0
class BulkSeries(BulkBase):

    def setup_ui(self, parent):
        self.make_widgets(parent, EditWithComplete)
        values = self.all_values = list(self.db.all_custom(num=self.col_id))
        values.sort(key=sort_key)
        self.main_widget.setSizeAdjustPolicy(self.main_widget.AdjustToMinimumContentsLengthWithIcon)
        self.main_widget.setMinimumContentsLength(25)
        self.widgets.append(QLabel('', parent))
        w = QWidget(parent)
        layout = QHBoxLayout(w)
        layout.setContentsMargins(0, 0, 0, 0)
        self.remove_series = QCheckBox(parent)
        self.remove_series.setText(_('Remove series'))
        layout.addWidget(self.remove_series)
        self.idx_widget = QCheckBox(parent)
        self.idx_widget.setText(_('Automatically number books'))
        layout.addWidget(self.idx_widget)
        self.force_number = QCheckBox(parent)
        self.force_number.setText(_('Force numbers to start with '))
        layout.addWidget(self.force_number)
        self.series_start_number = QSpinBox(parent)
        self.series_start_number.setMinimum(1)
        self.series_start_number.setMaximum(9999999)
        self.series_start_number.setProperty("value", 1)
        layout.addWidget(self.series_start_number)
        layout.addItem(QSpacerItem(20, 10, QSizePolicy.Expanding, QSizePolicy.Minimum))
        self.widgets.append(w)
        self.idx_widget.stateChanged.connect(self.check_changed_checkbox)
        self.force_number.stateChanged.connect(self.check_changed_checkbox)
        self.series_start_number.valueChanged.connect(self.check_changed_checkbox)
        self.remove_series.stateChanged.connect(self.check_changed_checkbox)
        self.ignore_change_signals = False

    def check_changed_checkbox(self):
        self.a_c_checkbox.setChecked(True)

    def initialize(self, book_id):
        self.idx_widget.setChecked(False)
        self.main_widget.set_separator(None)
        self.main_widget.update_items_cache(self.all_values)
        self.main_widget.setEditText('')
        self.a_c_checkbox.setChecked(False)

    def getter(self):
        n = unicode(self.main_widget.currentText()).strip()
        i = self.idx_widget.checkState()
        f = self.force_number.checkState()
        s = self.series_start_number.value()
        r = self.remove_series.checkState()
        return n, i, f, s, r

    def commit(self, book_ids, notify=False):
        if not self.a_c_checkbox.isChecked():
            return
        val, update_indices, force_start, at_value, clear = self.gui_val
        val = None if clear else self.normalize_ui_val(val)
        if clear or val != '':
            extras = []
            for book_id in book_ids:
                if clear:
                    extras.append(None)
                    continue
                if update_indices:
                    if force_start:
                        s_index = at_value
                        at_value += 1
                    elif tweaks['series_index_auto_increment'] != 'const':
                        s_index = self.db.get_next_cc_series_num_for(val, num=self.col_id)
                    else:
                        s_index = 1.0
                else:
                    s_index = self.db.get_custom_extra(book_id, num=self.col_id,
                                                       index_is_id=True)
                extras.append(s_index)
            self.db.set_custom_bulk(book_ids, val, extras=extras,
                                   num=self.col_id, notify=notify)
Ejemplo n.º 20
0
class GUI(QtWidgets.QMainWindow):
    def __init__(self):
        '''Asetetaan muuttujille alkuarvoja ohjelman suorittamiseksi'''
        super().__init__()
        self.title = "Lujuusanalysaattori"
        self.left = 200
        self.top = 200
        self.width = 1300
        self.height = 700
        self.palkin_default_pituus = 5
        self.square_size = 10
        self.ikkuna()
        self.button_height = 75
        self.button_width = 150
        self.button_separation = 25
        self.x = 0
        self.y = 0
        self.palkin_leveys = 700
        self.palkin_korkeus = 75
        self.palkin_keskipiste = 650
        self.palkin_paatypiste = 1000
        self.yksikko_arvo = 0
        self.voima = 20
        self.maks_jannitys = "-"
        self.asteikko_teksti = QGraphicsSimpleTextItem()
        '''Lisää QGraphicsScenen ruudukon piirtämistä varten'''
        self.scene = QtWidgets.QGraphicsScene()
        self.scene.setSceneRect(0, -20, self.width - 200, self.height - 100)
        '''Suoritetaan lukuisia metodeja, jolla ohjelma "alustetaan"'''
        self.aloita_simulaatio()
        self.simulaatioikkuna()
        self.simulaatio_nappi()
        self.materiaali_valikko()
        self.uusi_palkki_nappi()
        self.lisaa_tuki_nappi()
        self.lisaa_ulkoinen_voima_nappi()
        self.poista_ulkoinen_voima_nappi()
        self.vaihda_tuki_nappi()

        Ominaisuudet.alkuarvot(self)
        self.lisaa_palkki()
        self.palkin_pituus_valikko()
        self.yksikko_pituus()
        self.asteikko()
        self.lisaa_asteikko_arvo()
        self.asteikko_teksti.hide()
        self.tulos_teksti()
        self.lisaa_seina_tuki()
        self.lisaa_tuki_alhaalta()
        self.ulkoinen_voima_valikko()
        self.ulkoinen_voima_nuoli_alatuki()
        self.ulkoinen_voima_nuoli_seinatuki()
        Ominaisuudet.alkuarvot(self)
        '''Asetetaan tietyille napeille tietty näkyvyys'''
        self.lisaa_tuki.setEnabled(False)
        self.simuloi.setEnabled(False)
        self.show()

    def ikkuna(self):
        '''Tekee ohjelman pääikkunan'''
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.setWindowTitle('Lujuusanalysaattori')
        self.horizontal = QtWidgets.QHBoxLayout()
        '''Luo menubarin'''
        self.uusiAction = QAction("Uusi simulaatio", self)
        self.uusiAction.setStatusTip("Luo uusi rakenne")
        self.uusiAction.triggered.connect(self.uusi_rakenne)
        self.uusiAction.setEnabled(True)
        self.uusiAction.setShortcut("Ctrl+N")

        self.tallennaAction = QAction("Tallenna simulaatio", self)
        self.tallennaAction.setStatusTip("Tallenna simulaatio")
        self.tallennaAction.triggered.connect(self.tallenna_rakenne)
        self.tallennaAction.setEnabled(False)
        self.tallennaAction.setShortcut("Ctrl+S")

        self.avaaAction = QAction("Lataa simulaatio", self)
        self.avaaAction.setStatusTip("Lataa simulaatio tiedostosta")
        self.avaaAction.triggered.connect(self.lataa_tallennettu_rakenne)
        self.avaaAction.setShortcut("Ctrl+O")

        self.exitAction = QAction("Exit", self)
        self.exitAction.setToolTip("Lopeta ohjelma")
        self.exitAction.triggered.connect(self.close_application)
        self.exitAction.setShortcut("Ctrl+E")
        self.statusBar()

        mainMenu = self.menuBar()
        fileMenu = mainMenu.addMenu('&File')
        aboutMenu = mainMenu.addMenu('&About')
        fileMenu.addAction(self.uusiAction)
        fileMenu.addAction(self.avaaAction)
        fileMenu.addAction(self.tallennaAction)
        fileMenu.addAction(self.exitAction)

    def tallenna_rakenne(self):
        '''Hoitaa rakenteen tallentamisen'''
        tallennus = Tallennin.tallenin(self)
        if tallennus == True:
            '''Kerrotaan käyttäjälle, että tallennus onnistui'''
            msgBox = QMessageBox()
            msgBox.setText("Tallennus onnistui!")
            msgBox.setWindowTitle("Onnistunut Tallennus")
            msgBox.setMinimumWidth(50)
            msgBox.addButton(QPushButton('OK'), QMessageBox.NoRole)
            msgBox.exec_()

    def lataa_tallennettu_rakenne(self):
        '''Metodi avaa QFileDialog ikkunan, josta käyttäjä valitsee tiedoston, jossa aiemmin tallennettu rakenne sijaitsee. Vain .txt -tiedostot 
        ovat ladattavissa '''
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        tiedosto, _ = QFileDialog.getOpenFileName(self,
                                                  "Valitse tiedosto",
                                                  "",
                                                  "txt Files (*.txt)",
                                                  options=options)
        lataus = Lataaja.lataaja(self, tiedosto)
        if lataus == False:
            return

        if lataus == True:
            self.uusi_rakenne()
            Lataaja.lataaja(self, tiedosto)
            tuen_tyyppi = Ominaisuudet.palauta_tuen_tyyppi(self)
            '''Jos tuki on seinästä, piirretään sitä vastaava grafiikka'''
            if tuen_tyyppi == 0:
                self.nayta_seina_tuki()
                self.gradient_seina_tuki()
            '''Jos tuki on alhaalta, piirretään sitä vastaava grafiikka'''
            if tuen_tyyppi == 1:
                self.nayta_tuki_alhaalta()
                self.gradient_alatuki()

            if tuen_tyyppi != 2:
                self.vaihda_tuki.show()
                self.lisaa_tuki.hide()
            '''Jos ulkoinen voima on asetettu, piirretään se'''
            ulkoinen_voima = int(
                Ominaisuudet.onko_ulkoinen_voima_asetettu(self))
            if ulkoinen_voima == 1:
                self.nayta_ulkoinen_voima()

            self.nayta_palkki()
            Laskin.laskin(self)
            self.paivita_tulos_teksti()
            self.tulos.show()
            self.sp.setValue(float(Ominaisuudet.palauta_palkin_pituus(self)))
            self.uusiAction.setEnabled(True)
            self.simuloi.setEnabled(True)
            '''Kerrotaan käyttäjälle, että kaikki onnistui'''
            msgBox = QMessageBox()
            msgBox.setText("Lataus onnistui!")
            msgBox.setWindowTitle("Onnistunut lataus")
            msgBox.addButton(QPushButton('OK'), QMessageBox.NoRole)
            msgBox.exec_()

    def aloita_simulaatio(self):
        '''Aloittaa simulaation'''
        self.setCentralWidget(QtWidgets.QWidget())
        self.horizontal = QtWidgets.QHBoxLayout()
        self.centralWidget().setLayout(self.horizontal)

    def simulaatioikkuna(self):
        '''lisää view näyttämistä varten'''
        self.view = QtWidgets.QGraphicsView(self.scene, self)
        self.view.adjustSize()
        self.view.show()
        self.horizontal.addWidget(self.view)

    def uusi_palkki_nappi(self):
        '''Luo Uusi palkki -napin'''
        self.uusi_palkki = QPushButton('Uusi palkki')
        self.uusi_palkki.setToolTip("Lisää uusi palkki")
        self.uusi_palkki.move(0, 0)
        self.uusi_palkki.resize(self.button_width, self.button_height)
        self.uusi_palkki.font = QtGui.QFont()
        self.uusi_palkki.font.setPointSize(12)
        self.uusi_palkki.setFont(self.uusi_palkki.font)
        self.uusi_palkki.setEnabled(True)
        self.scene.addWidget(self.uusi_palkki)
        self.uusi_palkki.clicked.connect(self.nayta_palkki)

    def nayta_palkki(self):
        '''Näyttää kaikki palkkiin liittyvät komponentit sekä asettaa uusi palkki -napin toimimattomaksi'''
        self.rect.show()
        self.palkin_pituus.show()
        self.sp.show()
        self.yksikko.show()
        self.asteikko_teksti.show()
        self.line.show()
        self.nuoli_1.show()
        self.nuoli_2.show()
        self.uusi_palkki.setEnabled(False)
        self.lisaa_tuki.setEnabled(True)
        self.materiaali_valinta.setEnabled(True)

    def lisaa_palkki(self):
        '''lisää palkin'''
        self.rect = QGraphicsRectItem(300, 200, self.palkin_leveys,
                                      self.palkin_korkeus)
        self.rect.setBrush(QBrush(4))
        self.scene.addItem(self.rect)
        self.rect.hide()
        self.lisaa_tuki.setEnabled(True)
        '''Aina kun on uusi palkki luotu, voidaan aloittaa simulaatio alusta'''
        self.uusiAction.setEnabled(True)

    def lisaa_tuki_nappi(self):
        '''Luo Lisää tuki -napin'''
        self.lisaa_tuki = QPushButton("Lisää tuki")
        self.lisaa_tuki.setToolTip("Lisää tuki")
        self.lisaa_tuki.move(0, self.button_height + self.button_separation)
        self.lisaa_tuki.resize(self.button_width, self.button_height)
        self.lisaa_tuki.font = QtGui.QFont()
        self.lisaa_tuki.font.setPointSize(12)
        self.lisaa_tuki.setFont(self.lisaa_tuki.font)
        self.lisaa_tuki.setEnabled(False)
        self.lisaa_tuki.clicked.connect(self.valitse_tuki)
        self.scene.addWidget(self.lisaa_tuki)

    def vaihda_tuki_nappi(self):
        '''Luo vaihda tuki -napin'''
        self.vaihda_tuki = QPushButton("Vaihda tuki")
        self.vaihda_tuki.setToolTip("Vaihda tuki")
        self.vaihda_tuki.move(0, self.button_height + self.button_separation)
        self.vaihda_tuki.resize(self.button_width, self.button_height)
        self.vaihda_tuki.setFont(self.lisaa_tuki.font)
        self.vaihda_tuki.clicked.connect(self.valitse_tuki)
        self.scene.addWidget(self.vaihda_tuki)
        self.vaihda_tuki.hide()

    def valitse_tuki(self):
        '''Tuen valinta.
        Jos tuki on seinästä (tyyppi = 0), kysytään halutaanko vaihtaa.
        Jos haluaa muutetaan tuen grafiikka ja arvo'''

        if Ominaisuudet.palauta_tuen_tyyppi(self) == 0:
            msgBox = QMessageBox()
            msgBox.setText("Haluatko vaihtaa tuen tyyppiä?")
            msgBox.addButton(QPushButton('En'), QMessageBox.NoRole)
            msgBox.addButton(QPushButton('Kyllä'), QMessageBox.YesRole)
            vastaus = msgBox.exec_()
            self.rect.setBrush(QBrush(4))

            if vastaus == 1:
                self.viiva_1.hide()
                self.viiva_2.hide()
                self.viiva_3.hide()
                self.viiva_4.hide()
                self.nayta_tuki_alhaalta()

                if int(Ominaisuudet.onko_ulkoinen_voima_asetettu(self)) == 1:
                    self.viiva.hide()
                    self.nuoli_3.hide()
                    self.viiva_5.show()
                    self.nuoli_6.show()

                Ominaisuudet.tuki(self, 1)
            return
        '''Jos tuki on alhaalta (tyyppi = 1), kysytään halutaanko vaihtaa.
        Jos haluaa muutetaan tuen grafiikka ja arvo'''
        if Ominaisuudet.palauta_tuen_tyyppi(self) == 1:
            msgBox = QMessageBox()
            msgBox.setText("Haluatko vaihtaa tuen tyyppiä?")
            msgBox.addButton(QPushButton('Kyllä'), QMessageBox.YesRole)
            msgBox.addButton(QPushButton('En'), QMessageBox.NoRole)
            vastaus = msgBox.exec_()
            self.rect.setBrush(QBrush(4))

            if vastaus == 0:
                Ominaisuudet.tuki(self, 0)
                self.nuoli_4.hide()
                self.nuoli_5.hide()
                self.nayta_seina_tuki()

                if int(Ominaisuudet.onko_ulkoinen_voima_asetettu(self)) == 1:
                    self.viiva.show()
                    self.nuoli_3.show()
                    self.viiva_5.hide()
                    self.nuoli_6.hide()

            if vastaus == 1:
                pass
        '''Jos tukea ei ole (tyyppi = 2). Tuen tyypin valinta'''
        if Ominaisuudet.palauta_tuen_tyyppi(self) == 2:
            msgBox = QMessageBox()
            msgBox.setText("Valitse tuen tyyppi")
            msgBox.addButton(QPushButton('Seinätuki'), QMessageBox.YesRole)
            msgBox.addButton(QPushButton('Tuki alhaalta'), QMessageBox.NoRole)
            vastaus = msgBox.exec_()
            self.vaihda_tuki.show()
            self.lisaa_tuki.hide()

            if vastaus == 0:
                self.nayta_seina_tuki()
                Ominaisuudet.tuki(self, 0)

            if vastaus == 1:
                self.nayta_tuki_alhaalta()
                Ominaisuudet.tuki(self, 1)
        '''Joka tapauksessa asetetaan ulkoisen voiman lisääminen mahdolliseksi
        sekä maalataan palkki normaaliksi'''
        self.lisaa_ulkoinen_voima.setEnabled(True)
        self.simuloi.setEnabled(True)

    def nayta_seina_tuki(self):
        '''Näytetään seinätukea kuvaavat grafiikat'''
        self.viiva_1.show()
        self.viiva_2.show()
        self.viiva_3.show()
        self.viiva_4.show()

    def nayta_tuki_alhaalta(self):
        '''Näytetään alatukea kuvaavat grafiikat'''
        self.nuoli_4.show()
        self.nuoli_5.show()

    def paivita_tuen_tyyppi(self, tyyppi):
        '''Päivittää tuen tyypin arvon Ominaisuudet luokassa'''
        Ominaisuudet.tuki(self, tyyppi)

    def lisaa_seina_tuki(self):
        '''Piirtää seinätukea kuvaavat viivat sekä asettaa self.tuen_tyyppi arvoksi 
        Asettaa SIMULOI-napin painettavaksi'''
        viiva = QtGui.QPen(QtCore.Qt.black, 2)
        viiva.setStyle(QtCore.Qt.SolidLine)
        self.viiva_1 = QGraphicsLineItem(QtCore.QLineF(300, 202, 275, 225))
        self.viiva_2 = QGraphicsLineItem(QtCore.QLineF(300, 222, 275, 245))
        self.viiva_3 = QGraphicsLineItem(QtCore.QLineF(300, 242, 275, 265))
        self.viiva_4 = QGraphicsLineItem(QtCore.QLineF(300, 262, 275, 285))

        self.scene.addItem(self.viiva_1)
        self.scene.addItem(self.viiva_2)
        self.scene.addItem(self.viiva_3)
        self.scene.addItem(self.viiva_4)
        self.viiva_1.hide()
        self.viiva_2.hide()
        self.viiva_3.hide()
        self.viiva_4.hide()
        tyyppi = 0
        Ominaisuudet.tuki(self, tyyppi)
        self.simuloi.setEnabled(True)

    def lisaa_tuki_alhaalta(self):
        '''Piirtää alhaalta tukemista kuvaavat grafiikat
        sekä asettaa self.tuen_tyyppi arvoksi 1'''
        leveys = 15  #nuolen leveus pikseleissä
        korkeus = 30  #nuuolen korkeus pikseleissä
        '''Nuolen kärkien koordinaatit'''
        nuoli_piste_1 = QtCore.QPointF(305, 275)
        nuoli_piste_2 = QtCore.QPointF(305 - leveys, 275 + korkeus)
        nuoli_piste_3 = QtCore.QPointF(305 + leveys, 275 + korkeus)

        nuoli_piste_4 = QtCore.QPointF(995, 275)
        nuoli_piste_5 = QtCore.QPointF(995 - leveys, 275 + korkeus)
        nuoli_piste_6 = QtCore.QPointF(995 + leveys, 275 + korkeus)
        '''Luodaan nuolia kuvaavat QPolygonF oliot'''
        self.nuoli_4 = QGraphicsPolygonItem(
            QtGui.QPolygonF([nuoli_piste_1, nuoli_piste_2, nuoli_piste_3]))
        self.nuoli_5 = QGraphicsPolygonItem(
            QtGui.QPolygonF([nuoli_piste_4, nuoli_piste_5, nuoli_piste_6]))
        self.nuoli_brush = QtGui.QBrush(1)
        self.nuoli_pencil = QtGui.QPen(QtCore.Qt.black, 2)
        self.nuoli_pencil.setStyle(QtCore.Qt.SolidLine)
        '''Lisätään nuolet sceneen'''
        self.scene.addItem(self.nuoli_4)
        self.scene.addItem(self.nuoli_5)
        self.nuoli_4.hide()
        self.nuoli_5.hide()

        tyyppi = 1
        Ominaisuudet.tuki(self, tyyppi)
        self.simuloi.setEnabled(True)

    def lisaa_ulkoinen_voima_nappi(self):
        '''Luo Lisää ulkoinen voima -napin'''
        self.lisaa_ulkoinen_voima = QPushButton("Lisää ulkoinen voima")
        self.lisaa_ulkoinen_voima.setToolTip("Lisää ulkoinen voima")
        self.lisaa_ulkoinen_voima.move(
            0, 2 * self.button_height + 2 * self.button_separation)
        self.lisaa_ulkoinen_voima.resize(self.button_width, self.button_height)
        self.lisaa_ulkoinen_voima.font = QtGui.QFont()
        self.lisaa_ulkoinen_voima.font.setPointSize(8)
        self.lisaa_ulkoinen_voima.setFont(self.lisaa_ulkoinen_voima.font)
        self.lisaa_ulkoinen_voima.clicked.connect(self.nayta_ulkoinen_voima)
        self.lisaa_ulkoinen_voima.clicked.connect(self.nollaa_gradientti)
        self.lisaa_ulkoinen_voima.setEnabled(False)
        self.scene.addWidget(self.lisaa_ulkoinen_voima)

    def poista_ulkoinen_voima_nappi(self):
        '''Luo poista ulkoinen voima -napin'''
        self.poista_ulkoinen_voima = QPushButton("Poista ulkoinen voima")
        self.poista_ulkoinen_voima.setToolTip("Poista ulkoinen voima")
        self.poista_ulkoinen_voima.move(
            0, 2 * self.button_height + 2 * self.button_separation)
        self.poista_ulkoinen_voima.resize(self.button_width,
                                          self.button_height)
        self.poista_ulkoinen_voima.setFont(self.lisaa_ulkoinen_voima.font)
        self.poista_ulkoinen_voima.clicked.connect(self.piilota_ulkoinen_voima)
        self.poista_ulkoinen_voima.clicked.connect(self.nollaa_gradientti)
        self.scene.addWidget(self.poista_ulkoinen_voima)
        self.poista_ulkoinen_voima.hide()

    def piilota_ulkoinen_voima(self):
        '''Piilotaa kaiken ulkoiseen voimaan liittyvän'''
        self.sp_voima.hide()
        self.yksikko_voima.hide()
        self.ulkoinen_voima.hide()
        self.lisaa_ulkoinen_voima.show()
        self.lisaa_ulkoinen_voima.setEnabled(True)
        self.viiva.hide()
        self.nuoli_3.hide()
        self.viiva_5.hide()
        self.nuoli_6.hide()
        self.poista_ulkoinen_voima.hide()
        self.lisaa_ulkoinen_voima.show()
        self.tulos.hide()

        Ominaisuudet.ulkoinen_voima(self, 0)

    def nayta_ulkoinen_voima(self):
        '''Näytetään ulkoinen voima riippuen tuen tyypistä'''
        self.sp_voima.show()
        self.yksikko_voima.show()
        self.ulkoinen_voima.show()
        self.lisaa_ulkoinen_voima.hide()
        self.poista_ulkoinen_voima.show()

        if int(Ominaisuudet.palauta_tuen_tyyppi(self)) == 0:
            self.viiva.show()
            self.nuoli_3.show()

        if int(Ominaisuudet.palauta_tuen_tyyppi(self)) == 1:
            self.viiva_5.show()
            self.nuoli_6.show()

        Ominaisuudet.ulkoinen_voima(self, 1)

    def ulkoinen_voima_valikko(self):
        '''Luo voiman suuruus -tekstin'''
        self.ulkoinen_voima = QGraphicsSimpleTextItem("Voiman suuruus")
        self.ulkoinen_voima.setPos(600, 5)
        self.ulkoinen_voima.font = QtGui.QFont()
        self.ulkoinen_voima.font.setPointSize(12)
        self.ulkoinen_voima.setFont(self.ulkoinen_voima.font)
        self.lisaa_ulkoinen_voima.setEnabled(False)
        self.scene.addItem(self.ulkoinen_voima)
        self.ulkoinen_voima.hide()
        '''Luo voiman arvon QSpinBoxin'''
        self.sp_voima = QSpinBox()
        self.sp_voima.move(750, 5)
        self.sp_voima.setRange(0, 10000)
        self.sp_voima.setSingleStep(1)
        self.sp_voima.setMinimumHeight(30)
        self.sp_voima.setValue(int(Ominaisuudet.palauta_voima(self)))
        self.sp_voima.valueChanged.connect(self.paivita_voima)
        self.scene.addWidget(self.sp_voima)
        self.sp_voima.hide()
        '''Luo yksikönvalinta QComboBOxin'''
        self.yksikko_voima = QComboBox()
        self.yksikko_voima.addItem("kN", 0)
        self.yksikko_voima.addItem("N", 1)
        self.yksikko_voima.move(820, 5)
        self.yksikko_voima.setMinimumHeight(30)
        self.yksikko_voima.setCurrentIndex(
            int(Ominaisuudet.palauta_voiman_yksikko(self)))
        self.yksikko_voima.setEditable(True)
        self.yksikko_voima.lineEdit().setAlignment(QtCore.Qt.AlignCenter)
        self.scene.addWidget(self.yksikko_voima)
        self.yksikko_voima.currentIndexChanged.connect(
            self.paivita_yksikko_voima)
        self.yksikko_voima.hide()

    def ulkoinen_voima_nuoli_seinatuki(self):
        '''Luo nuolen osoittamaan ulkoisen voiman paikkaa'''
        voima_viiva = QtGui.QPen(QtCore.Qt.black, 2)
        voima_viiva.setStyle(QtCore.Qt.SolidLine)
        '''Nuolen kärkien koordinaatit seinätuelle'''
        nuoli_piste_1 = QtCore.QPointF(self.palkin_paatypiste - 7, 185)
        nuoli_piste_2 = QtCore.QPointF(self.palkin_paatypiste, 200)
        nuoli_piste_3 = QtCore.QPointF(self.palkin_paatypiste + 7, 185)
        viiva_x = self.palkin_paatypiste
        self.viiva = QGraphicsLineItem(
            QtCore.QLineF(viiva_x, 100, viiva_x, 200))
        '''Luodaan nuoli QPolygonItem olio'''
        self.nuoli_3 = QGraphicsPolygonItem(
            QtGui.QPolygonF([nuoli_piste_1, nuoli_piste_2, nuoli_piste_3]))
        self.nuoli_brush = QtGui.QBrush(1)
        self.nuoli_pencil = QtGui.QPen(QtCore.Qt.black, 2)
        self.nuoli_pencil.setStyle(QtCore.Qt.SolidLine)
        '''Lisätään viiva sekä päiden nuolet sceneen'''
        self.scene.addItem(self.viiva)
        self.scene.addItem(self.nuoli_3)
        self.viiva.hide()
        self.nuoli_3.hide()
        '''Lisätään tieto, että voima on asetettu'''
        Ominaisuudet.ulkoinen_voima(self, 1)

    def ulkoinen_voima_nuoli_alatuki(self):
        '''Nuolen kärkien koordinaatit alhaalta tuetulle palkille'''
        nuoli_piste_1 = QtCore.QPointF(self.palkin_keskipiste - 7, 185)
        nuoli_piste_2 = QtCore.QPointF(self.palkin_keskipiste, 200)
        nuoli_piste_3 = QtCore.QPointF(self.palkin_keskipiste + 7, 185)
        viiva_x = self.palkin_keskipiste
        '''Luodaan nuoli QPolygonItem olio'''
        self.nuoli_6 = QGraphicsPolygonItem(
            QtGui.QPolygonF([nuoli_piste_1, nuoli_piste_2, nuoli_piste_3]))
        self.nuoli_brush = QtGui.QBrush(1)
        self.nuoli_pencil = QtGui.QPen(QtCore.Qt.black, 2)
        self.nuoli_pencil.setStyle(QtCore.Qt.SolidLine)

        self.viiva_5 = QGraphicsLineItem(
            QtCore.QLineF(viiva_x, 100, viiva_x, 200))
        '''Lisätään viiva sekä päiden nuolet sceneen'''
        self.scene.addItem(self.viiva_5)
        self.scene.addItem(self.nuoli_6)
        self.viiva_5.hide()
        self.nuoli_6.hide()
        '''Lisätään tieto, että voima on asetettu'''
        Ominaisuudet.ulkoinen_voima(self, 1)

    def paivita_voima(self):
        '''Lukee voiman arvon 
        ja kutsuu Ominaisuudet luoka metodia voima'''
        voima = self.sp_voima.value()
        Ominaisuudet.voima(self, voima)

    def paivita_yksikko_voima(self):
        '''Lukee ykiskön arvon 
        ja kutsuu Ominaisuudet-luokan metodia yksikko_voima'''
        self.yksikko_voima_arvo = self.yksikko_voima.currentData()
        Ominaisuudet.yksikko_voima(self, self.yksikko_voima_arvo)

    def materiaali_valikko(self):
        ''' Luo Materiaali-otsikon'''
        self.materiaali = QGraphicsSimpleTextItem("Materiaali")
        self.materiaali.setPos(
            0, 3 * self.button_height + 3 * self.button_separation)
        self.materiaali.font = QtGui.QFont()
        self.materiaali.font.setPointSize(12)
        self.materiaali.setFont(self.materiaali.font)
        self.scene.addItem(self.materiaali)
        '''Luo drop down valikon materiaalivalinnalle'''
        self.materiaali_valinta = QComboBox()
        self.materiaali_valinta.addItem("Teräs", 0)
        self.materiaali_valinta.addItem("Alumiini", 1)
        self.materiaali_valinta.addItem("Muovi", 2)
        self.materiaali_valinta.move(
            0, 3 * self.button_height + 3 * self.button_separation + 25)
        self.materiaali_valinta.resize(self.button_width,
                                       self.button_height - 25)
        self.materiaali_valinta.setEditable(True)
        self.materiaali_valinta.lineEdit().setAlignment(QtCore.Qt.AlignCenter)
        self.materiaali_valinta.setCurrentIndex(0)
        self.scene.addWidget(self.materiaali_valinta)
        self.materiaali_valinta.setEnabled(False)
        self.materiaali_valinta.currentIndexChanged.connect(
            self.paivita_materiaali)

    def paivita_materiaali(self):
        '''Lukee materiaalin arvon 
        ja kutsuu Ominaisuudet-luokan metodia materiaali'''
        materiaali = self.materiaali_valinta.currentData()
        Ominaisuudet.materiaali(self, materiaali)

    def simulaatio_nappi(self):
        '''Luo SIMULOI-napin'''
        self.simuloi = QPushButton('SIMULOI')
        self.simuloi.setToolTip('Simuloi valittu rakenne')
        self.simuloi.move(0,
                          4 * self.button_height + 4 * self.button_separation)
        self.simuloi.setStyleSheet("background-color:rgb(122, 201, 255)")
        self.simuloi.resize(self.button_width, self.button_height)
        self.simuloi.font = QtGui.QFont()
        self.simuloi.font.setPointSize(12)
        self.simuloi.setFont(self.simuloi.font)
        self.simuloi.setEnabled(False)
        self.simuloi.clicked.connect(self.simulaatio)
        self.scene.addWidget(self.simuloi)

    def simulaatio(self):
        '''Kutsuu laskentaa suorittavaa metodia ja tallentaa tuloksen.
        Tämän jälkeen kutsuu lopputuloksen esittävän tekstin päivittävää metodia
        sekä palkin visualisoivaa gradient-metodia'''
        Laskin.laskin(self)
        Ominaisuudet.palauta_tulos(self)
        self.paivita_tulos_teksti()
        self.tallennaAction.setEnabled(True)

        if Ominaisuudet.palauta_tuen_tyyppi(self) == 0:

            if Ominaisuudet.onko_ulkoinen_voima_asetettu(self) == 1:
                self.gradient_seina_tuki()

            if Ominaisuudet.onko_ulkoinen_voima_asetettu(self) == 0:
                self.gradient_seina_tuki_ei_voimaa()

        if Ominaisuudet.palauta_tuen_tyyppi(self) == 1:
            self.gradient_alatuki()

    def tulos_teksti(self):
        '''Lisää tekstin, joka kertoo maksimijänintyksen arvon'''
        teksti = "Maksimijännitys " + str(self.maks_jannitys) + " MPa"
        self.tulos = QGraphicsSimpleTextItem(teksti)
        self.tulos.setPos(550, 500)
        self.tulos.font = QtGui.QFont()
        self.tulos.font.setPointSize(12)
        self.tulos.setFont(self.tulos.font)
        self.scene.addItem(self.tulos)
        self.tulos.hide()

    def paivita_tulos_teksti(self):
        '''Päivittää maksimijännityksen arvoa kuvaavan tekstin'''
        maks_jannitys = Ominaisuudet.palauta_tulos(self)
        self.tulos.setText("Maksimijännitys " + str(maks_jannitys) + " MPa")
        self.tulos.show()

    def palkin_pituus_valikko(self):
        '''Luo palkin pituus tekstin sekä spinbox-valitsimen pituuden asettamista varten
        Päivittää palkin pituuden Ominaisuudet luokan avulla'''
        self.palkin_pituus = QGraphicsSimpleTextItem("Palkin pituus")
        self.palkin_pituus.setPos(300, 5)
        self.palkin_pituus.font = QtGui.QFont()
        self.palkin_pituus.font.setPointSize(12)
        self.palkin_pituus.setFont(self.palkin_pituus.font)
        self.scene.addItem(self.palkin_pituus)
        self.palkin_pituus.hide()

        self.sp = QSpinBox()
        self.scene.addWidget(self.sp)
        self.sp.hide()
        self.sp.move(450, 5)
        self.sp.setRange(0, 100)
        self.sp.setSingleStep(1)
        self.sp.setMinimumHeight(30)
        self.sp.setValue(int(Ominaisuudet.palauta_palkin_pituus(self)))
        self.paivita_pituus()
        self.sp.valueChanged.connect(self.paivita_pituus)

    def paivita_pituus(self):
        '''Lukee palkin pituuden ja aktivoi Ominaisuudet luokan meodin palkin pituus'''
        self.palkin_pituus_arvo = self.sp.value()
        Ominaisuudet.palkin_pituus(self, self.palkin_pituus_arvo)
        self.paivita_asteikon_arvot()

    def yksikko_pituus(self):
        '''Luo yksikönvalinta dropdown-menun
        ja arvon muuttuessa päivittää yksikön Ominaisuudet-luokassa'''
        self.yksikko = QComboBox()
        self.yksikko.addItem("m", 0)
        self.yksikko.addItem("cm", 1)
        self.yksikko.addItem("mm", 2)
        self.yksikko.move(500, 5)
        self.yksikko.setMinimumHeight(30)
        self.yksikko.setEditable(True)
        self.yksikko.lineEdit().setAlignment(QtCore.Qt.AlignCenter)
        self.yksikko.setCurrentIndex(
            Ominaisuudet.palauta_pituuden_yksikko(self))
        self.scene.addWidget(self.yksikko)
        self.yksikko.hide()
        self.yksikko_arvo = self.yksikko.currentData()
        self.yksikko.currentIndexChanged.connect(self.paivita_yksikko)

    def paivita_yksikko(self):
        '''Lukee yksikön arvon 
        ja kutsuu Ominaisuudet-luokan metodia yksikko'''
        self.yksikko_arvo = self.yksikko.currentData()
        Ominaisuudet.yksikko(self, self.yksikko_arvo)
        self.paivita_asteikon_arvot()

    def asteikko(self):
        ''''Luodaan viivaa kuvaava olio'''
        viiva = QtGui.QPen(QtCore.Qt.black, 2)
        viiva.setStyle(QtCore.Qt.SolidLine)
        '''Oikean puoleisen nuolen kärkien koordinaatit'''
        nuoli_1_piste_1 = QtCore.QPointF(990, 390)
        nuoli_1_piste_2 = QtCore.QPointF(1000, 400)
        nuoli_1_piste_3 = QtCore.QPointF(990, 410)
        '''Vasemman puoleisen nuolen kärkien koordinaatit'''
        nuoli_2_piste_1 = QtCore.QPointF(310, 390)
        nuoli_2_piste_2 = QtCore.QPointF(300, 400)
        nuoli_2_piste_3 = QtCore.QPointF(310, 410)
        '''Luodaan nuoli QPolygonF oliot'''
        self.nuoli_1 = QGraphicsPolygonItem(
            QtGui.QPolygonF(
                [nuoli_1_piste_1, nuoli_1_piste_2, nuoli_1_piste_3]))
        self.nuoli_2 = QGraphicsPolygonItem(
            QtGui.QPolygonF(
                [nuoli_2_piste_1, nuoli_2_piste_2, nuoli_2_piste_3]))

        self.nuoli_brush = QtGui.QBrush(1)
        self.nuoli_pencil = QtGui.QPen(QtCore.Qt.black, 2)
        self.nuoli_pencil.setStyle(QtCore.Qt.SolidLine)

        self.line = QGraphicsLineItem(QtCore.QLineF(300, 400, 1000, 400))
        '''Lisätään viiva sekä päiden nuolet sceneen'''
        self.scene.addItem(self.line)
        self.scene.addItem(self.nuoli_1)
        self.scene.addItem(self.nuoli_2)
        self.line.hide()
        self.nuoli_1.hide()
        self.nuoli_2.hide()

    def lisaa_asteikko_arvo(self):
        '''Lisää tekstikentän pituuden arvolle sekä yksikölle'''
        teksti = (str(Ominaisuudet.palauta_palkin_pituus(self)) + " " + "m")
        self.asteikko_teksti = QGraphicsSimpleTextItem()
        self.asteikko_teksti.setText(teksti)
        self.asteikko_teksti.setPos(650, 425)
        self.asteikko_teksti.font = QtGui.QFont()
        self.asteikko_teksti.font.setPointSize(12)
        self.asteikko_teksti.setFont(self.asteikko_teksti.font)
        self.scene.addItem(self.asteikko_teksti)
        self.asteikko_teksti.hide()

    def paivita_asteikon_arvot(self):
        '''Päivittää palkin pituutta kuvaavan asteikon'''
        yksikko = Ominaisuudet.palauta_pituuden_yksikko(self)

        if yksikko == 0:
            self.yksikko_merkki = "m"
        if yksikko == 1:
            self.yksikko_merkki = "cm"
        if yksikko == 2:
            self.yksikko_merkki = "mm"

        pituus = float(Ominaisuudet.palauta_palkin_pituus(self))
        teksti = str(str(pituus) + " " + self.yksikko_merkki)
        self.asteikko_teksti.setText(teksti)
        self.asteikko_teksti.show()

    def gradient_seina_tuki(self):
        '''Luo seinästä tuetun palkin rasitusta kuvaavan gradientin'''
        gradient = QLinearGradient(300, 200, 300 + self.palkin_leveys, 200)
        gradient.setColorAt(0, QColor(244, 72, 66))
        gradient.setColorAt(1, QColor(65, 244, 83))
        self.rect.setBrush(gradient)

    def gradient_seina_tuki_ei_voimaa(self):
        '''Luo ilman ulkoista voimaa olevan gradientin'''
        gradient = QLinearGradient(300, 200, 300 + (self.palkin_leveys / 2),
                                   200)
        gradient.setColorAt(0, QColor(244, 72, 66))
        gradient.setColorAt(1, QColor(65, 244, 83))
        self.rect.setBrush(gradient)

    def gradient_alatuki(self):
        '''Luo kahdella alatuella olevan palkin rasitusta kuvaavan gradientin'''
        gradient = QLinearGradient(300, 200, 300 + self.palkin_leveys, 200)
        gradient.setColorAt(0, QColor(65, 244, 83))
        gradient.setColorAt(0.5, QColor(244, 72, 66))
        gradient.setColorAt(1, QColor(65, 244, 83))
        self.rect.setBrush(gradient)

    def nollaa_gradientti(self):
        '''Asettaa palkin "normaaliksi"'''
        self.rect.setBrush(QBrush(4))

    def uusi_rakenne(self):
        '''Muokkaa ikkunaa uuden simulaation luomista varten'''
        self.rect.hide()
        self.ulkoinen_voima.hide()
        self.sp_voima.hide()
        self.yksikko_voima.hide()
        self.nuoli_1.hide()
        self.nuoli_2.hide()
        self.nuoli_3.hide()
        self.nuoli_4.hide()
        self.nuoli_5.hide()
        self.nuoli_6.hide()
        self.viiva_1.hide()
        self.viiva_2.hide()
        self.viiva_3.hide()
        self.viiva_4.hide()
        self.viiva_5.hide()
        self.viiva.hide()
        self.palkin_pituus.hide()
        self.sp.hide()
        self.yksikko.hide()
        self.line.hide()
        self.asteikko_teksti.hide()
        self.tulos.hide()
        self.nollaa_gradientti()
        self.lisaa_tuki.show()
        self.vaihda_tuki.hide()
        self.poista_ulkoinen_voima.hide()
        self.lisaa_ulkoinen_voima.show()
        Ominaisuudet.alkuarvot(self)
        '''Asettaa napit'''
        self.uusi_palkki.setEnabled(True)
        self.lisaa_ulkoinen_voima.setEnabled(False)
        self.lisaa_tuki.setEnabled(False)
        self.simuloi.setEnabled(False)
        self.tallennaAction.setEnabled(False)
        '''Päivittää tuen tyypiksi arvon, joka vastaa, ettei tukea ole'''
        self.tuen_tyyppi = 2

    def close_application(self):
        '''sulkee ohjelman'''
        sys.exit()