def save_settings(cls, config_widget): """Ensure settings are properly saved between old and new config styles.""" try: config_widget = config_widget.widget() log.warning( "KoboTouchExtended:save_settings: Have old style config.") except Exception: log.info("KoboTouchExtended:save_settings: Have new style config.") super(KOBOTOUCHEXTENDED, cls).save_settings(config_widget)
def sync_booklists(self, booklists, end_session=True): """Synchronize book lists between calibre and the Kobo device.""" if self.upload_covers: log.info("KoboTouchExtended:sync_booklists:Setting ImageId fields") select_query = ("SELECT ContentId FROM content WHERE " + "ContentType = ? AND " + "(ImageId IS NULL OR ImageId = '')") update_query = "UPDATE content SET ImageId = ? WHERE ContentId = ?" try: db = self.device_database_connection() except AttributeError: import apsw db = apsw.Connection(self.device_database_path()) def __rows_needing_imageid(): """Map row ContentID entries needing an ImageID. Returns a dict object with keys being the ContentID of a row without an ImageID. """ c = db.cursor() d = {} log.debug( "KoboTouchExtended:sync_booklists:About to call query: " "{0}".format(select_query)) c.execute(select_query, (self.content_types["main"], )) for row in c: d[row[0]] = 1 return d all_nulls = __rows_needing_imageid() log.debug("KoboTouchExtended:sync_booklists:Got {0:d} rows to " "update".format(len(list(all_nulls.keys())))) nulls = [] for booklist in booklists: for b in booklist: if b.application_id is not None and b.contentID in all_nulls: nulls.append((self.imageid_from_contentid(b.contentID), b.contentID)) del all_nulls cursor = db.cursor() while nulls[:100]: log.debug("KoboTouchExtended:sync_booklists:Updating {0:d} " "ImageIDs...".format(len(nulls[:100]))) cursor.executemany(update_query, nulls[:100]) del nulls[:100] cursor.close() db.close() log.debug( "KoboTouchExtended:sync_booklists:done setting ImageId fields") super(KOBOTOUCHEXTENDED, self).sync_booklists(booklists, end_session)
def config_widget(cls): """Create and populate the driver settings config widget.""" from calibre.gui2.device_drivers.configwidget import ConfigWidget cw = super(KOBOTOUCHEXTENDED, cls).config_widget() if isinstance(cw, ConfigWidget): log.warning( "KoboTouchExtended:config_widget: Have old style config.") try: from PyQt5.QtCore import QCoreApplication from PyQt5.QtWidgets import QScrollArea except ImportError: from PyQt4.Qt import QCoreApplication from PyQt4.Qt import QScrollArea qsa = QScrollArea() qsa.setWidgetResizable(True) qsa.setWidget(cw) qsa.validate = cw.validate desktop_geom = QCoreApplication.instance().desktop( ).availableGeometry() if desktop_geom.height() < 800: qsa.setBaseSize(qsa.size().width(), desktop_geom.height() - 100) cw = qsa else: log.info("KoboTouchExtended:config_widget: Have new style config.") cls.current_friendly_name = cls.gui_name from calibre_plugins.kobotouch_extended.device.koboextended_config import ( KOBOTOUCHEXTENDEDConfig, ) cw = KOBOTOUCHEXTENDEDConfig( cls.settings(), cls.FORMATS, cls.SUPPORTS_SUB_DIRS, cls.MUST_READ_METADATA, cls.SUPPORTS_USE_AUTHOR_SORT, cls.EXTRA_CUSTOMIZATION_MESSAGE, cls, extra_customization_choices=cls.EXTRA_CUSTOMIZATION_CHOICES, ) return cw
def migrate_old_settings(cls, settings): """Migrate old settings to the new format.""" log.debug("KoboTouchExtended::migrate_old_settings - start") settings = super(KOBOTOUCHEXTENDED, cls).migrate_old_settings(settings) log.debug( "KoboTouchExtended::migrate_old_settings - end", settings.extra_customization, ) count_options = 0 opt_extra_features = count_options count_options += 1 opt_upload_encumbered = count_options count_options += 1 opt_skip_failed = count_options count_options += 1 opt_hypnenate = count_options count_options += 1 opt_smarten_punctuation = count_options count_options += 1 opt_clean_markup = count_options count_options += 1 opt_full_page_numbers = count_options count_options += 1 opt_file_copy_dir = count_options count_options += 1 opt_disable_hyphenation = count_options if len(settings.extra_customization) >= count_options: log.warning( "KoboTouchExtended::migrate_old_settings - settings need to " "be migrated") try: settings.extra_features = settings.extra_customization[ opt_extra_features] except IndexError: pass try: settings.upload_encumbered = settings.extra_customization[ opt_upload_encumbered] except IndexError: pass try: settings.skip_failed = settings.extra_customization[ opt_skip_failed] except IndexError: pass try: settings.hyphenate = settings.extra_customization[ opt_hypnenate] except IndexError: pass try: settings.smarten_punctuation = settings.extra_customization[ opt_smarten_punctuation] except IndexError: pass try: settings.clean_markup = settings.extra_customization[ opt_clean_markup] except IndexError: pass try: settings.file_copy_dir = settings.extra_customization[ opt_file_copy_dir] if not isinstance(settings.file_copy_dir, str): settings.file_copy_dir = None except IndexError: pass try: settings.full_page_numbers = settings.extra_customization[ opt_full_page_numbers] except IndexError: pass try: settings.disable_hyphenation = settings.extra_customization[ opt_disable_hyphenation] except IndexError: pass settings.extra_customization = settings.extra_customization[ count_options + 1:] log.info( "KoboTouchExtended::migrate_old_settings - end", settings.extra_customization, ) return settings
def upload_books(self, files, names, on_card=None, end_session=True, metadata=None): """Process sending the book to the Kobo device.""" if self.modifying_css(): log.info( "KoboTouchExtended:upload_books:Searching for device-specific " "CSS file") device_css_file_name = self.KOBO_EXTRA_CSSFILE try: if self.isAuraH2O(): device_css_file_name = "kobo_extra_AURAH2O.css" elif self.isAuraHD(): device_css_file_name = "kobo_extra_AURAHD.css" elif self.isAura(): device_css_file_name = "kobo_extra_AURA.css" elif self.isGlo(): device_css_file_name = "kobo_extra_GLO.css" elif self.isGloHD(): device_css_file_name = "kobo_extra_GLOHD.css" elif self.isMini(): device_css_file_name = "kobo_extra_MINI.css" elif self.isTouch(): device_css_file_name = "kobo_extra_TOUCH.css" except AttributeError: log.warning( "KoboTouchExtended:upload_books:Calibre version too old " "to handle some specific devices, falling back to " "generic file {0}".format(device_css_file_name)) device_css_file_name = os.path.join(self.configdir, device_css_file_name) if os.path.isfile(device_css_file_name): log.info( "KoboTouchExtended:upload_books:Found device-specific " "file {0}".format(device_css_file_name)) shutil.copy( device_css_file_name, os.path.join(self._main_prefix, self.KOBO_EXTRA_CSSFILE), ) else: log.info( "KoboTouchExtended:upload_books:No device-specific CSS " "file found (expecting {0})".format(device_css_file_name)) kobo_config_file = os.path.join(self._main_prefix, ".kobo", "Kobo", "Kobo eReader.conf") if os.path.isfile(kobo_config_file): cfg = SafeConfigParser(allow_no_value=True) cfg.optionxform = str cfg.read(kobo_config_file) if not cfg.has_section("FeatureSettings"): cfg.add_section("FeatureSettings") log.info("KoboTouchExtended:upload_books:Setting FeatureSettings." "FullBookPageNumbers to {0}".format( "true" if self.full_page_numbers else "false")) cfg.set( "FeatureSettings", "FullBookPageNumbers", "true" if self.full_page_numbers else "false", ) with open(kobo_config_file, "w") as cfgfile: cfg.write(cfgfile) return super(KOBOTOUCHEXTENDED, self).upload_books(files, names, on_card, end_session, metadata)
def _modify_epub(self, infile, metadata, container=None): if not infile.endswith(EPUB_EXT): if not infile.endswith(KEPUB_EXT): self.skip_renaming_files.add(metadata.uuid) else: log.info("KoboTouchExtended:_modify_epub:Skipping all " "processing for calibre-converted KePub file " "{0}".format(infile)) return super(KOBOTOUCHEXTENDED, self)._modify_epub(infile, metadata, container) log.info( "KoboTouchExtended:_modify_epub:Adding basic Kobo features to " "{0} by {1}".format(metadata.title, " and ".join(metadata.authors))) opts = self.settings() skip_failed = self.skip_failed if skip_failed: log.info( "KoboTouchExtended:_modify_epub:Failed conversions will be skipped" ) else: log.info( "KoboTouchExtended:_modify_epub:Failed conversions will raise " "exceptions") is_encumbered_book = False try: if container is None: container = KEPubContainer(infile, log) else: is_encumbered_book = container.is_drm_encumbered except DRMError: log.warning("KoboTouchExtended:_modify_epub:ERROR: ePub is " "DRM-encumbered, not modifying") is_encumbered_book = True if is_encumbered_book: self.skip_renaming_files.add(metadata.uuid) if self.upload_encumbered: return super(KOBOTOUCHEXTENDED, self)._modify_epub(infile, metadata, container) else: return False try: # Add the conversion info file calibre_details_file = self.normalize_path( os.path.join(self._main_prefix, "driveinfo.calibre")) log.debug("KoboTouchExtended:_modify_epub:Calibre details file :: " "{0}".format(calibre_details_file)) o = {} if os.path.isfile(calibre_details_file): with open(calibre_details_file, "rb") as f: o = json.loads(f.read()) for prop in ( "device_store_uuid", "prefix", "last_library_uuid", "location_code", ): del o[prop] else: log.warning( "KoboTouchExtended:_modify_file:Calibre details file does " "not exist!") o["kobotouchextended_version"] = ".".join( [str(n) for n in self.version]) o["kobotouchextended_options"] = str(opts.extra_customization) o["kobotouchextended_currenttime"] = datetime.utcnow().ctime() kte_data_file = self.temporary_file("_KoboTouchExtendedDriverInfo") log.debug("KoboTouchExtended:_modify_epub:Driver data file :: {0}". format(kte_data_file.name)) kte_data_file.write(json.dumps(o).encode("UTF-8")) kte_data_file.close() container.copy_file_to_container(kte_data_file.name, name="driverinfo.kte", mt="application/json") modify_epub( container, infile, metadata=metadata, opts={ "clean_markup": self.clean_markup, "hyphenate": self.hyphenate and not self.disable_hyphenation, "no-hyphens": self.disable_hyphenation, "smarten_punctuation": self.smarten_punctuation, "extended_kepub_features": self.extra_features, }, ) except Exception as e: log.exception("Failed to process {0} by {1}: {2}".format( metadata.title, " and ".join(metadata.authors), e.message, )) if not skip_failed: raise self.skip_renaming_files.add(metadata.uuid) return super(KOBOTOUCHEXTENDED, self)._modify_epub(infile, metadata, container) if not self.extra_features: self.skip_renaming_files.add(metadata.uuid) dpath = self.file_copy_dir or "" if dpath != "": dpath = os.path.expanduser(dpath).strip() dpath = self.create_upload_path(dpath, metadata, metadata.kte_calibre_name) log.info( "KoboTouchExtended:_modify_epub:Generated KePub file copy " "path: {0}".format(dpath)) shutil.copy(infile, dpath) retval = super(KOBOTOUCHEXTENDED, self)._modify_epub(infile, metadata, container) if retval: container.commit(outpath=infile) return retval