def dispatch_command(self, command, user): if type(command) == list and len(command) > 0: if command[0] == ' get_books_list': from ia_scribe.book.library import Library l = Library() blist = l.get_all_books() msg = str(list(blist)) self.connection.msg(user, msg.encode('utf-8')) self.message_callback( 'Sent information about {} books in library'.format( len(blist)))
def __init__(self, **kwargs): self.book = None self._book_obj = None self._books_db = Library() self._show_advanced_options = False self._log_panel = None self._log_displayed = False self._trigger_update = Clock.create_trigger(self._update, -1) super(BookMenuPopup, self).__init__(**kwargs) self.use_tooltips = True Clock.schedule_once(self._postponed_init, -1)
def build(self): from ia_scribe.tasks.task_scheduler import TaskScheduler task_scheduler = TaskScheduler() task_scheduler.start() from ia_scribe.book.library import Library library = Library() app_screen = BookDownloadAppScreen(task_scheduler=task_scheduler, library=library) return app_screen
def __init__(self, **kwargs): self._identifier = None self._metadata = None self._new_book = False self._config = Scribe3Configuration() self.book_obj = None self.books_db = kwargs.pop('books_db', Library()) self.rcs_manager = RCS() self.rcs_manager.subscribe(self._rcs_update_handler) self.task_scheduler = kwargs.pop('task_scheduler') self.books_dir = kwargs.get('books_dir', None) or BOOKS_DIR self.book_path = kwargs.get('book_path', None) self.config_path = kwargs.get('config_path', None) or CONFIG_DIR super(BookMetadataScreenBackend, self).__init__(**kwargs)
def _postponed_init(self, *args): menu = self.ids.menu_bar menu.fbind(menu.EVENT_OPTION_SELECT, self.on_menu_bar_option_select) view = self.ids.note_leafs_view view.fbind(view.EVENT_LEAF_SELECT, self.on_note_leaf_select) self._books_db = Library()
class ReScribeScreen(TooltipScreen, Screen): cover_image = StringProperty(MISSING_IMAGE) book = ObjectProperty(None) scandata = ObjectProperty(None) scribe_widget = ObjectProperty(None) screen_manager = ObjectProperty(None) def __init__(self, **kwargs): self._note_leafs = [] self.book_obj = None super(ReScribeScreen, self).__init__(**kwargs) Clock.schedule_once(self._postponed_init) def _postponed_init(self, *args): menu = self.ids.menu_bar menu.fbind(menu.EVENT_OPTION_SELECT, self.on_menu_bar_option_select) view = self.ids.note_leafs_view view.fbind(view.EVENT_LEAF_SELECT, self.on_note_leaf_select) self._books_db = Library() def on_pre_enter(self): self.load_scandata() self.load_note_leafs() self.setup_menu_bar() self.setup_book_info_panel() self.setup_note_leafs_view() def load_scandata(self): book_path = self.book['path'] book_uuid = basename(book_path) self.book_obj = self._books_db.get_book(book_uuid) self.scandata = ScanData(book_path, downloaded=True) Logger.info( 'ReScribeScreen: Loaded scandata from directory: {}'.format( book_path)) def load_note_leafs(self): leafs = self._note_leafs del leafs[:] scandata = self.scandata book_path = self.book['path'] original_path = join(book_path, 'thumbnails') reshoot_path = join(book_path, 'reshooting', 'thumbnails') for note_leaf in scandata.iter_flagged_leafs(): leaf_data = scandata.get_page_data(note_leaf) image_name = '{:04d}.jpg'.format(note_leaf) reshoot_image_path = join(reshoot_path, image_name) page_number = leaf_data.get('pageNumber', None) new_leaf_data = { 'original_image': join(original_path, image_name), 'reshoot_image': reshoot_image_path, 'leaf_number': note_leaf, 'page_number': self._get_page_number(page_number), 'page_type': leaf_data['pageType'], 'note': leaf_data.get('note', None) or u'', 'status': 1 if exists(reshoot_image_path) else 0 } leafs.append(new_leaf_data) def _get_page_number(self, page_number_data): # TODO: Remove this method when scandata structure becomes the same # for reshooting mode and otherwise if page_number_data: if isinstance(page_number_data, dict): page_number = page_number_data.get('num', None) return None if page_number is None else int(page_number) elif isinstance(page_number_data, str): return int(page_number_data) return None def setup_menu_bar(self): menu = self.ids.menu_bar menu.identifier = self.book['identifier'] #menu.upload_button_disabled = not self.is_rescribing_complete() menu.reshooting_button_disabled = not bool(self._note_leafs) def setup_book_info_panel(self): panel = self.ids.book_info_panel panel.scroll_y = 1.0 cover_image = join(self.book['path'], 'thumbnails', '0001.jpg') if not exists(cover_image): cover_image = MISSING_IMAGE panel.cover_image = cover_image panel.claimer = self.get_claimer() panel.update_from_metadata(get_metadata(self.book['path'])) def get_claimer(self): path = join(expanduser(self.book['path']), 'claimer') if exists(path): with open(path, 'r') as f: return f.read() or NONE_STR return NONE_STR def setup_note_leafs_view(self): view = self.ids.note_leafs_view view.leafs[:] = self._note_leafs view.refresh_views() def popup_dismiss_to_home(self, popup, *args): popup.dismiss(animation=False) self.go_to_home() def go_to_home(self, *args, **kwargs): self.screen_manager.transition.direction = 'left' self.screen_manager.current = 'upload_screen' def on_menu_bar_option_select(self, menu, option): if option == menu.OPTION_UPLOAD: self.package_and_schedule_for_upload() elif option == menu.OPTION_FIRST_LEAF: leaf_number = self.find_first_non_reshoot_leaf_number() if leaf_number: self.open_book_at_leaf(leaf_number) elif option == menu.OPTION_PUBLIC_NOTES: metadata = get_metadata(self.book['path']) notes = metadata.get('notes', None) or '' popup = BookNotesPopup(title='Edit public book notes', notes=notes) popup.bind(on_submit=self.on_book_notes_submit) popup.open() elif option == menu.OPTION_INTERNAL_NOTES: internal_notes = self.scandata.get_internal_book_notes() or '' popup = BookNotesPopup(title='Edit internal book notes', notes=internal_notes) popup.bind(on_submit=self.on_internal_book_notes_submit) popup.open() def on_book_notes_submit(self, popup, notes): metadata = get_metadata(self.book['path']) metadata_notes = metadata.get('notes', None) or '' notes = notes.strip() if metadata_notes != notes: if notes: metadata['notes'] = notes message = 'Saved public book notes: %s' \ % ('\n%s' % notes if '\n' in notes else notes) else: metadata.pop('notes', None) message = 'Removed public book notes' set_metadata(metadata, self.book['path']) Logger.info('ReScribeScreen: %s' % message) self.book_obj.reload_metadata() def on_internal_book_notes_submit(self, popup, notes): scandata = self.scandata internal_notes = scandata.get_internal_book_notes() or '' notes = notes.strip() if internal_notes != notes: scandata.set_internal_book_notes(notes) scandata.save() if notes: message = 'Saved internal book notes: %s' \ % ('\n%s' % notes if '\n' in notes else notes) else: message = 'Removed internal book notes' Logger.info('ReScribeScreen: %s' % message) self.book_obj.reload_scandata() def on_note_leaf_select(self, note_leafs_view, note_leaf): self.open_book_at_leaf(note_leaf['leaf_number']) def find_first_non_reshoot_leaf_number(self): for note_leaf_data in self._note_leafs: if note_leaf_data['status'] == 0: return note_leaf_data['leaf_number'] try: ret = self._note_leafs[0]['leaf_number'] return ret except: return None def open_book_at_leaf(self, leaf_number): Logger.debug('ReScribeScreen: Trying to open book with id: {}'.format( self.book['identifier'])) screen_name = 'reshoot_screen' try: capture_screen = self.screen_manager.get_screen(screen_name) except Exception: capture_screen = ReShootScreen(name=screen_name) self.screen_manager.add_widget(capture_screen) capture_screen.pos = self.screen_manager.pos capture_screen.book = self.book capture_screen.reopen_at = leaf_number capture_screen.scandata = self.scandata capture_screen.screen_manager = self.screen_manager capture_screen.scribe_widget = self.scribe_widget ''' target_screen = screen_name models, ports = self.scribe_widget.cameras.get_cameras() camera_ports = self.scribe_widget.cameras.camera_ports if camera_ports['left'] not in ports: target_screen = 'calibration_screen' if camera_ports['right'] not in ports: target_screen = 'calibration_screen' foldout_port = camera_ports['foldout'] if foldout_port is not None and foldout_port not in ports: target_screen = 'calibration_screen' if target_screen == 'calibration_screen': screen = self.screen_manager.get_screen('calibration_screen') screen.target_screen = 'reshoot_screen' self.screen_manager.transition.direction = 'left' self.screen_manager.current = target_screen else: ''' self.screen_manager.transition.direction = 'left' self.screen_manager.current = screen_name def is_rescribing_complete(self): if not self._note_leafs: return False for leaf_data in self._note_leafs: if not exists(leaf_data['reshoot_image']): return False return True def package_and_schedule_for_upload(self): if self.is_rescribing_complete(): self.action = UploadCorrectionsBookActionMixin( book=self.book_obj, task_scheduler=self.scribe_widget.task_scheduler, done_action_callback=self.go_to_home) self.action.display() else: msg = 'ReScribeScreen: Book is not done rescribing' popup = InfoPopup(title='Error', message=msg, auto_dismiss=False) popup.bind(on_submit=popup.dismiss) popup.open() Logger.error(msg)
class BookMenuPopup(TooltipControl, FormBehavior, OverlayView): image = StringProperty() media_type = StringProperty(allownone=False) book_path = StringProperty(NONE_STR) title = StringProperty(NONE_STR) creator = StringProperty(NONE_STR) volume = StringProperty(NONE_STR) boxid = StringProperty(NONE_STR) uuid = StringProperty(NONE_STR) identifier = StringProperty(NONE_STR) isbn = StringProperty(NONE_STR) shiptracking = StringProperty(NONE_STR) status = StringProperty(NONE_STR) status_numeric = StringProperty(NONE_STR) next_states = StringProperty(NONE_STR) path_to_success = StringProperty(NONE_STR) operator = StringProperty(NONE_STR) edit_date = StringProperty(NONE_STR) update_date = StringProperty(NONE_STR) create_date = StringProperty(NONE_STR) leafs = StringProperty(NONE_STR) ppi = StringProperty(NONE_STR) error_msg = StringProperty(NONE_STR) task_msg = StringProperty(NONE_STR) worker_log = StringProperty() loading_image = LOADING_IMAGE _has_identifier = BooleanProperty(False) def __init__(self, **kwargs): self.book = None self._book_obj = None self._books_db = Library() self._show_advanced_options = False self._log_panel = None self._log_displayed = False self._trigger_update = Clock.create_trigger(self._update, -1) super(BookMenuPopup, self).__init__(**kwargs) self.use_tooltips = True Clock.schedule_once(self._postponed_init, -1) def _postponed_init(self, *args): menu = self.ids.entry_box menu.fbind('on_selection', self._on_option_selection) def init_from_data(self, book): self.book = book self._book_obj = self._books_db.get_item(book['uuid']) self._book_obj.subscribe(self._trigger_update) self._update() def _update(self, *args, **kwargs): self._update_attributes() self._update_from_metadata() self._update_ppi_from_scandata() self._update_book_options() if self._book_obj.is_locked(): self.lock_controls() owner = self._book_obj.worker_lock self.task_msg = 'This book is being worked on by {}'.format(owner) else: self.task_msg = '' self.unlock_controls() def _update_attributes(self): book_obj = self._book_obj self.uuid = self.book['uuid'] self.media_type = self.book.get('type').lower() self.book_path = book_obj.path self.error_msg = self.book.get('error', None) \ or book_obj.msg if book_obj.msg else None \ or book_obj.error if book_obj.error else None \ or '' status_tag = book_obj.status self.status = status_human_readable.get(status_tag, status_tag) self.status_numeric = '%s' % book_obj.get_numeric_status() if int(self.status_numeric) in ERROR_STATES: self.ids.status_numeric_button.rgba = (0.5, 0, 0, 1) else: self.ids.status_numeric_button.rgba = (0, 0.28, 0.42, .7) self.next_states = self._format_status_list( book_obj.get_available_next_states(human_readable=True)) self.path_to_success = self._format_status_list( book_obj.get_path_to_upload(human_readable=True), separator='->') self.identifier = book_obj.identifier or NONE_STR self._has_identifier = bool(book_obj.identifier) to_string = self._book_value_to_string self.leafs = to_string(book_obj, 'leafs') self.title = to_string(book_obj, 'title') self.creator = to_string(book_obj, 'creator') self.volume = to_string(book_obj, 'volume') self.boxid = to_string(book_obj, 'boxid') self.isbn = to_string(book_obj, 'isbn') self.shiptracking = to_string(book_obj, 'shiptracking') self.operator = to_string(book_obj, 'operator') if book_obj.date_last_modified: self.edit_date = time.strftime( '%m/%d/%Y %H:%M:%S', time.localtime(book_obj.date_last_modified)) else: self.edit_date = NONE_STR if book_obj.date_last_updated: self.update_date = time.strftime( '%m/%d/%Y %H:%M:%S', time.localtime(book_obj.date_last_updated)) else: self.update_date = NONE_STR if book_obj.date_created: self.create_date = time.strftime( '%m/%d/%Y %H:%M:%S', time.localtime(book_obj.date_created)) else: self.create_date = NONE_STR self.image = book_obj.get_cover_image() self.worker_log = book_obj.get_log() def _format_status_list(self, status_list, separator='|'): ret = " {} ".format(separator).join(status_list) return text_type(ret) def _update_book_options(self): menu = self.ids.entry_box num_status = UploadStatus[self._book_obj.status].value data = BOOK_STATUS_OPTIONS_TABLE.get(num_status, None) data = list(data) if data else list() advanced_text = 'Show Advanced' if self._show_advanced_options: advanced_text = 'Hide Advanced' data.append({ 'key': 'show_plan', 'text': 'Action Plan', 'icon': 'icon_expand_menu.png', 'color': 'blue' }) data.append({ 'key': 'move_along', 'text': 'Move along', 'icon': 'ff.png', 'color': 'blue' }) data.append({ 'key': 'advanced', 'text': advanced_text, 'icon': 'baseline_play_circle_filled_white_48dp.png', 'color': 'gray' }) data.append({ 'key': 'cancel', 'text': 'Close', 'icon': 'close_x.png', 'color': 'gray' }) if self._show_advanced_options: data = self._generate_next_actions_buttons() + data if len(data) % 2 == 1: data.insert(-2, {'key': 'dummy', 'disabled': True, 'opacity': 0}) menu.data = data def _generate_next_actions_buttons(self): out = [] next_actions = self._book_obj.get_available_next_actions() for action in next_actions: option = { 'key': 'do_action', 'text': action, 'icon': 'baseline_play_circle_filled_white_48dp.png', 'color': 'orange' } out.append(option) return out def _update_from_metadata(self): ''' this updates the values of certain self fields listed in `augmented_fields`, with the values fetched from reading metadata.xml of that book. We shouldn't be doing this here, instead relying on all the right information being passed to the constructor, which will come when we can pass more structured Book objects (2.0-Release branch) ''' try: self.metadata = get_metadata(self.book_path) except Exception: Logger.exception( 'Failed to get book metadata from path: {}'.format( self.book_path)) self.metadata = None augmented_fields = ['isbn', 'shiptracking'] if self.metadata: for field in augmented_fields: if field in self.metadata: setattr(self, field, self._book_value_to_string(self.metadata, field)) def _update_ppi_from_scandata(self): scandata = self._book_obj.get_scandata() bookData = scandata.get('bookData', None) if bookData: ppi = bookData.get('ppi', None) if ppi: self.ppi = str(ppi) def _book_value_to_string(self, md, key): value = md.get(key, None) if value is not None: if isinstance(value, list): return '; '.join(value) return '%s' % value return NONE_STR def _on_option_selection(self, menu, selection): selected = selection[0] if selected['key'] == 'advanced': self._show_advanced_options = not self._show_advanced_options self._update_book_options() elif selected['key'] == 'do_action': self.submit_data((selection[0]['key'], selection[0]['text'])) else: self.submit_data(selection[0]['key']) def _on_book_event(self, event, book, topic): #self._update() pass def open_book_path(self): book_path = self.book_path if book_path and exists(book_path): subprocess.check_call(['xdg-open', book_path.encode('utf-8')]) def on_dismiss(self): super(BookMenuPopup, self).on_dismiss() self.hide_log_panel() if self._book_obj: self._book_obj.unsub(self._trigger_update) self._book_obj = None self.book = None def show_log_panel(self, log, log_state): if not self._log_panel: self._log_panel = BookMenuPopupLogPanel(size_hint_y=0.95) self._log_panel.fbind('state', self._on_log_panel_state) if not self._log_displayed: self.ids.container.add_widget(self._log_panel) self._log_displayed = True self._log_panel.log = log self._log_panel.state = log_state def hide_log_panel(self): if self._log_panel and self._log_displayed: self._log_displayed = False self._log_panel.state = 'close' self.ids.container.remove_widget(self._log_panel) def _on_log_panel_state(self, log_panel, state): if state == 'close': self.hide_log_panel() elif state == 'show_log': log_panel.log = self.worker_log elif state == 'show_full_log': log = self._book_obj.get_full_log() log_panel.log = log[-10000:] elif state == 'show_history': history = self._book_obj.get_status_history() log_panel.log = '\n'.join(history) def show_log(self): self.show_log_panel(self.worker_log, 'show_log') def show_book_history(self): history = self._book_obj.get_status_history() self.show_log_panel('\n'.join(history), 'show_history') def show_book_full_log(self, *args): log = self._book_obj.get_full_log() # not entirely sure why truncating is necessary, but for now... self.show_log_panel(log[-10000:], 'show_full_log') def open_web_identifier(self): if self._has_identifier: webbrowser.open('https://archive.org/details/{}'.format( self._book_obj.identifier)) def lock_controls(self): self.ids.entry_box.disabled = True def unlock_controls(self): self.ids.entry_box.disabled = False
from ia_scribe.book.automata import move_along from ia_scribe.book.library import Library from ia_scribe.book.book import Book from ia_scribe.breadcrumbs import api as metrics_api from ia_scribe.breadcrumbs import other_stats from ia_scribe.cameras.optics import Cameras from ia_scribe.config.config import Scribe3Configuration from ia_scribe.notifications.notifications_manager import NotificationManager from ia_scribe.update.update import UpdateManager from ia_scribe.utils import restart_app, restart_process from ia_scribe.book import metadata from ia_scribe.ia_services.rcs import RCS cameras = Cameras() config = Scribe3Configuration() library = Library() notification_manager = NotificationManager() update_manager = UpdateManager() rcs_manager = RCS() ALLOWED_TOKENS = [ 'help', 'print', 'clear', 'exit', 'library', 'book', 'telemetry', 'metadata', 'rcs', 'config',
def _postponed_init(self, *args): self._books_db = Library() self.update_manager = UpdateManager() self.update_manager.task_scheduler = self.task_scheduler self.update_manager.schedule_update_check()