Exemple #1
0
 def _update_marker_button(self, button, value):
     button.value = value
     prefix = self.tooltip_prefix
     if prefix:
         button.tooltip = text_type('{}: {}').format(prefix, value)
     else:
         button.tooltip = text_type(prefix)
Exemple #2
0
 def update_page_assertion(self, leaf_number, page_number):
     '''Updates pageNumData dict by setting `page_number` to key
     `leaf_num` or removing `leaf_num` entry if `page_number` is None.
     '''
     book_data = self.scandata['bookData']
     page_num_data = book_data.get('pageNumData', None)
     if page_num_data is None:
         book_data['pageNumData'] = page_num_data = {}
     if self._downloaded:
         assertions = page_num_data.get('assertion', None)
         if assertions is None:
             page_num_data['assertion'] = assertions = []
         if page_number is not None:
             for item in assertions:
                 if int(item['leafNum']) == leaf_number:
                     item['pageNum'] = text_type(page_number)
                     return
             assertions.append({
                 'leafNum': text_type(leaf_number),
                 'pageNum': text_type(page_number)
             })
         else:
             for index, item in enumerate(assertions):
                 if int(item['leafNum']) == leaf_number:
                     assertions.pop(index)
                     return
     else:
         if page_number is not None:
             page_num_data[text_type(leaf_number)] = page_number
         else:
             page_num_data.pop(text_type(leaf_number), None)
 def _write(self, instance):
     is_float = "." in str(self.value)
     self._dismiss()
     try:
         if is_float:
             self.value = text_type(float(self.textinput.text))
         else:
             self.value = text_type(int(self.textinput.text))
     except ValueError:
         return
Exemple #4
0
 def _validate(self, instance):
     super(SettingBoundedNumeric, self)._validate(instance)
     if type(self.max) is float or type(self.min) is float:
         value = float(self.value)
     else:
         value = int(self.value)
     if value > self.max:
         self.value = text_type(self.max)
     if value < self.min:
         self.value = text_type(self.min)
 def _write(self, instance):
     is_float = '.' in str(self.value)
     self._dismiss()
     try:
         if is_float:
             self.value = text_type(float(self.textinput.text))
         else:
             self.value = text_type(int(self.textinput.text))
     except ValueError:
         return
Exemple #6
0
 def _key_function(self, item):
     key = self._sort_key
     if key == 'progress':
         if item.get('task', None):
             return item['task'].last_report.get('progress', 0.0)
         return 0.0
     elif key in set(item.keys()):
         return text_type(item[key])
     elif item.get('task', None):
         return text_type(getattr(item['task'], key))
     return u''
 def _validate(self, instance):
     # we know the type just by checking if there is a '.' in the original
     # value
     is_float = '.' in str(self.value)
     self._dismiss()
     try:
         if is_float:
             self.value = text_type(float(self.textinput.text))
         else:
             self.value = text_type(int(self.textinput.text))
     except ValueError:
         return
Exemple #8
0
 def _validate(self, instance):
     # we know the type just by checking if there is a '.' in the original
     # value
     is_float = '.' in str(self.value)
     self._dismiss()
     try:
         if is_float:
             self.value = text_type(float(self.textinput.text))
         else:
             self.value = text_type(int(self.textinput.text))
     except ValueError:
         return
Exemple #9
0
    def _select_font(self):
        fontsize = int(self.options['font_size'])
        fontname = self.options['font_name_r']
        try:
            id = '%s.%s' % (text_type(fontname), text_type(fontsize))
        except UnicodeDecodeError:
            id = '%s.%s' % (fontname, fontsize)

        if id not in self._cache:
            font = ImageFont.truetype(fontname, fontsize)
            self._cache[id] = font

        return self._cache[id]
Exemple #10
0
 def _validate(self, instance, answer):
     # we know the type just by checking if there is a '.' in the original value
     is_float = '.' in str(self.value)
     value = self.popup.content.ids['input'].text
     self.dismiss()
     if answer == 'yes':
         try:
             if is_float:
                 self.value = text_type(float(value))
             else:
                 self.value = text_type(int(value))
         except ValueError:
             return
Exemple #11
0
    def _select_font(self):
        fontsize = int(self.options['font_size'])
        fontname = self.options['font_name_r']
        try:
            id = '%s.%s' % (text_type(fontname), text_type(fontsize))
        except UnicodeDecodeError:
            id = '%s.%s' % (fontname, fontsize)

        if not id in self._cache:
            font = ImageFont.truetype(fontname, fontsize)
            self._cache[id] = font

        return self._cache[id]
Exemple #12
0
    def format_value(self, value):
        ret = ''
        if type(value) is list:
            ret = ' | '.join(value)
        elif type(value) is dict:
            for n,item in enumerate(iter(sorted(value.items()))):
                k, v = item
                separator = ' | ' if n != 0 else ''
                formatted_key = text_type(k)
                formatted_value = text_type(v)
                item_string = separator + '[size=16][i][b]{k}: [/b][/i][/size][size=18]{v}[/size]'.format(k=formatted_key, v=formatted_value)
                ret += item_string

        else:
            ret = text_type(value)
        return ret
Exemple #13
0
 def post_login(self, result, error):
     if not error:
         self.dispatch(self.EVENT_LOGIN_USER_SUCCESS, self.email, result)
     else:
         msg = text_type(error)
         self.dispatch(self.EVENT_LOGIN_USER_FAILURE, self.email, msg)
     self.email = self.password = ''
Exemple #14
0
 def add_page_num(self, leaf_num, page_num, page_num_type):
     page_data = self.get_page_data(leaf_num)
     if not page_data:
         # Only update existing page_data
         return
     if self._downloaded:
         page_num = text_type(page_num)
     page_data['pageNumber'] = {'num': page_num, 'type': page_num_type}
Exemple #15
0
 def update_page_type(self, leaf_number, page_type):
     leaf_data = self.scandata['pageData'].get(text_type(leaf_number), None)
     if leaf_data is not None:
         old_page_type = leaf_data['pageType']
         leaf_data['pageType'] = page_type
         self._cache.add(page_type, leaf_number)
         self._cache.discard(old_page_type, leaf_number)
         self.dispatch('on_leafs', self._cache.pop_change_report())
Exemple #16
0
 def refresh_view_attrs(self, rv, index, data):
     self.index = index
     self.focus = False
     self.key = self._format_key(data['key'])
     self.readonly = readonly = data.get('readonly', False)
     self.text = text_type(data['value'])
     self.disabled = rv.layout_manager.disabled
     self.validate(data)
Exemple #17
0
 def _to_valid_value(self, stats, key, not_allowed=(None, '')):
     value = stats.get(key, None)
     if value in not_allowed:
         return None
     if key == 'leaf_num' or key == 'ppi':
         return int(value)
     if key == 'capture_time' or key == 'blurriness':
         return float(value)
     return text_type(value)
Exemple #18
0
 def _update_file_paths(self, leaf_data, leaf_number):
     for file_key in FILE_PATH_KEYS:
         full_path = leaf_data.get(file_key, None)
         if full_path is not None:
             path, ext = splitext(full_path)
             name = path.split('_')[-1]
             path = path.rstrip(name + ext)
             new_name = text_type(leaf_number).rjust(4, '0')
             leaf_data[file_key] = path + new_name + ext
Exemple #19
0
    def _downloaded_insert(self, leaf_number, side, page_type):
        page_data = self.scandata['pageData']
        max_leaf_number = self.get_max_leaf_number()
        total = 0 if max_leaf_number is None else max_leaf_number + 1
        new_leaf_data = {
            'pageType': page_type,
            'ppi': text_type(self.default_ppi),
            'rotateDegree': text_type(SIDE_TO_DEGREE[side]),
            'type': 'INSERT',
            'handSide': 'LEFT' if leaf_number % 2 == 0 else 'RIGHT'
        }
        new_page_num_data = {}
        book_data = self.scandata['bookData']
        if leaf_number < total:
            stack = []
            for leaf_int in range(total - 1, leaf_number - 1, -1):
                leaf_data = page_data.pop(text_type(leaf_int), None)
                if not leaf_data:
                    stack.append(None)
                    continue
                self._cache.discard(leaf_data['pageType'], leaf_int)
                self._cache.discard(KEY_NOTE, leaf_int)
                stack.append(leaf_data)
            page_data[text_type(leaf_number)] = new_leaf_data

            page_num_data = book_data.get('pageNumData', None)

            # Porting assertions for leafs BEFORE insertion point
            if page_num_data:
                assertions = page_num_data.get('assertion', None)
                if assertions:
                    for item in assertions:
                        leaf_int = int(item['leafNum'])
                        if leaf_int >= leaf_number:
                            item['leafNum'] = text_type(leaf_int + 1)

            for leaf_int in range(leaf_number + 1, total + 1):
                leaf_data = stack.pop()
                if not leaf_data:
                    continue
                # self._update_file_paths(leaf_data, leaf_int)
                hand_side = 'LEFT' if leaf_int % 2 == 0 else 'RIGHT'
                leaf_data['handSide'] = hand_side
                page_data[text_type(leaf_int)] = leaf_data
                self._cache.add(leaf_data['pageType'], leaf_int)
                if KEY_NOTE in leaf_data:
                    self._cache.add(KEY_NOTE, leaf_int)
            self.compute_page_nums(total + 1)
        else:
            page_data[text_type(leaf_number)] = new_leaf_data

        self._cache.add(page_type, leaf_number)
        book_data['leafCount'] = text_type(len(page_data))
        self.dispatch('on_leafs', self._cache.pop_change_report())
Exemple #20
0
 def get_page_assertion(self, leaf_number):
     book_data = self.scandata['bookData']
     page_num_data = book_data.get('pageNumData', None)
     if not page_num_data:
         return None
     if self._downloaded:
         assertions = page_num_data.get('assertion', None)
         if assertions:
             for item in assertions:
                 if int(item['leafNum']) == leaf_number:
                     return int(item['pageNum'])
         return None
     else:
         return page_num_data.get(text_type(leaf_number), None)
Exemple #21
0
 def backfill(self, curr_page_num, page_type=PT_NORMAL):
     '''If we are adding images to a book that was started before
     `scandata.json` files were being written, backfill the data using
     default values.
     '''
     if self._downloaded:
         return
     if curr_page_num == 0:
         return
     page_data_keys = set(self.scandata['pageData'])
     # Note that xrange is not inclusive, so we add one to the end
     for i in range(curr_page_num + 1):
         if text_type(i) not in page_data_keys:
             side = 'left' if i % 2 == 0 else 'right'
             self.update(i, side, page_type)
Exemple #22
0
 def update(self, leaf_number, side, page_type=PT_NORMAL):
     '''Update or set pageData['leaf_number'] with `rotateDegree` computed
     from side.
     '''
     page_data = self.get_page_data(leaf_number)
     old_page_type = page_data['pageType']
     if not self._downloaded:
         page_data['rotateDegree'] = SIDE_TO_DEGREE[side]
     elif page_data.get('rotateDegree', None) is None:
         page_data['rotateDegree'] = SIDE_TO_DEGREE[side]
     page_data['pageType'] = page_type
     self.scandata['pageData'][text_type(leaf_number)] = page_data
     self._cache.add(page_type, leaf_number)
     self._cache.add(old_page_type, leaf_number)
     self.dispatch('on_leafs', self._cache.pop_change_report())
Exemple #23
0
 def update_metadata(self):
     """Update scanner metadata
     """
     config = get_metadata(scribe_globals.SCANCENTER_METADATA_DIR)
     # Go trough all widgets
     # Since there are also "EmailTextInput" class instances,
     # let us see each widget has 'metadata_key' property
     for widget in self.ids['_metadata'].children:
         if hasattr(widget, 'metadata_key'):
             value = config.get(widget.metadata_key)
             if value is not None:
                 widget.text = text_type(value)
     # Easter egg
     if config.get('operator') == '*****@*****.**':
         rectangle = self.ids['_about_header'].canvas.before.children[1]
         rectangle.source = 'images/fidget.png'
    def _validate(self, instance):
        if self._range:
            self._dismiss()
            try:
                value = self.textinput.text.strip()
                value = text_type(int(value))
            except ValueError:
                self.textinput.text = self.value
                return
            if not self._override:
                if self.minval <= int(value) <= self.maxval:
                    self.value = value
                else:
                    self.value = str(self.default[self.default_key])
            else:
                self.value = str(value)

            self.textinput.text = self.value
Exemple #25
0
    def _validate(self, instance):
        if self._range:
            self._dismiss()
            try:
                value = self.textinput.text.strip()
                value = text_type(float(value))
            except ValueError:
                self.textinput.text = self.value
                return
            if not self._override:
                if self.minval <= float(value) <= self.maxval:
                    self.value = value
                else:
                    self.value = str(self.default[self.default_key])
            else:
                self.value = str(value)

            self.textinput.text = self.value
Exemple #26
0
def set_metadata(md,
                 meta_dir,
                 file_name='metadata.xml',
                 root_element='metadata'):
    meta_dir_expanded = os.path.expanduser(meta_dir)
    meta_file = os.path.join(meta_dir_expanded, file_name)
    root = etree.Element(root_element)
    for key, value in md.items():
        if isinstance(value, list):
            for item in value:
                child = etree.SubElement(root, key)
                child.text = item
        else:
            if value is not None:
                child = etree.SubElement(root, key)
                child.text = text_type(value)
    tree = etree.ElementTree(root)
    tree.write(meta_file, encoding='utf-8', pretty_print=True)
    Logger.info(
        'Metadata: Saved at path "{}" with root element "{}"{}{}'.format(
            meta_file, root_element, os.linesep, pformat(md)))
Exemple #27
0
 def set_metadata(self, md):
     ids = self.ids
     get = get_string_value_if_list
     ids.date.text = md['datetime'].strftime('%Y-%m-%d')
     ids.time.text = md['datetime'].strftime('%H:%M')
     ids.operator.text = (md.get('operator', None) or NONE_STR)\
         .replace('@archive.org', '', 1)
     ids.scanner.text = (md.get('scanner', None) or NONE_STR)\
         .replace('.archive.org', '', 1)
     self._isbn = md.get('isbn', None)
     ids.isbn.text = self._isbn or NONE_STR
     ids.boxid.text = md.get('boxid', None) or NONE_STR
     ids.old_pallet.text = md.get('old_pallet', None) or NONE_STR
     ids.title.text = self.purify_string(md.get('title', None)) or NONE_STR
     ids.creator.text = self.purify_string(get(md, 'creator',
                                               u'; ')) or NONE_STR
     ids.pages.text = text_type(md.get('pages', None) or NONE_STR)
     identifier = md.get('identifier', None)
     ids.identifier.text = identifier if identifier else NONE_STR
     url = DETAILS_URL + identifier if identifier else NONE_STR
     ids.url.text = url
     self._set_qr_label(url)
Exemple #28
0
 def _format_status_list(self, status_list, separator='|'):
     ret = " {} ".format(separator).join(status_list)
     return text_type(ret)
Exemple #29
0
 def get_page_data(self, leaf_num):
     return self.scandata['pageData'].get(text_type(leaf_num), {})
Exemple #30
0
 def update_rotate_degree(self, leaf_number, degree):
     data = self.get_page_data(leaf_number)
     degree = text_type(degree) if self._downloaded else degree
     data['rotateDegree'] = degree
     self.scandata['pageData'][text_type(leaf_number)] = data
Exemple #31
0
 def set_ppi(self, leaf_number, ppi_value):
     data = self.get_page_data(leaf_number)
     ppi_value = text_type(ppi_value) if self._downloaded else ppi_value
     data['ppi'] = ppi_value
     self.scandata['pageData'][text_type(leaf_number)] = data
Exemple #32
0
 def _set_option(self, instance):
     self.value = text_type(self.options.index(instance.text)+1)
     self.popup.dismiss()
Exemple #33
0
 def _validate(self):
     self.value = text_type(round(self.popup.ids.slider.value, 2))
     self._dismiss()
Exemple #34
0
    def delete_spread(self, left_leaf_num, right_leaf_num):
        end_leaf_num = self.get_max_leaf_number()
        page_data = self.scandata['pageData']
        book_data = self.scandata['bookData']
        page_num_data = book_data.get('pageNumData', None)

        # Pop the spread
        for leaf_int in range(left_leaf_num, right_leaf_num + 1):
            # If there is an asserted page number, delete the assertion from
            # pageNumData block
            leaf_str = text_type(leaf_int)
            if page_num_data and leaf_str in page_num_data:
                del page_num_data[leaf_str]
            leaf_data = page_data.pop(leaf_str, None)
            if leaf_data:
                self._cache.discard(leaf_data['pageType'], leaf_int)
                self._cache.discard(KEY_NOTE, leaf_int)

        if self._downloaded:
            book_data['leafCount'] = text_type(len(page_data))

        # If we are deleting at the end
        if end_leaf_num == right_leaf_num:
            if page_num_data is None:
                return
            if self._downloaded:
                assertions = page_num_data.get('assertion', None)
                if assertions:
                    for_deletion = []
                    leaf_ints = set(range(left_leaf_num, right_leaf_num + 1))
                    for index, item in enumerate(assertions):
                        leaf_int = int(item['leafNum'])
                        if leaf_int in leaf_ints:
                            for_deletion.append(index)
                            leaf_ints.remove(leaf_int)
                        if not leaf_ints:
                            break
                    while for_deletion:
                        assertions.pop(for_deletion.pop())
            else:
                for leaf_int in range(left_leaf_num, right_leaf_num + 1):
                    page_num_data.pop(text_type(leaf_int), None)
            self.dispatch('on_leafs', self._cache.pop_change_report())
            return

        # if we are deleting in the middle, split at the deletion point
        # and cycle through the leafs up to the end and, if deleting a
        # single-page spread, swap sides accordingly
        delta = right_leaf_num - left_leaf_num + 1
        should_update_hand_side = delta % 2 != 0
        # Update leaf numbers because insert is not at the end
        for leaf_int in range(right_leaf_num + 1, end_leaf_num + 1):
            leaf_str = text_type(leaf_int)
            leaf_data = page_data.get(leaf_str, None)
            if not leaf_data:
                continue
            # move the leaf back
            prev_leaf_int = leaf_int - delta
            # Add handSide if the book has been downloaded
            if self._downloaded and should_update_hand_side:
                hand_side = 'LEFT' if prev_leaf_int % 2 == 0 else 'RIGHT'
                leaf_data['handSide'] = hand_side
                # self._update_file_paths(leaf_data, prev_leaf_int)
            # Finally, add the constructed leaf_data to page_data in the new
            # position
            page_data[text_type(prev_leaf_int)] = leaf_data
            # and delete the original leaf. This strikes me as dangerous.
            del page_data[leaf_str]
            self._cache.discard(leaf_data['pageType'], leaf_int)
            self._cache.add(leaf_data['pageType'], prev_leaf_int)
            if KEY_NOTE in leaf_data:
                self._cache.discard(KEY_NOTE, leaf_int)
                self._cache.add(KEY_NOTE, prev_leaf_int)

        # If there is no assertion, we're done!
        if page_num_data is None:
            return

        # Fix page assertions
        # sorted_leafs is a list of strings, but sorted by int value
        if self._downloaded:
            assertions = page_num_data.get('assertion', None)
            if assertions:
                assertions = {x['leafNum']: x['pageNum'] for x in assertions}
                sorted_leafs = sorted(assertions, key=int)
                for leaf_str in sorted_leafs:
                    leaf_int = int(leaf_str)
                    if leaf_int > right_leaf_num + 1:
                        assertions[text_type(leaf_int -
                                             delta)] = assertions[leaf_str]
                        del assertions[leaf_str]
                page_num_data['assertion'] = [{
                    'leafNum': k,
                    'pageNum': v
                } for k, v in assertions.items()]
        else:
            sorted_leafs = sorted(page_num_data, key=int)
            for leaf_str in sorted_leafs:
                leaf_int = int(leaf_str)
                if leaf_int > right_leaf_num:
                    prev_leaf_str = text_type(leaf_int - delta)
                    page_num_data[prev_leaf_str] = page_num_data[leaf_str]
                    del page_num_data[leaf_str]
        self.compute_page_nums(end_leaf_num)
        self.dispatch('on_leafs', self._cache.pop_change_report())
Exemple #35
0
    def _default_insert(self, leaf_number, side, page_type):
        page_data = self.scandata['pageData']
        page_num_data = self.scandata['bookData'].get('pageNumData', None)
        new_page_num_data = {}
        max_leaf_number = self.get_max_leaf_number()
        total = 0 if max_leaf_number is None else max_leaf_number + 1
        new_leaf_data = {
            'pageType': page_type,
            'ppi': self.default_ppi,
            'rotateDegree': SIDE_TO_DEGREE[side]
        }
        # If we are not appending, but actually inserting
        if leaf_number < total:
            stack = []
            # Put all the leafs after insertion point into a stack
            for leaf_int in range(total - 1, leaf_number - 1, -1):
                leaf_str = text_type(leaf_int)
                leaf_data = page_data.pop(leaf_str, None)
                if not leaf_data:
                    stack.append(None)
                    continue
                self._cache.discard(leaf_data['pageType'], leaf_int)
                self._cache.discard(KEY_NOTE, leaf_int)
                stack.append(leaf_data)

            # Porting assertions for leafs BEFORE insertion point
            for leaf in page_data.items():
                if 'pageNumber' in leaf[1]:
                    if leaf[1]['pageNumber']['type'] == 'assert':
                        leaf_str = text_type(leaf[0])
                        new_page_num_data[leaf_str] = leaf[1]['pageNumber'][
                            'num']

            # drop in the new leaf
            page_data[text_type(leaf_number)] = new_leaf_data

            # add leafs from the stack and update references to assertions
            for leaf_int in range(leaf_number + 1, total + 1):
                leaf_str = text_type(leaf_int)
                leaf_data = stack.pop()
                if not leaf_data:
                    continue
                if 'pageNumber' in leaf_data:
                    assertion = leaf_data.pop('pageNumber')
                    if assertion['type'] == 'assert':
                        new_page_num_data[text_type(
                            leaf_int)] = assertion['num']

                page_data[leaf_str] = leaf_data
                self._cache.add(leaf_data['pageType'], leaf_int)
                if KEY_NOTE in leaf_data:
                    self._cache.add(KEY_NOTE, leaf_int)
                # self.compute_page_nums(total + 1)

            # Replace old assertion block with new one
            if page_num_data:
                self.scandata['bookData']['pageNumData'] = new_page_num_data
                self.compute_page_nums(total + 1)

        # This is an insertion at the end
        else:
            page_data[text_type(leaf_number)] = new_leaf_data

        self._cache.add(page_type, leaf_number)
        self.dispatch('on_leafs', self._cache.pop_change_report())
Exemple #36
0
 def set_capture_time(self, leaf_number, capture_time):
     leaf_data = self.get_page_data(leaf_number)
     leaf_data['cameraTime'] = capture_time
     self.scandata['pageData'][text_type(leaf_number)] = leaf_data
Exemple #37
0
 def _load(self):
     scandata = {
         'bookData': {},
         'pageData': OrderedDict(),
     }
     cache = ScandataCache(VALID_PAGE_TYPES | {KEY_NOTE})
     if self.book_dir is None:
         self._cache = cache
         self.scandata = scandata
     path = join(self.book_dir, 'scandata.json')
     if not exists(path):
         self._cache = cache
         self.scandata = scandata
         self.dispatch('on_leafs', cache.pop_change_report())
         return
     f = None
     try:
         f = open(path, 'rb', 'utf-8')
         tmp = json.load(f)
         tmp_page_data = tmp.get('pageData', None)
         if tmp_page_data:
             max_leaf_number = max(map(int, tmp_page_data))
             for leaf_int in range(max_leaf_number + 1):
                 leaf_str = str(leaf_int)
                 leaf_data = tmp_page_data.get(leaf_str, None)
                 if not leaf_data:
                     continue
                 page_type = leaf_data.get('pageType', None)
                 if page_type not in VALID_PAGE_TYPES:
                     continue
                 scandata['pageData'][leaf_str] = leaf_data
                 cache.add(page_type, leaf_int)
                 if KEY_NOTE in leaf_data:
                     cache.add(KEY_NOTE, leaf_int)
         page_data = scandata['pageData']
         tmp_book_data = tmp.get('bookData', None)
         if tmp_book_data:
             page_num_data = tmp_book_data.get('pageNumData', None)
             if self._downloaded and page_num_data:
                 assertions = page_num_data.get('assertion', None)
                 if assertions:
                     # Delete assertions where leafNum doesn't exists in
                     # pageData
                     for_deletion = []
                     for index, assertion in enumerate(assertions):
                         if not page_data.get(assertion['leafNum'], None):
                             for_deletion.append(index)
                     while for_deletion:
                         assertions.pop(for_deletion.pop())
             elif page_num_data:
                 # Delete leaf number for pageNumData if it doesn't exists
                 # in pageData
                 for_deletion = []
                 for leaf_str in page_num_data:
                     if not page_data.get(leaf_str, None):
                         for_deletion.append(leaf_str)
                 while for_deletion:
                     page_num_data.pop(for_deletion.pop())
             scandata['bookData'] = tmp_book_data
             if self._downloaded:
                 # Ensure that leafCount is correct
                 tmp_book_data['leafCount'] = text_type(len(page_data))
     except Exception:
         traceback.print_exc()
         print(('Could not load scandata from {}'.format(path)))
     finally:
         if f:
             f.close()
     self._cache = cache
     self.scandata = scandata
     self.dispatch('on_leafs', cache.pop_change_report())