Example #1
0
class MetadataGroupBox(DeviceOptionsGroupBox):

    def __init__(self, parent, device):
        super(MetadataGroupBox, self).__init__(parent, device)
        self.setTitle(_("Update metadata on the device"))

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

        self.setCheckable(True)
        self.setChecked(device.get_pref('update_device_metadata'))
        self.setToolTip(wrap_msg(_('Update the metadata on the device when it is connected. '
                               'Be careful when doing this as it will take time and could make the initial connection take a long time.')))

        self.update_series_checkbox = create_checkbox(
                             _("Set Series information"),
                             _('The book lists on the Kobo devices can display series information. '
                               'This is not read by the device from the sideloaded books. '
                               'Series information can only be added to the device after the book has been processed by the device. '
                               'Enable if you wish to set series information.'),
                             device.get_pref('update_series')
                             )
        self.options_layout.addWidget(self.update_series_checkbox, 0, 0, 1, 1)
        self.options_layout.setRowStretch(1, 1)

    @property
    def update_series(self):
        return self.update_series_checkbox.isChecked()

    @property
    def update_device_metadata(self):
        return self.isChecked()
Example #2
0
class BookUploadsGroupBox(DeviceOptionsGroupBox):

    def __init__(self, parent, device):
        super(BookUploadsGroupBox, self).__init__(parent, device)
        self.setTitle(_("Book Uploading"))

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

        self.modify_css_checkbox = create_checkbox(
                _("Modify CSS"),
                _('This allows addition of user CSS rules and removal of some CSS. '
                'When sending a book, the driver adds the contents of {0} to all stylesheets in the ePub. '
                'This file is searched for in the root directory of the main memory of the device. '
                'As well as this, if the file contains settings for the "orphans" or "widows", '
                'these are removed for all styles in the original stylesheet.').format(device.KOBO_EXTRA_CSSFILE),
                device.get_pref('modify_css')
                )

        self.options_layout.addWidget(self.modify_css_checkbox, 0, 0, 1, 2)
        self.options_layout.setRowStretch(1, 1)

    @property
    def modify_css(self):
        return self.modify_css_checkbox.isChecked()
Example #3
0
class MetadataGroupBox(DeviceOptionsGroupBox):
    def __init__(self, parent, device):
        super(MetadataGroupBox, self).__init__(parent, device)
        self.setTitle(_("Update metadata on the device"))

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

        self.setCheckable(True)
        self.setChecked(device.get_pref('update_device_metadata'))
        self.setToolTip(
            wrap_msg(
                _('Update the metadata on the device when it is connected. '
                  'Be careful when doing this as it will take time and could make the initial connection take a long time.'
                  )))

        self.update_series_checkbox = create_checkbox(
            _("Set series information"),
            _('The book lists on the Kobo devices can display series information. '
              'This is not read by the device from the sideloaded books. '
              'Series information can only be added to the device after the book has been processed by the device. '
              'Enable if you wish to set series information.'),
            device.get_pref('update_series'))
        self.options_layout.addWidget(self.update_series_checkbox, 0, 0, 1, 1)
        self.options_layout.setRowStretch(1, 1)

    @property
    def update_series(self):
        return self.update_series_checkbox.isChecked()

    @property
    def update_device_metadata(self):
        return self.isChecked()
Example #4
0
class CollectionsGroupBox(DeviceOptionsGroupBox):
    def __init__(self, parent, device):
        super(CollectionsGroupBox, self).__init__(parent, device)
        self.setTitle(_("Collections"))

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

        self.setCheckable(True)
        self.setChecked(device.get_pref('manage_collections'))
        self.setToolTip(
            wrap_msg(
                _('Create new bookshelves on the Kobo if they do not exist. This is only for firmware V2.0.0 or later.'
                  )))

        self.collections_columns_label = QLabel(_('Collections Columns'))
        self.collections_columns_edit = QLineEdit(self)
        self.collections_columns_edit.setToolTip(
            _('The Kobo from firmware V2.0.0 supports bookshelves.'
              ' These are created on the Kobo. ' +
              'Specify a tags type column for automatic management.'))
        self.collections_columns_edit.setText(
            device.get_pref('collections_columns'))

        self.create_collections_checkbox = create_checkbox(
            _("Create Collections"),
            _('Create new bookshelves on the Kobo if they do not exist. This is only for firmware V2.0.0 or later.'
              ), device.get_pref('create_collections'))
        self.delete_empty_collections_checkbox = create_checkbox(
            _('Delete Empty Bookshelves'),
            _('Delete any empty bookshelves from the Kobo when syncing is finished. This is only for firmware V2.0.0 or later.'
              ), device.get_pref('delete_empty_collections'))

        self.options_layout.addWidget(self.collections_columns_label, 1, 0, 1,
                                      1)
        self.options_layout.addWidget(self.collections_columns_edit, 1, 1, 1,
                                      1)
        self.options_layout.addWidget(self.create_collections_checkbox, 2, 0,
                                      1, 2)
        self.options_layout.addWidget(self.delete_empty_collections_checkbox,
                                      3, 0, 1, 2)
        self.options_layout.setRowStretch(4, 1)

    @property
    def manage_collections(self):
        return self.isChecked()

    @property
    def collections_columns(self):
        return self.collections_columns_edit.text().strip()

    @property
    def create_collections(self):
        return self.create_collections_checkbox.isChecked()

    @property
    def delete_empty_collections(self):
        return self.delete_empty_collections_checkbox.isChecked()
Example #5
0
class DeviceListGroupBox(DeviceOptionsGroupBox):

    def __init__(self, parent, device):
        super(DeviceListGroupBox, self).__init__(parent, device)
        self.setTitle(_("Show as on device"))

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

        self.show_recommendations_checkbox = create_checkbox(
                             _("Show Recommendations"),
                             _('Kobo shows recommendations on the device.  In some cases these have '
                               'files but in other cases they are just pointers to the web site to buy. '
                               'Enable if you wish to see/delete them.'),
                             device.get_pref('show_recommendations')
                             )

        self.show_archived_books_checkbox = create_checkbox(
                             _("Show archived books"),
                             _('Archived books are listed on the device but need to be downloaded to read.'
                               ' Use this option to show these books and match them with books in the calibre library.'),
                             device.get_pref('show_archived_books')
                             )

        self.show_previews_checkbox = create_checkbox(
                             _('Show Previews'),
                             _('Kobo previews are included on the Touch and some other versions'
                               ' by default they are no longer displayed as there is no good reason to '
                               'see them.  Enable if you wish to see/delete them.'),
                             device.get_pref('show_previews')
                             )

        self.options_layout.addWidget(self.show_recommendations_checkbox, 0, 0, 1, 1)
        self.options_layout.addWidget(self.show_archived_books_checkbox,  1, 0, 1, 1)
        self.options_layout.addWidget(self.show_previews_checkbox,        2, 0, 1, 1)
        self.options_layout.setRowStretch(3, 1)

    @property
    def show_recommendations(self):
        return self.show_recommendations_checkbox.isChecked()

    @property
    def show_archived_books(self):
        return self.show_archived_books_checkbox.isChecked()

    @property
    def show_previews(self):
        return self.show_previews_checkbox.isChecked()
Example #6
0
class AdvancedGroupBox(DeviceOptionsGroupBox):
    def __init__(self, parent, device):
        super(AdvancedGroupBox, self).__init__(parent, device,
                                               _("Advanced options"))
        #         self.setTitle(_("Advanced Options"))

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

        self.support_newer_firmware_checkbox = create_checkbox(
            _("Attempt to support newer firmware"),
            _('Kobo routinely updates the firmware and the '
              'database version. With this option calibre will attempt '
              'to perform full read-write functionality - Here be Dragons!! '
              'Enable only if you are comfortable with restoring your kobo '
              'to factory defaults and testing software. '
              'This driver supports firmware V2.x.x and DBVersion up to ') +
            unicode(device.supported_dbversion),
            device.get_pref('support_newer_firmware'))

        self.debugging_title_checkbox = create_checkbox(
            _("Title to test when debugging"),
            _('Part of title of a book that can be used when doing some tests for debugging. '
              'The test is to see if the string is contained in the title of a book. '
              'The better the match, the less extraneous output.'),
            device.get_pref('debugging_title'))
        self.debugging_title_label = QLabel(_('Title to test when debugging:'))
        self.debugging_title_edit = QLineEdit(self)
        self.debugging_title_edit.setToolTip(
            _('Part of title of a book that can be used when doing some tests for debugging. '
              'The test is to see if the string is contained in the title of a book. '
              'The better the match, the less extraneous output.'))
        self.debugging_title_edit.setText(device.get_pref('debugging_title'))
        self.debugging_title_label.setBuddy(self.debugging_title_edit)

        self.options_layout.addWidget(self.support_newer_firmware_checkbox, 0,
                                      0, 1, 2)
        self.options_layout.addWidget(self.debugging_title_label, 1, 0, 1, 1)
        self.options_layout.addWidget(self.debugging_title_edit, 1, 1, 1, 1)
        self.options_layout.setRowStretch(2, 2)

    @property
    def support_newer_firmware(self):
        return self.support_newer_firmware_checkbox.isChecked()

    @property
    def debugging_title(self):
        return self.debugging_title_edit.text().strip()
Example #7
0
class AdvancedGroupBox(DeviceOptionsGroupBox):

    def __init__(self, parent, device):
        super(AdvancedGroupBox, self).__init__(parent, device, _("Advanced Options"))
#         self.setTitle(_("Advanced Options"))

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

        self.support_newer_firmware_checkbox = create_checkbox(
                            _("Attempt to support newer firmware"),
                            _('Kobo routinely updates the firmware and the '
                              'database version.  With this option Calibre will attempt '
                              'to perform full read-write functionality - Here be Dragons!! '
                              'Enable only if you are comfortable with restoring your kobo '
                              'to factory defaults and testing software. '
                              'This driver supports firmware V2.x.x and DBVersion up to ') + unicode(
                                  device.supported_dbversion), device.get_pref('support_newer_firmware')
                             )

        self.debugging_title_checkbox = create_checkbox(
                             _("Title to test when debugging"),
                             _('Part of title of a book that can be used when doing some tests for debugging. '
                               'The test is to see if the string is contained in the title of a book. '
                               'The better the match, the less extraneous output.'),
                             device.get_pref('debugging_title')
                             )
        self.debugging_title_label = QLabel(_('Title to test when debugging:'))
        self.debugging_title_edit = QLineEdit(self)
        self.debugging_title_edit.setToolTip(_('Part of title of a book that can be used when doing some tests for debugging. '
                    'The test is to see if the string is contained in the title of a book. '
                    'The better the match, the less extraneous output.'))
        self.debugging_title_edit.setText(device.get_pref('debugging_title'))
        self.debugging_title_label.setBuddy(self.debugging_title_edit)

        self.options_layout.addWidget(self.support_newer_firmware_checkbox,   0, 0, 1, 2)
        self.options_layout.addWidget(self.debugging_title_label,             1, 0, 1, 1)
        self.options_layout.addWidget(self.debugging_title_edit,              1, 1, 1, 1)
        self.options_layout.setRowStretch(2, 2)

    @property
    def support_newer_firmware(self):
        return self.support_newer_firmware_checkbox.isChecked()

    @property
    def debugging_title(self):
        return self.debugging_title_edit.text().strip()
Example #8
0
class DeviceListGroupBox(DeviceOptionsGroupBox):

    def __init__(self, parent, device):
        super(DeviceListGroupBox, self).__init__(parent, device)
        self.setTitle(_("Show as on device"))

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

        self.show_recommendations_checkbox = create_checkbox(
                             _("Show recommendations"),
                             _('Kobo shows recommendations on the device.  In some cases these have '
                               'files but in other cases they are just pointers to the web site to buy. '
                               'Enable if you wish to see/delete them.'),
                             device.get_pref('show_recommendations')
                             )

        self.show_archived_books_checkbox = create_checkbox(
                             _("Show archived books"),
                             _('Archived books are listed on the device but need to be downloaded to read.'
                               ' Use this option to show these books and match them with books in the calibre library.'),
                             device.get_pref('show_archived_books')
                             )

        self.show_previews_checkbox = create_checkbox(
                             _('Show previews'),
                             _('Kobo previews are included on the Touch and some other versions'
                               ' by default they are no longer displayed as there is no good reason to '
                               'see them.  Enable if you wish to see/delete them.'),
                             device.get_pref('show_previews')
                             )

        self.options_layout.addWidget(self.show_recommendations_checkbox, 0, 0, 1, 1)
        self.options_layout.addWidget(self.show_archived_books_checkbox,  1, 0, 1, 1)
        self.options_layout.addWidget(self.show_previews_checkbox,        2, 0, 1, 1)

    @property
    def show_recommendations(self):
        return self.show_recommendations_checkbox.isChecked()

    @property
    def show_archived_books(self):
        return self.show_archived_books_checkbox.isChecked()

    @property
    def show_previews(self):
        return self.show_previews_checkbox.isChecked()
Example #9
0
class Tag(QWidget):
    def __init__(self, url: str, id: int):
        self.url = url
        self.id = id
        self.site_name = self.url[:url.find('.')]
        # self.update_site_name()
        super().__init__()
        self.initUi()
        self.is_deleted = False
        self.update_site_name()

    def initUi(self):
        self.gridLayout = QGridLayout()
        self.setLayout(self.gridLayout)
        self.gridLayout.setObjectName("gridLayout")
        # self.setGeometry(200, 200, 250, 40)
        self.tag_body = QPushButton(self.site_name, self)
        # self.tag_body.resize(250, 40)
        self.del_btn = QPushButton('x', self)
        # self.del_btn.resize(26, 26)
        # self.del_btn.move(215, 7)
        self.gridLayout.addWidget(self.tag_body, 0, 0, 1, 5)
        self.gridLayout.addWidget(self.del_btn, 0, 4, 1, 1)
        self.del_btn.setStyleSheet("""
            QPushButton{
            background-color: grey;
            border-style: outset;
            border-width: 1px;
            border-radius: 20px;
            border-color: black;
            padding: 2px;
            }
            """)

    def update_site_name(self):
        try:
            if 'https://www' in self.url:
                self.site_name = self.url.split('/')[2].split('.')[-2]
                # print(self.site_name)
                # print(self.site_name, self.url[12:], self.url, self.url[12:].find('.'))
            elif 'https://' in self.url:
                self.site_name = self.url.split('/')[2].split('.')[-2]
                # print(self.site_name)
            else:
                self.site_name = self.url.split('/')[0].split('.')[-2]
        except Exception:
            self.site_name = self.url
        self.tag_body.setText(self.site_name)
Example #10
0
class CoversGroupBox(DeviceOptionsGroupBox):
    def __init__(self, parent, device):
        super(CoversGroupBox, self).__init__(parent, device)
        self.setTitle(_("Upload covers"))

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

        self.setCheckable(True)
        self.setChecked(device.get_pref('upload_covers'))
        self.setToolTip(
            wrap_msg(
                _('Upload cover images from the calibre library when sending books to the device.'
                  )))

        self.upload_grayscale_checkbox = create_checkbox(
            _('Upload black and white Covers'),
            _('Convert covers to black and white when uploading'),
            device.get_pref('upload_grayscale'))

        self.keep_cover_aspect_checkbox = create_checkbox(
            _('Keep cover aspect ratio'),
            _('When uploading covers, do not change the aspect ratio when resizing for the device.'
              ' This is for firmware versions 2.3.1 and later.'),
            device.get_pref('keep_cover_aspect'))

        self.options_layout.addWidget(self.keep_cover_aspect_checkbox, 0, 0, 1,
                                      1)
        self.options_layout.addWidget(self.upload_grayscale_checkbox, 1, 0, 1,
                                      1)
        self.options_layout.setRowStretch(2, 1)

    @property
    def upload_covers(self):
        return self.isChecked()

    @property
    def upload_grayscale(self):
        return self.upload_grayscale_checkbox.isChecked()

    @property
    def keep_cover_aspect(self):
        return self.keep_cover_aspect_checkbox.isChecked()
Example #11
0
class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName(_fromUtf8("Dialog"))
        Dialog.resize(497, 235)
        self.gridLayout = QGridLayout(Dialog)
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        self.icon_label = QLabel(Dialog)
        self.icon_label.setMaximumSize(
            QtCore.QSize(COVER_ICON_SIZE, COVER_ICON_SIZE))
        self.icon_label.setText(_fromUtf8(""))
        self.icon_label.setPixmap(QPixmap(_fromUtf8(I("dialog_warning.png"))))
        self.icon_label.setScaledContents(False)
        self.icon_label.setObjectName(_fromUtf8("icon_label"))
        self.gridLayout.addWidget(self.icon_label, 0, 0, 1, 1)
        self.msg = QLabel(Dialog)
        self.msg.setText(_fromUtf8(""))
        self.msg.setWordWrap(True)
        self.msg.setOpenExternalLinks(True)
        self.msg.setObjectName(_fromUtf8("msg"))
        self.gridLayout.addWidget(self.msg, 0, 1, 1, 1)
        self.det_msg = QPlainTextEdit(Dialog)
        self.det_msg.setReadOnly(True)
        self.det_msg.setObjectName(_fromUtf8("det_msg"))
        self.gridLayout.addWidget(self.det_msg, 1, 0, 1, 2)
        self.bb = QDialogButtonBox(Dialog)
        self.bb.setOrientation(QtCore.Qt.Horizontal)
        self.bb.setStandardButtons(QDialogButtonBox.Ok)
        self.bb.setObjectName(_fromUtf8("bb"))
        self.gridLayout.addWidget(self.bb, 3, 0, 1, 2)
        self.toggle_checkbox = QCheckBox(Dialog)
        self.toggle_checkbox.setText(_fromUtf8(""))
        self.toggle_checkbox.setObjectName(_fromUtf8("toggle_checkbox"))
        self.gridLayout.addWidget(self.toggle_checkbox, 2, 0, 1, 2)

        self.retranslateUi(Dialog)
        self.bb.accepted.connect(Dialog.accept)
        self.bb.rejected.connect(Dialog.reject)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(_("Dialog"))
Example #12
0
class BookUploadsGroupBox(DeviceOptionsGroupBox):

    def __init__(self, parent, device):
        super(BookUploadsGroupBox, self).__init__(parent, device)
        self.setTitle(_("Book uploading"))

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

        self.modify_css_checkbox = create_checkbox(
                _("Modify CSS"),
                _('This allows addition of user CSS rules and removal of some CSS. '
                'When sending a book, the driver adds the contents of {0} to all stylesheets in the EPUB. '
                'This file is searched for in the root directory of the main memory of the device. '
                'As well as this, if the file contains settings for the "orphans" or "widows", '
                'these are removed for all styles in the original stylesheet.').format(device.KOBO_EXTRA_CSSFILE),
                device.get_pref('modify_css')
                )
        self.override_kobo_replace_existing_checkbox = create_checkbox(
                _("Do not treat replacements as new books"),
                _('When a new book is side-loaded, the Kobo firmware imports details of the book into the internal database. '
                'Even if the book is a replacement for an existing book, the Kobo will remove the book from the database and then treat it as a new book. '
                'This means that the reading status, bookmarks and collections for the book will be lost. '
                'This option overrides firmware behavior and attempts to prevent a book that has been resent from being treated as a new book. '
                'If you prefer to have replacements treated as new books, turn this option off.'
                ),
                device.get_pref('override_kobo_replace_existing')
                )

        self.options_layout.addWidget(self.modify_css_checkbox, 0, 0, 1, 2)
        self.options_layout.addWidget(self.override_kobo_replace_existing_checkbox, 1, 0, 1, 2)
        self.options_layout.setRowStretch(2, 1)

    @property
    def modify_css(self):
        return self.modify_css_checkbox.isChecked()

    @property
    def override_kobo_replace_existing(self):
        return self.override_kobo_replace_existing_checkbox.isChecked()
Example #13
0
class CoversGroupBox(DeviceOptionsGroupBox):

    def __init__(self, parent, device):
        super(CoversGroupBox, self).__init__(parent, device)
        self.setTitle(_("Upload covers"))

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

        self.setCheckable(True)
        self.setChecked(device.get_pref('upload_covers'))
        self.setToolTip(wrap_msg(_('Upload cover images from the calibre library when sending books to the device.')))

        self.upload_grayscale_checkbox = create_checkbox(
                             _('Upload Black and White Covers'),
                             _('Convert covers to Black and White when uploading'),
                             device.get_pref('upload_grayscale')
                             )

        self.keep_cover_aspect_checkbox = create_checkbox(
                             _('Keep cover aspect ratio'),
                             _('When uploading covers, do not change the aspect ratio when resizing for the device.'
                               ' This is for firmware versions 2.3.1 and later.'),
                             device.get_pref('keep_cover_aspect'))

        self.options_layout.addWidget(self.keep_cover_aspect_checkbox,    0, 0, 1, 1)
        self.options_layout.addWidget(self.upload_grayscale_checkbox,     1, 0, 1, 1)
        self.options_layout.setRowStretch(2, 1)

    @property
    def upload_covers(self):
        return self.isChecked()

    @property
    def upload_grayscale(self):
        return self.upload_grayscale_checkbox.isChecked()

    @property
    def keep_cover_aspect(self):
        return self.keep_cover_aspect_checkbox.isChecked()
class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName(_fromUtf8("Dialog"))
        Dialog.resize(497, 235)
        self.gridLayout = QGridLayout(Dialog)
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        self.icon_label = QLabel(Dialog)
        self.icon_label.setMaximumSize(QtCore.QSize(COVER_ICON_SIZE, COVER_ICON_SIZE))
        self.icon_label.setText(_fromUtf8(""))
        self.icon_label.setPixmap(QPixmap(_fromUtf8(I("dialog_warning.png"))))
        self.icon_label.setScaledContents(False)
        self.icon_label.setObjectName(_fromUtf8("icon_label"))
        self.gridLayout.addWidget(self.icon_label, 0, 0, 1, 1)
        self.msg = QLabel(Dialog)
        self.msg.setText(_fromUtf8(""))
        self.msg.setWordWrap(True)
        self.msg.setOpenExternalLinks(True)
        self.msg.setObjectName(_fromUtf8("msg"))
        self.gridLayout.addWidget(self.msg, 0, 1, 1, 1)
        self.det_msg = QPlainTextEdit(Dialog)
        self.det_msg.setReadOnly(True)
        self.det_msg.setObjectName(_fromUtf8("det_msg"))
        self.gridLayout.addWidget(self.det_msg, 1, 0, 1, 2)
        self.bb = QDialogButtonBox(Dialog)
        self.bb.setOrientation(QtCore.Qt.Horizontal)
        self.bb.setStandardButtons(QDialogButtonBox.Ok)
        self.bb.setObjectName(_fromUtf8("bb"))
        self.gridLayout.addWidget(self.bb, 3, 0, 1, 2)
        self.toggle_checkbox = QCheckBox(Dialog)
        self.toggle_checkbox.setText(_fromUtf8(""))
        self.toggle_checkbox.setObjectName(_fromUtf8("toggle_checkbox"))
        self.gridLayout.addWidget(self.toggle_checkbox, 2, 0, 1, 2)

        self.retranslateUi(Dialog)
        self.bb.accepted.connect(Dialog.accept)
        self.bb.rejected.connect(Dialog.reject)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(_("Dialog"))
Example #15
0
class BookUploadsGroupBox(DeviceOptionsGroupBox):

    def __init__(self, parent, device):
        super(BookUploadsGroupBox, self).__init__(parent, device)
        self.setTitle(_("Book uploading"))

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

        self.modify_css_checkbox = create_checkbox(
                _("Modify CSS"),
                _('This allows addition of user CSS rules and removal of some CSS. '
                'When sending a book, the driver adds the contents of {0} to all stylesheets in the EPUB. '
                'This file is searched for in the root directory of the main memory of the device. '
                'As well as this, if the file contains settings for the "orphans" or "widows", '
                'these are removed for all styles in the original stylesheet.').format(device.KOBO_EXTRA_CSSFILE),
                device.get_pref('modify_css')
                )
        self.override_kobo_replace_existing_checkbox = create_checkbox(
                _("Do not treat replacements as new books"),
                _('When a new book is side-loaded, the Kobo firmware imports details of the book into the internal database. '
                'Even if the book is a replacement for an existing book, the Kobo will remove the book from the database and then treat it as a new book. '
                'This means that the reading status, bookmarks and collections for the book will be lost. '
                'This option overrides firmware behavior and attempts to prevent a book that has been resent from being treated as a new book. '
                'If you prefer to have replacements treated as new books, turn this option off.'
                ),
                device.get_pref('override_kobo_replace_existing')
                )

        self.options_layout.addWidget(self.modify_css_checkbox, 0, 0, 1, 2)
        self.options_layout.addWidget(self.override_kobo_replace_existing_checkbox, 1, 0, 1, 2)

    @property
    def modify_css(self):
        return self.modify_css_checkbox.isChecked()

    @property
    def override_kobo_replace_existing(self):
        return self.override_kobo_replace_existing_checkbox.isChecked()
Example #16
0
class Master_Tag(QWidget):
    def __init__(self, name: str, tags: list, id: int):
        self.name = name
        self.tags = tags
        self.id = id
        # print(type(self.tags))
        super().__init__()
        self.initUi()
        self.is_deleted = False

    def initUi(self):
        self.gridLayout = QGridLayout()
        self.setLayout(self.gridLayout)
        self.gridLayout.setObjectName("gridLayout")
        # self.setGeometry(200, 200, 250, 40)
        self.tag_body = QPushButton(self.name, self)
        # self.tag_body.resize(250, 40)
        self.del_btn = QPushButton('x', self)

        # self.del_btn.resize(26, 26)
        # self.del_btn.move(215, 7)
        self.gridLayout.addWidget(self.tag_body, 0, 0, 1,
                                  5)  # row column row_span column_span
        self.gridLayout.addWidget(self.del_btn, 0, 4, 1, 1)
        self.del_btn.setStyleSheet("""
            QPushButton{
            background-color: grey;
            border-style: outset;
            border-width: 1px;
            border-radius: 20px;
            border-color: black;
            padding: 2px;
            }
            """)

    def add_tag(self, new: Tag):
        self.tags.append(new)
Example #17
0
class BookUploadsGroupBox(DeviceOptionsGroupBox):
    def __init__(self, parent, device):
        super(BookUploadsGroupBox, self).__init__(parent, device)
        self.setTitle(_("Book uploading"))

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

        self.modify_css_checkbox = create_checkbox(
            _("Modify CSS"),
            _('This allows addition of user CSS rules and removal of some CSS. '
              'When sending a book, the driver adds the contents of {0} to all stylesheets in the EPUB. '
              'This file is searched for in the root directory of the main memory of the device. '
              'As well as this, if the file contains settings for the "orphans" or "widows", '
              'these are removed for all styles in the original stylesheet.').
            format(device.KOBO_EXTRA_CSSFILE), device.get_pref('modify_css'))

        self.options_layout.addWidget(self.modify_css_checkbox, 0, 0, 1, 2)
        self.options_layout.setRowStretch(1, 1)

    @property
    def modify_css(self):
        return self.modify_css_checkbox.isChecked()
Example #18
0
class CoversGroupBox(DeviceOptionsGroupBox):

    def __init__(self, parent, device):
        super(CoversGroupBox, self).__init__(parent, device)
        self.setTitle(_("Upload covers"))

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

        self.setCheckable(True)
        self.setChecked(device.get_pref('upload_covers'))
        self.setToolTip(wrap_msg(_('Upload cover images from the calibre library when sending books to the device.')))

        self.upload_grayscale_checkbox = create_checkbox(
                             _('Upload black and white covers'),
                             _('Convert covers to grayscale when uploading.'),
                             device.get_pref('upload_grayscale')
                             )

        self.dithered_covers_checkbox = create_checkbox(
                             _('Upload dithered covers'),
                             _('Dither cover images to the appropriate 16c grayscale palette for an eInk screen.'
                               ' This usually ensures greater accuracy and avoids banding, making sleep covers look better.'
                               ' Note that in some cases, you might want to leave this disabled,'
                               ' as Nickel will do a better job than Calibre, especially on newer FW versions (>= 4.11)!'
                               ' Unfortunately, this desirable behavior appears to depend on the exact device and FW version combo...'
                               ' Has no effect without "Upload black and white covers"!'),
                             device.get_pref('dithered_covers')
                             )
        # Make it visually depend on B&W being enabled!
        # c.f., https://stackoverflow.com/q/36281103
        self.dithered_covers_checkbox.setEnabled(device.get_pref('upload_grayscale'))
        self.upload_grayscale_checkbox.toggled.connect(self.dithered_covers_checkbox.setEnabled)
        self.upload_grayscale_checkbox.toggled.connect(
            lambda checked: not checked and self.dithered_covers_checkbox.setChecked(False))

        self.keep_cover_aspect_checkbox = create_checkbox(
                             _('Keep cover aspect ratio'),
                             _('When uploading covers, do not change the aspect ratio when resizing for the device.'
                               ' This is for firmware versions 2.3.1 and later.'),
                             device.get_pref('keep_cover_aspect'))

        self.letterbox_fs_covers_checkbox = create_checkbox(
                             _('Letterbox full-screen covers'),
                             _('Do it on our end, instead of letting nickel handle it.'
                               ' Provides pixel-perfect results on devices where Nickel does not do extra processing.'
                               ' Obviously has no effect without "Keep cover aspect ratio".'
                               ' This is also probably undesirable if you disable the "Show book covers full screen"'
                               ' setting on your device.'),
                             device.get_pref('letterbox_fs_covers'))
        # Make it visually depend on AR being enabled!
        self.letterbox_fs_covers_checkbox.setEnabled(device.get_pref('keep_cover_aspect'))
        self.keep_cover_aspect_checkbox.toggled.connect(self.letterbox_fs_covers_checkbox.setEnabled)
        self.keep_cover_aspect_checkbox.toggled.connect(
            lambda checked: not checked and self.letterbox_fs_covers_checkbox.setChecked(False))

        self.png_covers_checkbox = create_checkbox(
                             _('Save covers as PNG'),
                             _('Use the PNG image format instead of JPG.'
                               ' Higher quality, especially with "Upload dithered covers" enabled,'
                               ' which will also help generate potentially smaller files.'
                               ' Behavior completely unknown on "old" Kobo firmwares,'
                               ' last tested on FW 4.9 to 4.12.'
                               ' Has no effect without "Upload black and white covers"!'),
                             device.get_pref('png_covers'))
        # Make it visually depend on B&W being enabled, to avoid storing ridiculously large color PNGs.
        self.png_covers_checkbox.setEnabled(device.get_pref('upload_grayscale'))
        self.upload_grayscale_checkbox.toggled.connect(self.png_covers_checkbox.setEnabled)
        self.upload_grayscale_checkbox.toggled.connect(
            lambda checked: not checked and self.png_covers_checkbox.setChecked(False))

        self.options_layout.addWidget(self.keep_cover_aspect_checkbox,    0, 0, 1, 1)
        self.options_layout.addWidget(self.upload_grayscale_checkbox,     1, 0, 1, 1)
        self.options_layout.addWidget(self.dithered_covers_checkbox,      2, 0, 1, 1)
        self.options_layout.addWidget(self.letterbox_fs_covers_checkbox,  3, 0, 1, 1)
        self.options_layout.addWidget(self.png_covers_checkbox,           4, 0, 1, 1)

    @property
    def upload_covers(self):
        return self.isChecked()

    @property
    def upload_grayscale(self):
        return self.upload_grayscale_checkbox.isChecked()

    @property
    def dithered_covers(self):
        return self.dithered_covers_checkbox.isChecked()

    @property
    def keep_cover_aspect(self):
        return self.keep_cover_aspect_checkbox.isChecked()

    @property
    def letterbox_fs_covers(self):
        return self.letterbox_fs_covers_checkbox.isChecked()

    @property
    def png_covers(self):
        return self.png_covers_checkbox.isChecked()
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.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.setRowStretch(6, 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()
Example #20
0
class ExtraCustomization(DeviceConfigTab):  # {{{
    def __init__(self, extra_customization_message,
                 extra_customization_choices, device_settings):
        super(ExtraCustomization, self).__init__()

        debug_print(
            "ExtraCustomization.__init__ - extra_customization_message=",
            extra_customization_message)
        debug_print(
            "ExtraCustomization.__init__ - extra_customization_choices=",
            extra_customization_choices)
        debug_print(
            "ExtraCustomization.__init__ - device_settings.extra_customization=",
            device_settings.extra_customization)
        debug_print("ExtraCustomization.__init__ - device_settings=",
                    device_settings)
        self.extra_customization_message = extra_customization_message

        self.l = QVBoxLayout(self)
        self.setLayout(self.l)

        options_group = QGroupBox(_("Extra driver customization options"),
                                  self)
        self.l.addWidget(options_group)
        self.extra_layout = QGridLayout()
        self.extra_layout.setObjectName("extra_layout")
        options_group.setLayout(self.extra_layout)

        if extra_customization_message:
            extra_customization_choices = extra_customization_choices or {}

            def parse_msg(m):
                msg, _, tt = m.partition(':::') if m else ('', '', '')
                return msg.strip(), textwrap.fill(tt.strip(), 100)

            if isinstance(extra_customization_message, list):
                self.opt_extra_customization = []
                if len(extra_customization_message) > 6:
                    row_func = lambda x, y: ((x / 2) * 2) + y
                    col_func = lambda x: x % 2
                else:
                    row_func = lambda x, y: x * 2 + y
                    col_func = lambda x: 0

                for i, m in enumerate(extra_customization_message):
                    label_text, tt = parse_msg(m)
                    if not label_text:
                        self.opt_extra_customization.append(None)
                        continue
                    if isinstance(device_settings.extra_customization[i],
                                  bool):
                        self.opt_extra_customization.append(
                            QCheckBox(label_text))
                        self.opt_extra_customization[-1].setToolTip(tt)
                        self.opt_extra_customization[i].setChecked(
                            bool(device_settings.extra_customization[i]))
                    elif i in extra_customization_choices:
                        cb = QComboBox(self)
                        self.opt_extra_customization.append(cb)
                        l = QLabel(label_text)
                        l.setToolTip(tt), cb.setToolTip(tt), l.setBuddy(
                            cb), cb.setToolTip(tt)
                        for li in sorted(extra_customization_choices[i]):
                            self.opt_extra_customization[i].addItem(li)
                        cb.setCurrentIndex(
                            max(
                                0,
                                cb.findText(
                                    device_settings.extra_customization[i])))
                    else:
                        self.opt_extra_customization.append(QLineEdit(self))
                        l = QLabel(label_text)
                        l.setToolTip(tt)
                        self.opt_extra_customization[i].setToolTip(tt)
                        l.setBuddy(self.opt_extra_customization[i])
                        l.setWordWrap(True)
                        self.opt_extra_customization[i].setText(
                            device_settings.extra_customization[i])
                        self.opt_extra_customization[i].setCursorPosition(0)
                        self.extra_layout.addWidget(l, row_func(i + 2, 0),
                                                    col_func(i))
                    self.extra_layout.addWidget(
                        self.opt_extra_customization[i], row_func(i + 2, 1),
                        col_func(i))
                spacerItem1 = QSpacerItem(10, 10, QSizePolicy.Minimum,
                                          QSizePolicy.Expanding)
                self.extra_layout.addItem(spacerItem1, row_func(i + 2 + 2, 1),
                                          0, 1, 2)
                self.extra_layout.setRowStretch(row_func(i + 2 + 2, 1), 2)
            else:
                self.opt_extra_customization = QLineEdit()
                label_text, tt = parse_msg(extra_customization_message)
                l = QLabel(label_text)
                l.setToolTip(tt)
                l.setBuddy(self.opt_extra_customization)
                l.setWordWrap(True)
                if device_settings.extra_customization:
                    self.opt_extra_customization.setText(
                        device_settings.extra_customization)
                    self.opt_extra_customization.setCursorPosition(0)
                self.opt_extra_customization.setCursorPosition(0)
                self.extra_layout.addWidget(l, 0, 0)
                self.extra_layout.addWidget(self.opt_extra_customization, 1, 0)

    def extra_customization(self):
        ec = []
        if self.extra_customization_message:
            if isinstance(self.extra_customization_message, list):
                for i in range(0, len(self.extra_customization_message)):
                    if self.opt_extra_customization[i] is None:
                        ec.append(None)
                        continue
                    if hasattr(self.opt_extra_customization[i], 'isChecked'):
                        ec.append(self.opt_extra_customization[i].isChecked())
                    elif hasattr(self.opt_extra_customization[i],
                                 'currentText'):
                        ec.append(
                            unicode(self.opt_extra_customization[i].
                                    currentText()).strip())
                    else:
                        ec.append(
                            unicode(self.opt_extra_customization[i].text()).
                            strip())
            else:
                ec = unicode(self.opt_extra_customization.text()).strip()
                if not ec:
                    ec = None

        return ec

    @property
    def has_extra_customizations(self):
        debug_print(
            "ExtraCustomization::has_extra_customizations - self.extra_customization_message",
            self.extra_customization_message)
        return self.extra_customization_message and len(
            self.extra_customization_message) > 0
Example #21
0
class MetadataGroupBox(DeviceOptionsGroupBox):

    def __init__(self, parent, device):
        super(MetadataGroupBox, self).__init__(parent, device)
        self.setTitle(_("Update metadata on the device"))

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

        self.setCheckable(True)
        self.setChecked(device.get_pref('update_device_metadata'))
        self.setToolTip(wrap_msg(_('Update the metadata on the device when it is connected. '
                               'Be careful when doing this as it will take time and could make the initial connection take a long time.')))

        self.update_series_checkbox = create_checkbox(
                             _("Set series information"),
                             _('The book lists on the Kobo devices can display series information. '
                               'This is not read by the device from the sideloaded books. '
                               'Series information can only be added to the device after the book has been processed by the device. '
                               'Enable if you wish to set series information.'),
                             device.get_pref('update_series')
                             )
        self.update_core_metadata_checkbox = create_checkbox(
                             _("Update metadata on Book Details pages"),
                             _('This will update the metadata in the device database when the device is connected. '
                               'The metadata updated is displayed on the device in the library and the book details page. '
                               'This is the Title, Authors, Comments/Synopsis, Series name and number, Publisher and Published Date, ISBN and Language. '
                               'If a metadata plugboard exists for the device and book format, this will be used to set the metadata.'
                               ),
                             device.get_pref('update_core_metadata')
                             )

        self.update_purchased_kepubs_checkbox = create_checkbox(
                             _("Update purchased books"),
                             _('Update books purchased from Kobo and downloaded to the device.'
                               ),
                             device.get_pref('update_purchased_kepubs')
                             )
        self.update_subtitle_checkbox = create_checkbox(
                             _("Subtitle"),
                             _('Update the subtitle on the device using a template.'),
                             device.get_pref('update_subtitle')
                             )
        self.subtitle_template_edit = TemplateConfig(
                            device.get_pref('subtitle_template'),
                            tooltip=_("Enter a template to use to set the subtitle. "
                                      "If the template is empty, the subtitle will be cleared."
                                      )
                            )

        self.options_layout.addWidget(self.update_series_checkbox, 0, 0, 1, 2)
        self.options_layout.addWidget(self.update_core_metadata_checkbox, 1, 0, 1, 2)
        self.options_layout.addWidget(self.update_subtitle_checkbox, 2, 0, 1, 1)
        self.options_layout.addWidget(self.subtitle_template_edit, 2, 1, 1, 1)
        self.options_layout.addWidget(self.update_purchased_kepubs_checkbox, 3, 0, 1, 2)

        self.update_core_metadata_checkbox.clicked.connect(self.update_core_metadata_checkbox_clicked)
        self.update_subtitle_checkbox.clicked.connect(self.update_subtitle_checkbox_clicked)
        self.update_core_metadata_checkbox_clicked(device.get_pref('update_core_metadata'))
        self.update_subtitle_checkbox_clicked(device.get_pref('update_subtitle'))

    def update_core_metadata_checkbox_clicked(self, checked):
        self.update_series_checkbox.setEnabled(not checked)
        self.subtitle_template_edit.setEnabled(checked)
        self.update_subtitle_checkbox.setEnabled(checked)
        self.update_subtitle_checkbox_clicked(self.update_subtitle)
        self.update_purchased_kepubs_checkbox.setEnabled(checked)

    def update_subtitle_checkbox_clicked(self, checked):
        self.subtitle_template_edit.setEnabled(checked and self.update_core_metadata)

    def edit_template(self):
        t = TemplateDialog(self, self.template)
        t.setWindowTitle(_('Edit template'))
        if t.exec_():
            self.t.setText(t.rule[1])

    def validate(self):
        if self.update_subtitle and not self.subtitle_template_edit.validate():
            return False
        return True

    @property
    def update_series(self):
        return self.update_series_checkbox.isChecked()

    @property
    def update_core_metadata(self):
        return self.update_core_metadata_checkbox.isChecked()

    @property
    def update_purchased_kepubs(self):
        return self.update_purchased_kepubs_checkbox.isChecked()

    @property
    def update_device_metadata(self):
        return self.isChecked()

    @property
    def subtitle_template(self):
        return self.subtitle_template_edit.template

    @property
    def update_subtitle(self):
        return self.update_subtitle_checkbox.isChecked()
Example #22
0
class ExtendedGroupBox(DeviceOptionsGroupBox):
    def __init__(self, parent, device):
        super(ExtendedGroupBox, self).__init__(parent, device,
                                               _("Extended driver"))

        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'),
            _('Choose whether to enable extra customizations'),
            device.get_pref('extra_features'))

        self.upload_encumbered_checkbox = create_checkbox(
            _('Upload DRM-encumbered ePub files'),
            _('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'),
            _('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'),
            _('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.replace_lang_checkbox = create_checkbox(
            _('Replace Content Language Code'),
            _('Select this to replace the defined language in each content '
              'file inside the ePub.'), device.get_pref('replace_lang'))

        self.smarten_punctuation_checkbox = create_checkbox(
            _('Smarten Punctuation'),
            _('Select this to smarten punctuation in the ePub'),
            device.get_pref('smarten_punctuation'))

        self.clean_markup_checkbox = create_checkbox(
            _('Clean up ePub Markup'),
            _('Select this to clean up the internal ePub markup.'),
            device.get_pref('clean_markup'))

        self.file_copy_dir_checkbox = create_checkbox(
            _('Copy generated KePub files to a directory'),
            _('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'))
        self.file_copy_dir_edit = QLineEdit(self)
        self.file_copy_dir_edit.setToolTip(
            _('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'),
            _('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'),
            _('Select this to disable hyphenation for books.'),
            device.get_pref('disable_hyphenation'))

        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.replace_lang_checkbox, 2, 0, 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.setRowStretch(6, 2)

    @property
    def extra_features(self):
        return self.extra_features_checkbox.isChecked()

    @property
    def upload_encumbered(self):
        return self.upload_encumbered_checkbox.isChecked()

    @property
    def skip_failed(self):
        return self.skip_failed_checkbox.isChecked()

    @property
    def hyphenate(self):
        return self.hyphenate_checkbox.isChecked()

    @property
    def replace_lang(self):
        return self.replace_lang_checkbox.isChecked()

    @property
    def smarten_punctuation(self):
        return self.smarten_punctuation_checkbox.isChecked()

    @property
    def clean_markup(self):
        return self.clean_markup_checkbox.isChecked()

    @property
    def full_page_numbers(self):
        return self.full_page_numbers_checkbox.isChecked()

    @property
    def disable_hyphenation(self):
        return self.disable_hyphenation_checkbox.isChecked()

    @property
    def file_copy_dir(self):
        return self.file_copy_dir_edit.text().strip()
Example #23
0
class CollectionsGroupBox(DeviceOptionsGroupBox):

    def __init__(self, parent, device):
        super(CollectionsGroupBox, self).__init__(parent, device)
        self.setTitle(_("Collections"))

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

        self.setCheckable(True)
        self.setChecked(device.get_pref('manage_collections'))
        self.setToolTip(wrap_msg(_('Create new bookshelves on the Kobo if they do not exist. This is only for firmware V2.0.0 or later.')))

        self.collections_columns_label = QLabel(_('Collections Columns:'))
        self.collections_columns_edit = QLineEdit(self)
        self.collections_columns_edit.setToolTip(_('The Kobo from firmware V2.0.0 supports bookshelves.'
                ' These are created on the Kobo. ' +
                'Specify a tags type column for automatic management.'))
        self.collections_columns_edit.setText(device.get_pref('collections_columns'))

        self.create_collections_checkbox = create_checkbox(
                         _("Create Collections"),
                         _('Create new bookshelves on the Kobo if they do not exist. This is only for firmware V2.0.0 or later.'),
                         device.get_pref('create_collections')
                         )
        self.delete_empty_collections_checkbox = create_checkbox(
                         _('Delete Empty Bookshelves'),
                         _('Delete any empty bookshelves from the Kobo when syncing is finished. This is only for firmware V2.0.0 or later.'),
                         device.get_pref('delete_empty_collections')
                         )

        self.ignore_collections_names_label = QLabel(_('Ignore Collections:'))
        self.ignore_collections_names_edit = QLineEdit(self)
        self.ignore_collections_names_edit.setToolTip(_('List the names of collections to be ignored by ' +
                'the collection management. The collections listed ' +
                'will not be changed. Names are separated by commas.'))
        self.ignore_collections_names_edit.setText(device.get_pref('ignore_collections_names'))

        self.options_layout.addWidget(self.collections_columns_label,         1, 0, 1, 1)
        self.options_layout.addWidget(self.collections_columns_edit,          1, 1, 1, 1)
        self.options_layout.addWidget(self.create_collections_checkbox,       2, 0, 1, 2)
        self.options_layout.addWidget(self.delete_empty_collections_checkbox, 3, 0, 1, 2)
        self.options_layout.addWidget(self.ignore_collections_names_label,    4, 0, 1, 1)
        self.options_layout.addWidget(self.ignore_collections_names_edit,     4, 1, 1, 1)
        self.options_layout.setRowStretch(4, 1)

    @property
    def manage_collections(self):
        return self.isChecked()

    @property
    def collections_columns(self):
        return self.collections_columns_edit.text().strip()

    @property
    def create_collections(self):
        return self.create_collections_checkbox.isChecked()

    @property
    def delete_empty_collections(self):
        return self.delete_empty_collections_checkbox.isChecked()

    @property
    def ignore_collections_names(self):
        return self.ignore_collections_names_edit.text().strip()
Example #24
0
class ExtraCustomization(DeviceConfigTab):  # {{{

    def __init__(self, extra_customization_message, extra_customization_choices, device_settings):
        super(ExtraCustomization, self).__init__()

        debug_print("ExtraCustomization.__init__ - extra_customization_message=", extra_customization_message)
        debug_print("ExtraCustomization.__init__ - extra_customization_choices=", extra_customization_choices)
        debug_print("ExtraCustomization.__init__ - device_settings.extra_customization=", device_settings.extra_customization)
        debug_print("ExtraCustomization.__init__ - device_settings=", device_settings)
        self.extra_customization_message = extra_customization_message

        self.l = QVBoxLayout(self)
        self.setLayout(self.l)

        options_group = QGroupBox(_("Extra driver customization options"), self)
        self.l.addWidget(options_group)
        self.extra_layout = QGridLayout()
        self.extra_layout.setObjectName("extra_layout")
        options_group.setLayout(self.extra_layout)

        if extra_customization_message:
            extra_customization_choices = extra_customization_choices or {}

            def parse_msg(m):
                msg, _, tt = m.partition(':::') if m else ('', '', '')
                return msg.strip(), textwrap.fill(tt.strip(), 100)

            if isinstance(extra_customization_message, list):
                self.opt_extra_customization = []
                if len(extra_customization_message) > 6:
                    row_func = lambda x, y: ((x/2) * 2) + y
                    col_func = lambda x: x%2
                else:
                    row_func = lambda x, y: x*2 + y
                    col_func = lambda x: 0

                for i, m in enumerate(extra_customization_message):
                    label_text, tt = parse_msg(m)
                    if not label_text:
                        self.opt_extra_customization.append(None)
                        continue
                    if isinstance(device_settings.extra_customization[i], bool):
                        self.opt_extra_customization.append(QCheckBox(label_text))
                        self.opt_extra_customization[-1].setToolTip(tt)
                        self.opt_extra_customization[i].setChecked(bool(device_settings.extra_customization[i]))
                    elif i in extra_customization_choices:
                        cb = QComboBox(self)
                        self.opt_extra_customization.append(cb)
                        l = QLabel(label_text)
                        l.setToolTip(tt), cb.setToolTip(tt), l.setBuddy(cb), cb.setToolTip(tt)
                        for li in sorted(extra_customization_choices[i]):
                            self.opt_extra_customization[i].addItem(li)
                        cb.setCurrentIndex(max(0, cb.findText(device_settings.extra_customization[i])))
                    else:
                        self.opt_extra_customization.append(QLineEdit(self))
                        l = QLabel(label_text)
                        l.setToolTip(tt)
                        self.opt_extra_customization[i].setToolTip(tt)
                        l.setBuddy(self.opt_extra_customization[i])
                        l.setWordWrap(True)
                        self.opt_extra_customization[i].setText(device_settings.extra_customization[i])
                        self.opt_extra_customization[i].setCursorPosition(0)
                        self.extra_layout.addWidget(l, row_func(i + 2, 0), col_func(i))
                    self.extra_layout.addWidget(self.opt_extra_customization[i],
                                                row_func(i + 2, 1), col_func(i))
                spacerItem1 = QSpacerItem(10, 10, QSizePolicy.Minimum, QSizePolicy.Expanding)
                self.extra_layout.addItem(spacerItem1, row_func(i + 2 + 2, 1), 0, 1, 2)
                self.extra_layout.setRowStretch(row_func(i + 2 + 2, 1), 2)
            else:
                self.opt_extra_customization = QLineEdit()
                label_text, tt = parse_msg(extra_customization_message)
                l = QLabel(label_text)
                l.setToolTip(tt)
                l.setBuddy(self.opt_extra_customization)
                l.setWordWrap(True)
                if device_settings.extra_customization:
                    self.opt_extra_customization.setText(device_settings.extra_customization)
                    self.opt_extra_customization.setCursorPosition(0)
                self.opt_extra_customization.setCursorPosition(0)
                self.extra_layout.addWidget(l, 0, 0)
                self.extra_layout.addWidget(self.opt_extra_customization, 1, 0)

    def extra_customization(self):
        ec = []
        if self.extra_customization_message:
            if isinstance(self.extra_customization_message, list):
                for i in range(0, len(self.extra_customization_message)):
                    if self.opt_extra_customization[i] is None:
                        ec.append(None)
                        continue
                    if hasattr(self.opt_extra_customization[i], 'isChecked'):
                        ec.append(self.opt_extra_customization[i].isChecked())
                    elif hasattr(self.opt_extra_customization[i], 'currentText'):
                        ec.append(unicode_type(self.opt_extra_customization[i].currentText()).strip())
                    else:
                        ec.append(unicode_type(self.opt_extra_customization[i].text()).strip())
            else:
                ec = unicode_type(self.opt_extra_customization.text()).strip()
                if not ec:
                    ec = None

        return ec

    @property
    def has_extra_customizations(self):
        debug_print("ExtraCustomization::has_extra_customizations - self.extra_customization_message", self.extra_customization_message)
        return self.extra_customization_message and len(self.extra_customization_message) > 0
Example #25
0
class Config(QDialog):
    '''
    Configuration dialog for single book conversion. If accepted, has the
    following important attributes

    output_format - Output format (without a leading .)
    input_format  - Input format (without a leading .)
    opf_path - Path to OPF file with user specified metadata
    cover_path - Path to user specified cover (can be None)
    recommendations - A pickled list of 3 tuples in the same format as the
    recommendations member of the Input/Output plugins.
    '''
    def __init__(self,
                 parent,
                 db,
                 book_id,
                 preferred_input_format=None,
                 preferred_output_format=None):
        QDialog.__init__(self, parent)
        self.setupUi()
        self.opt_individual_saved_settings.setVisible(False)
        self.db, self.book_id = db, book_id

        self.setup_input_output_formats(self.db, self.book_id,
                                        preferred_input_format,
                                        preferred_output_format)
        self.setup_pipeline()

        self.input_formats.currentIndexChanged[native_string_type].connect(
            self.setup_pipeline)
        self.output_formats.currentIndexChanged[native_string_type].connect(
            self.setup_pipeline)
        self.groups.setSpacing(5)
        self.groups.activated[(QModelIndex)].connect(self.show_pane)
        self.groups.clicked[(QModelIndex)].connect(self.show_pane)
        self.groups.entered[(QModelIndex)].connect(self.show_group_help)
        rb = self.buttonBox.button(self.buttonBox.RestoreDefaults)
        rb.setText(_('Restore &defaults'))
        rb.clicked.connect(self.restore_defaults)
        self.groups.setMouseTracking(True)
        geom = gprefs.get('convert_single_dialog_geom', None)
        if geom:
            self.restoreGeometry(geom)
        else:
            self.resize(self.sizeHint())

    def setupUi(self):
        self.setObjectName("Dialog")
        self.resize(1024, 700)
        self.setWindowIcon(QIcon(I('convert.png')))
        self.gridLayout = QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.input_label = QLabel(self)
        self.input_label.setObjectName("input_label")
        self.horizontalLayout.addWidget(self.input_label)
        self.input_formats = QComboBox(self)
        self.input_formats.setSizeAdjustPolicy(
            QComboBox.AdjustToMinimumContentsLengthWithIcon)
        self.input_formats.setMinimumContentsLength(5)
        self.input_formats.setObjectName("input_formats")
        self.horizontalLayout.addWidget(self.input_formats)
        self.opt_individual_saved_settings = QCheckBox(self)
        self.opt_individual_saved_settings.setObjectName(
            "opt_individual_saved_settings")
        self.horizontalLayout.addWidget(self.opt_individual_saved_settings)
        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                 QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        self.label_2 = QLabel(self)
        self.label_2.setObjectName("label_2")
        self.horizontalLayout.addWidget(self.label_2)
        self.output_formats = QComboBox(self)
        self.output_formats.setSizeAdjustPolicy(
            QComboBox.AdjustToMinimumContentsLengthWithIcon)
        self.output_formats.setMinimumContentsLength(5)
        self.output_formats.setObjectName("output_formats")
        self.horizontalLayout.addWidget(self.output_formats)
        self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 2)
        self.groups = QListView(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.groups.sizePolicy().hasHeightForWidth())
        self.groups.setSizePolicy(sizePolicy)
        self.groups.setTabKeyNavigation(True)
        self.groups.setIconSize(QSize(48, 48))
        self.groups.setWordWrap(True)
        self.groups.setObjectName("groups")
        self.gridLayout.addWidget(self.groups, 1, 0, 3, 1)
        self.scrollArea = QScrollArea(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(4)
        sizePolicy.setVerticalStretch(10)
        sizePolicy.setHeightForWidth(
            self.scrollArea.sizePolicy().hasHeightForWidth())
        self.scrollArea.setSizePolicy(sizePolicy)
        self.scrollArea.setFrameShape(QFrame.NoFrame)
        self.scrollArea.setLineWidth(0)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName("scrollArea")
        self.scrollAreaWidgetContents = QWidget()
        self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 810, 494))
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.verticalLayout_3 = QVBoxLayout(self.scrollAreaWidgetContents)
        self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout_3.setObjectName("verticalLayout_3")
        self.stack = QStackedWidget(self.scrollAreaWidgetContents)
        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.stack.sizePolicy().hasHeightForWidth())
        self.stack.setSizePolicy(sizePolicy)
        self.stack.setObjectName("stack")
        self.page = QWidget()
        self.page.setObjectName("page")
        self.stack.addWidget(self.page)
        self.page_2 = QWidget()
        self.page_2.setObjectName("page_2")
        self.stack.addWidget(self.page_2)
        self.verticalLayout_3.addWidget(self.stack)
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        self.gridLayout.addWidget(self.scrollArea, 1, 1, 1, 1)
        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok
                                          | QDialogButtonBox.RestoreDefaults)
        self.buttonBox.setObjectName("buttonBox")
        self.gridLayout.addWidget(self.buttonBox, 3, 1, 1, 1)
        self.help = QTextEdit(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.help.sizePolicy().hasHeightForWidth())
        self.help.setSizePolicy(sizePolicy)
        self.help.setMaximumHeight(80)
        self.help.setObjectName("help")
        self.gridLayout.addWidget(self.help, 2, 1, 1, 1)
        self.input_label.setBuddy(self.input_formats)
        self.label_2.setBuddy(self.output_formats)
        self.input_label.setText(_("&Input format:"))
        self.opt_individual_saved_settings.setText(
            _("Use &saved conversion settings for individual books"))
        self.label_2.setText(_("&Output format:"))

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

    def sizeHint(self):
        desktop = QCoreApplication.instance().desktop()
        geom = desktop.availableGeometry(self)
        nh, nw = max(300, geom.height() - 100), max(400, geom.width() - 70)
        return QSize(nw, nh)

    def restore_defaults(self):
        delete_specifics(self.db, self.book_id)
        self.setup_pipeline()

    @property
    def input_format(self):
        return unicode_type(self.input_formats.currentText()).lower()

    @property
    def output_format(self):
        return unicode_type(self.output_formats.currentText()).lower()

    @property
    def manually_fine_tune_toc(self):
        for i in range(self.stack.count()):
            w = self.stack.widget(i)
            if hasattr(w, 'manually_fine_tune_toc'):
                return w.manually_fine_tune_toc.isChecked()

    def setup_pipeline(self, *args):
        oidx = self.groups.currentIndex().row()
        input_format = self.input_format
        output_format = self.output_format
        self.plumber = create_dummy_plumber(input_format, output_format)

        def widget_factory(cls):
            return cls(self.stack, self.plumber.get_option_by_name,
                       self.plumber.get_option_help, self.db, self.book_id)

        self.mw = widget_factory(MetadataWidget)
        self.setWindowTitle(
            _('Convert') + ' ' + unicode_type(self.mw.title.text()))
        lf = widget_factory(LookAndFeelWidget)
        hw = widget_factory(HeuristicsWidget)
        sr = widget_factory(SearchAndReplaceWidget)
        ps = widget_factory(PageSetupWidget)
        sd = widget_factory(StructureDetectionWidget)
        toc = widget_factory(TOCWidget)
        from calibre.gui2.actions.toc_edit import SUPPORTED
        toc.manually_fine_tune_toc.setVisible(
            output_format.upper() in SUPPORTED)
        debug = widget_factory(DebugWidget)

        output_widget = self.plumber.output_plugin.gui_configuration_widget(
            self.stack, self.plumber.get_option_by_name,
            self.plumber.get_option_help, self.db, self.book_id)
        input_widget = self.plumber.input_plugin.gui_configuration_widget(
            self.stack, self.plumber.get_option_by_name,
            self.plumber.get_option_help, self.db, self.book_id)
        while True:
            c = self.stack.currentWidget()
            if not c:
                break
            self.stack.removeWidget(c)

        widgets = [self.mw, lf, hw, ps, sd, toc, sr]
        if input_widget is not None:
            widgets.append(input_widget)
        if output_widget is not None:
            widgets.append(output_widget)
        widgets.append(debug)
        for w in widgets:
            self.stack.addWidget(w)
            w.set_help_signal.connect(self.help.setPlainText)

        self._groups_model = GroupModel(widgets)
        self.groups.setModel(self._groups_model)

        idx = oidx if -1 < oidx < self._groups_model.rowCount() else 0
        self.groups.setCurrentIndex(self._groups_model.index(idx))
        self.stack.setCurrentIndex(idx)
        try:
            shutil.rmtree(self.plumber.archive_input_tdir, ignore_errors=True)
        except:
            pass

    def setup_input_output_formats(self, db, book_id, preferred_input_format,
                                   preferred_output_format):
        if preferred_output_format:
            preferred_output_format = preferred_output_format.upper()
        output_formats = get_output_formats(preferred_output_format)
        input_format, input_formats = get_input_format_for_book(
            db, book_id, preferred_input_format)
        preferred_output_format = preferred_output_format if \
            preferred_output_format in output_formats else \
            sort_formats_by_preference(output_formats,
                    [prefs['output_format']])[0]
        self.input_formats.addItems(
            (unicode_type(x.upper()) for x in input_formats))
        self.output_formats.addItems(
            (unicode_type(x.upper()) for x in output_formats))
        self.input_formats.setCurrentIndex(input_formats.index(input_format))
        self.output_formats.setCurrentIndex(
            output_formats.index(preferred_output_format))

    def show_pane(self, index):
        self.stack.setCurrentIndex(index.row())

    def accept(self):
        recs = GuiRecommendations()
        for w in self._groups_model.widgets:
            if not w.pre_commit_check():
                return
            x = w.commit(save_defaults=False)
            recs.update(x)
        self.opf_file, self.cover_file = self.mw.opf_file, self.mw.cover_file
        self._recommendations = recs
        if self.db is not None:
            recs['gui_preferred_input_format'] = self.input_format
            save_specifics(self.db, self.book_id, recs)
        self.break_cycles()
        QDialog.accept(self)

    def reject(self):
        self.break_cycles()
        QDialog.reject(self)

    def done(self, r):
        if self.isVisible():
            gprefs['convert_single_dialog_geom'] = \
                bytearray(self.saveGeometry())
        return QDialog.done(self, r)

    def break_cycles(self):
        for i in range(self.stack.count()):
            w = self.stack.widget(i)
            w.break_cycles()

    @property
    def recommendations(self):
        recs = [(k, v, OptionRecommendation.HIGH)
                for k, v in self._recommendations.items()]
        return recs

    def show_group_help(self, index):
        widget = self._groups_model.widgets[index.row()]
        self.help.setPlainText(widget.HELP)
class ExtendedGroupBox(DeviceOptionsGroupBox):
    def __init__(self, parent, device):
        super(ExtendedGroupBox, self).__init__(parent, device,
                                               _("Extended driver"))

        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'),
            _('Choose whether to enable extra customizations'),
            device.get_pref('extra_features'))

        self.upload_encumbered_checkbox = create_checkbox(
            _('Upload DRM-encumbered ePub files'),
            _('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'),
            _('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'),
            _('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.replace_lang_checkbox = create_checkbox(
            _('Replace Content Language Code'),
            _('Select this to replace the defined language in each content '
              'file inside the ePub.'), device.get_pref('replace_lang'))

        self.smarten_punctuation_checkbox = create_checkbox(
            _('Smarten Punctuation'),
            _('Select this to smarten punctuation in the ePub'),
            device.get_pref('smarten_punctuation'))

        self.clean_markup_checkbox = create_checkbox(
            _('Clean up ePub Markup'),
            _('Select this to clean up the internal ePub markup.'),
            device.get_pref('clean_markup'))

        self.file_copy_dir_checkbox = create_checkbox(
            _('Copy generated KePub files to a directory'),
            _('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'))
        self.file_copy_dir_edit = QLineEdit(self)
        self.file_copy_dir_edit.setToolTip(
            _('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'),
            _('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'),
            _('Select this to disable hyphenation for books.'),
            device.get_pref('disable_hyphenation'))

        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.replace_lang_checkbox, 2, 0, 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.setRowStretch(6, 2)

    @property
    def extra_features(self):
        return self.extra_features_checkbox.isChecked()

    @property
    def upload_encumbered(self):
        return self.upload_encumbered_checkbox.isChecked()

    @property
    def skip_failed(self):
        return self.skip_failed_checkbox.isChecked()

    @property
    def hyphenate(self):
        return self.hyphenate_checkbox.isChecked()

    @property
    def replace_lang(self):
        return self.replace_lang_checkbox.isChecked()

    @property
    def smarten_punctuation(self):
        return self.smarten_punctuation_checkbox.isChecked()

    @property
    def clean_markup(self):
        return self.clean_markup_checkbox.isChecked()

    @property
    def full_page_numbers(self):
        return self.full_page_numbers_checkbox.isChecked()

    @property
    def disable_hyphenation(self):
        return self.disable_hyphenation_checkbox.isChecked()

    @property
    def file_copy_dir(self):
        return self.file_copy_dir_edit.text().strip()
Example #27
0
class CoversGroupBox(DeviceOptionsGroupBox):
    def __init__(self, parent, device):
        super(CoversGroupBox, self).__init__(parent, device)
        self.setTitle(_("Upload covers"))

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

        self.setCheckable(True)
        self.setChecked(device.get_pref('upload_covers'))
        self.setToolTip(
            wrap_msg(
                _('Upload cover images from the calibre library when sending books to the device.'
                  )))

        self.upload_grayscale_checkbox = create_checkbox(
            _('Upload black and white covers'),
            _('Convert covers to grayscale when uploading.'),
            device.get_pref('upload_grayscale'))

        self.dithered_covers_checkbox = create_checkbox(
            _('Upload dithered covers'),
            _('Dither cover images to the appropriate 16c grayscale palette for an eInk screen.'
              ' This usually ensures greater accuracy and avoids banding, making sleep covers look better.'
              ' On FW >= 4.11, Nickel itself may sometimes do a decent job of it.'
              ' Has no effect without "Upload black and white covers"!'),
            device.get_pref('dithered_covers'))
        # Make it visually depend on B&W being enabled!
        # c.f., https://stackoverflow.com/q/36281103
        self.dithered_covers_checkbox.setEnabled(
            device.get_pref('upload_grayscale'))
        self.upload_grayscale_checkbox.toggled.connect(
            self.dithered_covers_checkbox.setEnabled)
        self.upload_grayscale_checkbox.toggled.connect(
            lambda checked: not checked and self.dithered_covers_checkbox.
            setChecked(False))

        self.keep_cover_aspect_checkbox = create_checkbox(
            _('Keep cover aspect ratio'),
            _('When uploading covers, do not change the aspect ratio when resizing for the device.'
              ' This is for firmware versions 2.3.1 and later.'),
            device.get_pref('keep_cover_aspect'))

        self.letterbox_fs_covers_checkbox = create_checkbox(
            _('Letterbox full-screen covers'),
            _('Do it on our end, instead of letting Nickel handle it.'
              ' Provides pixel-perfect results on devices where Nickel does not do extra processing.'
              ' Obviously has no effect without "Keep cover aspect ratio".'
              ' This is probably undesirable if you disable the "Show book covers full screen"'
              ' setting on your device.'),
            device.get_pref('letterbox_fs_covers'))
        # Make it visually depend on AR being enabled!
        self.letterbox_fs_covers_checkbox.setEnabled(
            device.get_pref('keep_cover_aspect'))
        self.keep_cover_aspect_checkbox.toggled.connect(
            self.letterbox_fs_covers_checkbox.setEnabled)
        self.keep_cover_aspect_checkbox.toggled.connect(
            lambda checked: not checked and self.letterbox_fs_covers_checkbox.
            setChecked(False))

        self.png_covers_checkbox = create_checkbox(
            _('Save covers as PNG'),
            _('Use the PNG image format instead of JPG.'
              ' Higher quality, especially with "Upload dithered covers" enabled,'
              ' which will also help generate potentially smaller files.'
              ' Behavior completely unknown on old (< 3.x) Kobo firmwares,'
              ' known to behave on FW >= 4.8.'
              ' Has no effect without "Upload black and white covers"!'),
            device.get_pref('png_covers'))
        # Make it visually depend on B&W being enabled, to avoid storing ridiculously large color PNGs.
        self.png_covers_checkbox.setEnabled(
            device.get_pref('upload_grayscale'))
        self.upload_grayscale_checkbox.toggled.connect(
            self.png_covers_checkbox.setEnabled)
        self.upload_grayscale_checkbox.toggled.connect(
            lambda checked: not checked and self.png_covers_checkbox.
            setChecked(False))

        self.options_layout.addWidget(self.keep_cover_aspect_checkbox, 0, 0, 1,
                                      1)
        self.options_layout.addWidget(self.letterbox_fs_covers_checkbox, 0, 1,
                                      1, 1)
        self.options_layout.addWidget(self.upload_grayscale_checkbox, 1, 0, 1,
                                      1)
        self.options_layout.addWidget(self.dithered_covers_checkbox, 1, 1, 1,
                                      1)
        self.options_layout.addWidget(self.png_covers_checkbox, 2, 1, 1, 1)

    @property
    def upload_covers(self):
        return self.isChecked()

    @property
    def upload_grayscale(self):
        return self.upload_grayscale_checkbox.isChecked()

    @property
    def dithered_covers(self):
        return self.dithered_covers_checkbox.isChecked()

    @property
    def keep_cover_aspect(self):
        return self.keep_cover_aspect_checkbox.isChecked()

    @property
    def letterbox_fs_covers(self):
        return self.letterbox_fs_covers_checkbox.isChecked()

    @property
    def png_covers(self):
        return self.png_covers_checkbox.isChecked()
Example #28
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()
Example #29
0
class MetadataGroupBox(DeviceOptionsGroupBox):
    def __init__(self, parent, device):
        super(MetadataGroupBox, self).__init__(parent, device)
        self.setTitle(_("Update metadata on the device"))

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

        self.setCheckable(True)
        self.setChecked(device.get_pref('update_device_metadata'))
        self.setToolTip(
            wrap_msg(
                _('Update the metadata on the device when it is connected. '
                  'Be careful when doing this as it will take time and could make the initial connection take a long time.'
                  )))

        self.update_series_checkbox = create_checkbox(
            _("Set series information"),
            _('The book lists on the Kobo devices can display series information. '
              'This is not read by the device from the sideloaded books. '
              'Series information can only be added to the device after the book has been processed by the device. '
              'Enable if you wish to set series information.'),
            device.get_pref('update_series'))
        self.update_core_metadata_checkbox = create_checkbox(
            _("Update metadata on Book Details pages"),
            _('This will update the metadata in the device database when the device is connected. '
              'The metadata updated is displayed on the device in the library and the book details page. '
              'This is the title, authors, comments/synopsis, series name and number, publisher and published Date, ISBN and language. '
              'If a metadata plugboard exists for the device and book format, this will be used to set the metadata.'
              ), device.get_pref('update_core_metadata'))

        self.update_purchased_kepubs_checkbox = create_checkbox(
            _("Update purchased books"),
            _('Update books purchased from Kobo and downloaded to the device.'
              ), device.get_pref('update_purchased_kepubs'))
        self.update_subtitle_checkbox = create_checkbox(
            _("Subtitle"),
            _('Update the subtitle on the device using a template.'),
            device.get_pref('update_subtitle'))
        self.subtitle_template_edit = TemplateConfig(
            device.get_pref('subtitle_template'),
            tooltip=_(
                "Enter a template to use to set the subtitle. "
                "If the template is empty, the subtitle will be cleared."))

        self.options_layout.addWidget(self.update_series_checkbox, 0, 0, 1, 2)
        self.options_layout.addWidget(self.update_core_metadata_checkbox, 1, 0,
                                      1, 2)
        self.options_layout.addWidget(self.update_subtitle_checkbox, 2, 0, 1,
                                      1)
        self.options_layout.addWidget(self.subtitle_template_edit, 2, 1, 1, 1)
        self.options_layout.addWidget(self.update_purchased_kepubs_checkbox, 3,
                                      0, 1, 2)

        self.update_core_metadata_checkbox.clicked.connect(
            self.update_core_metadata_checkbox_clicked)
        self.update_subtitle_checkbox.clicked.connect(
            self.update_subtitle_checkbox_clicked)
        self.update_core_metadata_checkbox_clicked(
            device.get_pref('update_core_metadata'))
        self.update_subtitle_checkbox_clicked(
            device.get_pref('update_subtitle'))

    def update_core_metadata_checkbox_clicked(self, checked):
        self.update_series_checkbox.setEnabled(not checked)
        self.subtitle_template_edit.setEnabled(checked)
        self.update_subtitle_checkbox.setEnabled(checked)
        self.update_subtitle_checkbox_clicked(self.update_subtitle)
        self.update_purchased_kepubs_checkbox.setEnabled(checked)

    def update_subtitle_checkbox_clicked(self, checked):
        self.subtitle_template_edit.setEnabled(checked
                                               and self.update_core_metadata)

    def edit_template(self):
        t = TemplateDialog(self, self.template)
        t.setWindowTitle(_('Edit template'))
        if t.exec_():
            self.t.setText(t.rule[1])

    def validate(self):
        if self.update_subtitle and not self.subtitle_template_edit.validate():
            return False
        return True

    @property
    def update_series(self):
        return self.update_series_checkbox.isChecked()

    @property
    def update_core_metadata(self):
        return self.update_core_metadata_checkbox.isChecked()

    @property
    def update_purchased_kepubs(self):
        return self.update_purchased_kepubs_checkbox.isChecked()

    @property
    def update_device_metadata(self):
        return self.isChecked()

    @property
    def subtitle_template(self):
        return self.subtitle_template_edit.template

    @property
    def update_subtitle(self):
        return self.update_subtitle_checkbox.isChecked()
Example #30
0
class Ui(QApplication):
    def __init__(self):
        super().__init__(argv)
        self.w = QMainWindow()
        self.w.setMinimumWidth(300)
        self.w.setMinimumHeight(300)
        # self.w.setWindowTitle(tr("Отправка запросов на ВС АУГО"))
        self.cw = QScrollArea()
        # self.__create_ui()
        self.__showed = False
        self.__wgts = {}
        self.cb = QComboBox()
        self.individuals = []
        self.entities = []
        self.documents = []
        self.doc_files = []
        self.__setupUi(self.w)
        self.w.showMaximized()

    def report_error(self, msg=None):
        if not msg:
            etype, value, tb = exc_info()
            trace = ''.join(format_exception(etype, value, tb))
            delim_len = 40
            msg = ("*" * delim_len + "\n%s\n" + "*" * delim_len) % trace
            error(msg)
        mb = QMessageBox(QMessageBox.Critical, tr('Ошибка'),
                         str(exc_info()[1]))
        mb.setDetailedText(msg)
        mb.exec()

    def __create_ui(self):
        self.l = QGridLayout()
        self.t = QTableWidget(0, 3)
        self.t.setHorizontalHeaderLabels(
            ('№ дела (обращения)', 'Дата приёма', 'Дата отправки в СМЭВ'))
        self.t.resizeColumnsToContents()
        self.l.addWidget(self.t, 0, 0, 1, 2)
        w = QWidget()
        hl = QHBoxLayout(w)
        hl.setDirection(QHBoxLayout.LeftToRight)
        hl.addWidget(QWidget())
        ok_b = QPushButton(tr('Добавить запрос'))
        ok_b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)
        ok_b.clicked.connect(self.__show_form)
        hl.addWidget(ok_b)
        w.setLayout(hl)
        self.l.addWidget(w, 1, 0, 1, 2)
        w = QWidget()
        w.setLayout(self.l)
        self.cw.setWidget(w)
        # self.cw.setLayout(self.l)
        # self.w.setCentralWidget(self.cw)
        w = QWidget()
        l = QVBoxLayout()
        l.addWidget(self.cw)
        w.setLayout(l)
        self.w.setCentralWidget(w)

    def __setupUi(self, mainWindow):
        mainWindow.setObjectName("MainWindow")
        self.centralwidget = QWidget(mainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout = QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.scrollArea = QScrollArea(self.centralwidget)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName("scrollArea")
        self.scrollAreaWidgetContents = QWidget()
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.gridLayout = QGridLayout(self.scrollAreaWidgetContents)
        self.gridLayout.setObjectName("gridLayout")
        self.__show_form()
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        self.horizontalLayout.addWidget(self.scrollArea)
        mainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(mainWindow)
        self.menubar.setObjectName("menubar")
        self.menu = QMenu(self.menubar)
        self.menu.setObjectName("menu")
        mainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(mainWindow)
        self.statusbar.setObjectName("statusbar")
        mainWindow.setStatusBar(self.statusbar)
        self.action_1 = QAction(mainWindow)
        self.action_1.setObjectName("action")
        self.action_1.triggered.connect(self.send)
        self.action = QAction(mainWindow)
        self.action.setObjectName("action")
        self.action.triggered.connect(self.on_action_triggered)
        self.action_2 = QAction(mainWindow)
        self.action_2.setObjectName("action_2")
        self.action_3 = QAction(mainWindow)
        self.action_3.setObjectName("action_3")
        self.action_3.triggered.connect(self.get_response)
        self.menu.addAction(self.action)
        self.menubar.addAction(self.action_1)
        self.menubar.addAction(self.action_2)
        self.menubar.addAction(self.action_3)
        self.menubar.addAction(self.menu.menuAction())

        self.__retranslateUi(mainWindow)
        QMetaObject.connectSlotsByName(mainWindow)

    @pyqtSlot(bool)
    def get_response(self):
        try:
            from dmsic import Integration
            i = Integration(self)
            res = i.get_response()[0]
            if res:
                QMessageBox.information(self.w, tr("Получен ответ"), str(res))
        except:
            self.report_error()

    @pyqtSlot(bool)
    def send(self):
        try:
            from dmsic import Integration
            i = Integration(self)
            declar = {}
            for k, v in self.__wgts.items():
                if k in ('object_address', 'AppliedDocument', 'legal_entity',
                         'person'):
                    a = {}
                    for key, val in v.items():
                        if val.metaObject().className() == 'QDateEdit':
                            a[key] = datetime.strptime(val.text(), '%d.%m.%Y')
                        else:
                            a[key] = val.text()
                    declar[k] = a
                else:
                    if v.metaObject().className() == 'QDateEdit':
                        declar[k] = datetime.strptime(v.text(), '%d.%m.%Y')
                    else:
                        declar[k] = v.text()
            a = declar[
                'AppliedDocument'] if 'AppliedDocument' in declar else []
            for v in self.documents:
                d = {}
                for key, val in v.items():
                    if val.metaObject().className() == 'QDateEdit':
                        d[key] = datetime.strptime(val.text(), '%d.%m.%Y')
                    else:
                        d[key] = val.text()
                if not self.doc_files:
                    raise Exception('Добавте файл документа')
                d['file_name'] = self.doc_files[self.documents.index(v)]
                a.append(d)
            declar['AppliedDocument'] = a
            a = declar['person'] if 'person' in declar else []
            for v in self.individuals:
                ind = {}
                for key, val in v.items():
                    if key in ('address', 'fact_address'):
                        adr = {}
                        for k, vl in val.items():
                            adr[k] = vl.text()
                        ind[key] = adr
                    else:
                        if val.metaObject().className() == 'QDateEdit':
                            ind[key] = datetime.strptime(
                                val.text(), '%d.%m.%Y')
                        else:
                            ind[key] = val.text()
                a.append(ind)
            declar['person'] = a
            a = declar['legal_entity'] if 'legal_entity' in declar else []
            for v in self.entities:
                ent = {}
                for key, val in v.items():
                    if key == 'address':
                        adr = {}
                        for k, vl in val.items():
                            adr[k] = vl.text()
                        ent[key] = adr
                    else:
                        if val.metaObject().className() == 'QDateEdit':
                            ent[key] = datetime.strptime(
                                val.text(), '%d.%m.%Y')
                        else:
                            ent[key] = val.text()
                a.append(ent)
            declar['legal_entity'] = a
            i.send(declar)
            mb = QMessageBox(self.w)
            mb.information(self.w, tr('Готово'), tr('Запрос отправлен'))
        except:
            self.report_error()

    @pyqtSlot(bool)
    def on_action_triggered(self):
        a = Ui_Dialog()
        d = QDialog()
        a.setupUi(d)
        d.exec()

    def __retranslateUi(self, MainWindow):
        _translate = QCoreApplication.translate
        MainWindow.setWindowTitle(
            _translate("MainWindow", "Отправка запросов на ВС АУГО"))
        # self.pushButton.setText(_translate("MainWindow", "Добавить"))
        self.menu.setTitle(_translate("MainWindow", "Справка"))
        self.action_1.setText(_translate("MainWindow", "Отправить"))
        self.action_2.setText(_translate("MainWindow", "Настройка"))
        self.action.setText(_translate("MainWindow", "О программе"))
        self.action_3.setText(_translate("MainWindow", "Получить ответ"))

    @pyqtSlot(bool)
    def __show_form(self):
        if self.__showed:
            return

        self.gridLayout.addWidget(
            QLabel(tr('№ дела (обращения) <em style="color: red">*</em>')))
        w = QLineEdit()
        self.gridLayout.addWidget(w)
        w.setFocus()
        self.__wgts['declar_number'] = w
        self.gridLayout.addWidget(
            QLabel(
                tr('Услуга (код или номер, или наименование)<em style="color: red">*</em>'
                   )))
        w = QLineEdit()
        self.gridLayout.addWidget(w)
        self.__wgts['service'] = w
        self.gridLayout.addWidget(
            QLabel(
                tr('Дата регистрации запроса <em style="color: red">*</em>')))
        de = QDateEdit(QDate().currentDate())
        de.setCalendarPopup(True)
        self.gridLayout.addWidget(de)
        self.__wgts['register_date'] = de
        self.gridLayout.addWidget(
            QLabel(
                tr('Плановый срок предоставления услуги <em style="color: red">*</em>'
                   )))
        de = QDateEdit()
        self.__wgts['register_date'].dateChanged.connect(de.setMinimumDate)
        de.setCalendarPopup(True)
        de.setMinimumDate(self.__wgts['register_date'].date())
        self.gridLayout.addWidget(de)
        self.__wgts['end_date'] = de

        gb = QGroupBox(tr('Место нахождения объекта услуги'))
        gb_l = QGridLayout()
        self.__wgts['object_address'] = self.__add_address(gb_l)
        gb.setLayout(gb_l)
        self.gridLayout.addWidget(gb, self.gridLayout.rowCount() + 1, 0, 1, 2)

        doc = {}
        gb = QGroupBox(tr('Приложенный документ *'))
        gb_l = QGridLayout()
        gb_l.addWidget(
            QLabel(tr('Наименование документа <em style="color: red">*</em>')))
        w = QLineEdit()
        w.setMaxLength(1024)
        gb_l.addWidget(w, 0, 1, 1, 1)
        doc['title'] = w
        gb_l.addWidget(
            QLabel(tr('Номер документа <em style="color: red">*</em>')))
        w = QLineEdit()
        w.setMaxLength(50)
        gb_l.addWidget(w)
        doc['number'] = w
        gb_l.addWidget(
            QLabel(tr('Дата документа <em style="color: red">*</em>')))
        w = QDateEdit()
        w.setCalendarPopup(True)
        gb_l.addWidget(w)
        doc['date'] = w
        gb_l.addWidget(
            QLabel(
                tr('Прямая ссылка на файл. Поддерживаются только пртоколы '
                   'HTTP, FTP <em style="color: red">*</em>')))
        w = QLineEdit()
        gb_l.addWidget(w)
        doc['url'] = w
        gb.setLayout(gb_l)
        self.gridLayout.addWidget(gb, self.gridLayout.rowCount() + 1, 0, 1, 2)
        self.documents.append(doc)

        gb = QGroupBox(tr('Заявители *'))
        self.dec_layout = QGridLayout()
        self.cb = QComboBox()
        self.cb.addItems(('Физическое лицо',
                          'Юридическое лицо/Индивидуальный предприниматель'))
        self.dec_layout.addWidget(self.cb)
        b = QPushButton(tr('Добавить'))
        b.clicked.connect(self.add_declarant)
        self.dec_layout.addWidget(b, 0, 1, 1, 1)
        gb.setLayout(self.dec_layout)
        self.gridLayout.addWidget(gb, self.gridLayout.rowCount() + 1, 0, 1, 2)

        b = QPushButton(tr('Добавить файл документа'))
        b.clicked.connect(self.__add_doc_file)
        self.gridLayout.addWidget(b)
        self.file_label = QLabel()
        self.gridLayout.addWidget(self.file_label)
        self.warn_label = QLabel(tr("Не удаляйте файл до отправки запроса"))
        self.warn_label.setStyleSheet('color: red')
        self.warn_label.setVisible(False)
        self.gridLayout.addWidget(self.warn_label,
                                  self.gridLayout.rowCount() + 1, 0, 1, 2)

        self.__showed = True

    @pyqtSlot(bool)
    def __add_doc_file(self):
        file_name = QFileDialog.getOpenFileName(
            caption=tr('Выбурите файл'),
            filter=tr('Файлы pdf (*.pdf);;Все файлы (*.*)'))[0]
        self.file_label.setText(file_name)
        if self.doc_files:
            self.doc_files = []
        self.doc_files.append(file_name)
        self.warn_label.setVisible(True)

    def __add_address(self, gb_l):
        wgts = {}
        gb_l.addWidget(QLabel(tr('Почтовый индекс')))
        w = QLineEdit()
        gb_l.addWidget(w, 0, 1, 1, 1)
        wgts['Postal_Code'] = w
        gb_l.addWidget(QLabel(tr('Регион')))
        w = QLineEdit()
        gb_l.addWidget(w)
        wgts['Region'] = w
        gb_l.addWidget(QLabel(tr('Район')))
        w = QLineEdit()
        gb_l.addWidget(w)
        wgts['District'] = w
        gb_l.addWidget(QLabel(tr('Муниципальное образование')))
        w = QLineEdit()
        gb_l.addWidget(w)
        wgts['City'] = w
        gb_l.addWidget(QLabel(tr('Городской район')))
        w = QLineEdit()
        gb_l.addWidget(w)
        wgts['Urban_District'] = w
        gb_l.addWidget(QLabel(tr('Сельсовет')))
        w = QLineEdit()
        gb_l.addWidget(w)
        wgts['Soviet_Village'] = w
        gb_l.addWidget(
            QLabel(tr('Населенный пункт <em style="color: red">*</em>')))
        w = QLineEdit()
        gb_l.addWidget(w)
        wgts['Locality'] = w
        cb = QComboBox()
        cb.addItems(('Вариант 1', 'Вариант 2'))
        gb_l.addWidget(cb)
        st = QStackedWidget()
        p1 = QWidget()
        l = QGridLayout()
        l.setSpacing(3)
        l.addWidget(QLabel(tr('Улица <em style="color: red">*</em>')))
        w = QLineEdit()
        l.addWidget(w, 0, 1, 1, 1)
        wgts["Street"] = w
        l.addWidget(QLabel(tr('Дом <em style="color: red">*</em>')))
        w = QLineEdit()
        l.addWidget(w)
        wgts["House"] = w
        p1.setLayout(l)
        st.addWidget(p1)
        p2 = QWidget()
        l = QGridLayout()
        l.setSpacing(3)
        l.addWidget(QLabel(tr('Ориентир')))
        w = QLineEdit()
        l.addWidget(w, 0, 1, 1, 1)
        wgts["Reference_point"] = w
        p2.setLayout(l)
        st.addWidget(p2)
        gb_l.addWidget(st, 9, 0, 1, 2)
        cb.activated.connect(st.setCurrentIndex)
        gb_l.addWidget(QLabel(tr('Корпус')))
        w = QLineEdit()
        gb_l.addWidget(w)
        wgts['Housing'] = w
        gb_l.addWidget(QLabel(tr('Строение')))
        w = QLineEdit()
        gb_l.addWidget(w)
        wgts['Building'] = w
        gb_l.addWidget(QLabel(tr('Квартира')))
        w = QLineEdit()
        gb_l.addWidget(w)
        wgts['Apartment'] = w
        return wgts

    @pyqtSlot(bool)
    def add_declarant(self, var=True, gl=None):
        if not gl:
            gl = self.dec_layout
        dc = {}
        gb_l = QGridLayout()
        if self.cb.currentIndex() == 0 or gl != self.dec_layout:
            # Add Individual
            gb = QGroupBox(tr('Физическое лицо *'))
            gb_l.addWidget(QLabel(tr('Фамилия <em style="color: red">*</em>')))
            w = QLineEdit()
            gb_l.addWidget(w, 0, 1, 1, 1)
            dc['surname'] = w
            gb_l.addWidget(QLabel(tr('Имя <em style="color: red">*</em>')))
            w = QLineEdit()
            gb_l.addWidget(w)
            dc['first_name'] = w
            gb_l.addWidget(QLabel(tr('Отчество')))
            w = QLineEdit()
            gb_l.addWidget(w)
            dc['patronymic'] = w

            adr = QGroupBox(tr('Адрес регистрации *'))
            adr_l = QGridLayout()
            dc['address'] = self.__add_address(adr_l)
            adr.setLayout(adr_l)
            gb_l.addWidget(adr, gb_l.rowCount() + 1, 0, 1, 2)

            gb.setLayout(gb_l)
            gl.addWidget(gb, gl.rowCount() + 1, 0, 1, 2)
            self.individuals.append(dc)
        else:
            # Add LegalEntity
            gb = QGroupBox(
                tr('Юридическое лицо/Индивидуальный предприниматель *'))
            gb_l.addWidget(
                QLabel(
                    tr('Краткое наименование ЮЛ <em style="color: red">*</em>')
                ))
            w = QLineEdit()
            gb_l.addWidget(w, 0, 1, 1, 1)
            dc['name'] = w

            adr = QGroupBox(tr('Юридический адрес *'))
            adr_l = QGridLayout()
            dc['address'] = self.__add_address(adr_l)
            adr.setLayout(adr_l)
            gb_l.addWidget(adr, gb_l.rowCount() + 1, 0, 1, 2)

            gb.setLayout(gb_l)
            gl.addWidget(gb, gl.rowCount() + 1, 0, 1, 2)
            self.entities.append(dc)