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()
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()
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()
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()
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()
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()
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()
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()
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)
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"))
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()
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"))
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()
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)
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()
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()
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
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()
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()
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()
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
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()
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()
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()
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()
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)