diff --git a/src/calibre/devices/prs505/driver.py b/src/calibre/devices/prs505/driver.py index e9329c39c6..0f6668891a 100644 --- a/src/calibre/devices/prs505/driver.py +++ b/src/calibre/devices/prs505/driver.py @@ -98,6 +98,9 @@ class PRS505(USBMS): THUMBNAIL_HEIGHT = 200 + MAX_PATH_LEN = 201 # 250 - (max(len(CACHE_THUMBNAIL), len(MEDIA_THUMBNAIL)) + + # len('main_thumbnail.jpg') + 1) + def windows_filter_pnp_id(self, pnp_id): return '_LAUNCHER' in pnp_id @@ -201,10 +204,13 @@ class PRS505(USBMS): self._card_b_prefix if idx == 2 \ else self._main_prefix for book in bl: - p = os.path.join(prefix, book.lpath) - self._upload_cover(os.path.dirname(p), - os.path.splitext(os.path.basename(p))[0], - book, p) + try: + p = os.path.join(prefix, book.lpath) + self._upload_cover(os.path.dirname(p), + os.path.splitext(os.path.basename(p))[0], + book, p) + except: + debug_print('FAILED to upload cover', p) else: debug_print('PRS505: NOT uploading covers in sync_booklists') @@ -232,8 +238,7 @@ class PRS505(USBMS): try: self._upload_cover(path, filename, metadata, filepath) except: - import traceback - traceback.print_exc() + debug_print('FAILED to upload cover', filepath) def _upload_cover(self, path, filename, metadata, filepath): if metadata.thumbnail and metadata.thumbnail[-1]: diff --git a/src/calibre/devices/usbms/device.py b/src/calibre/devices/usbms/device.py index 4711a8eec4..a31897c8e5 100644 --- a/src/calibre/devices/usbms/device.py +++ b/src/calibre/devices/usbms/device.py @@ -98,6 +98,9 @@ class Device(DeviceConfig, DevicePlugin): # copy these back to the library BACKLOADING_ERROR_MESSAGE = None + #: The maximum length of paths created on the device + MAX_PATH_LEN = 250 + def reset(self, key='-1', log_packets=False, report_progress=None, detected_device=None): self._main_prefix = self._card_a_prefix = self._card_b_prefix = None @@ -875,7 +878,7 @@ class Device(DeviceConfig, DevicePlugin): def create_upload_path(self, path, mdata, fname, create_dirs=True): path = os.path.abspath(path) - extra_components = [] + maxlen = self.MAX_PATH_LEN special_tag = None if mdata.tags: @@ -902,7 +905,7 @@ class Device(DeviceConfig, DevicePlugin): app_id = str(getattr(mdata, 'application_id', '')) # The db id will be in the created filename extra_components = get_components(template, mdata, fname, - timefmt=opts.send_timefmt, length=250-len(app_id)-1) + timefmt=opts.send_timefmt, length=maxlen-len(app_id)-1) if not extra_components: extra_components.append(sanitize(self.filename_callback(fname, mdata))) @@ -937,12 +940,11 @@ class Device(DeviceConfig, DevicePlugin): return ans extra_components = list(map(remove_trailing_periods, extra_components)) - components = shorten_components_to(250 - len(path), extra_components) + components = shorten_components_to(maxlen - len(path), extra_components) components = self.sanitize_path_components(components) filepath = os.path.join(path, *components) filedir = os.path.dirname(filepath) - if create_dirs and not os.path.exists(filedir): os.makedirs(filedir) diff --git a/src/calibre/gui2/custom_column_widgets.py b/src/calibre/gui2/custom_column_widgets.py index d80909c4bb..58985d1121 100644 --- a/src/calibre/gui2/custom_column_widgets.py +++ b/src/calibre/gui2/custom_column_widgets.py @@ -599,7 +599,7 @@ class BulkEnumeration(BulkBase, Enumeration): value = None ret_value = None dialog_shown = False - for book_id in book_ids: + for i,book_id in enumerate(book_ids): val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True) if val and val not in self.col_metadata['display']['enum_values']: if not dialog_shown: @@ -610,7 +610,7 @@ class BulkEnumeration(BulkBase, Enumeration): show=True, show_copy_button=False) dialog_shown = True ret_value = ' nochange ' - elif value is not None and value != val: + elif (value is not None and value != val) or (val and i != 0): ret_value = ' nochange ' value = val if ret_value is None: diff --git a/src/calibre/utils/filenames.py b/src/calibre/utils/filenames.py index 47ccbe73c2..b79e72684b 100644 --- a/src/calibre/utils/filenames.py +++ b/src/calibre/utils/filenames.py @@ -42,30 +42,44 @@ def supports_long_names(path): else: return True -def shorten_components_to(length, components): +def shorten_component(s, by_what): + l = len(s) + if l < by_what: + return s + l = (l - by_what)//2 + if l <= 0: + return s + return s[:l] + s[-l:] + +def shorten_components_to(length, components, more_to_take=0): filepath = os.sep.join(components) - extra = len(filepath) - length + extra = len(filepath) - (length - more_to_take) if extra < 1: return components - delta = int(ceil(extra/float(len(components)))) - ans = [] + deltas = [] for x in components: + pct = len(x)/float(len(filepath)) + deltas.append(int(ceil(pct*extra))) + ans = [] + + for i, x in enumerate(components): + delta = deltas[i] if delta > len(x): r = x[0] if x is components[-1] else '' else: if x is components[-1]: b, e = os.path.splitext(x) if e == '.': e = '' - r = b[:-delta]+e + r = shorten_component(b, delta)+e if r.startswith('.'): r = x[0]+r else: - r = x[:-delta] + r = shorten_component(x, delta) r = r.strip() if not r: r = x.strip()[0] if x.strip() else 'x' ans.append(r) if len(os.sep.join(ans)) > length: - return shorten_components_to(length, ans) + return shorten_components_to(length, components, more_to_take+2) return ans def find_executable_in_path(name, path=None):