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)
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
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
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
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]
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
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]
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
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 = ''
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}
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())
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)
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)
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
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())
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)
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)
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())
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
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
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)))
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)
def _format_status_list(self, status_list, separator='|'): ret = " {} ".format(separator).join(status_list) return text_type(ret)
def get_page_data(self, leaf_num): return self.scandata['pageData'].get(text_type(leaf_num), {})
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
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
def _set_option(self, instance): self.value = text_type(self.options.index(instance.text)+1) self.popup.dismiss()
def _validate(self): self.value = text_type(round(self.popup.ids.slider.value, 2)) self._dismiss()
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())
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())
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
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())