class ServerListsScreen(Screen): base_url = StringProperty() api_url = StringProperty() def __init__(self, **kwargs): super(ServerListsScreen, self).__init__(**kwargs) self.lists_loaded = BooleanProperty() self.lists_loaded = False self.app = App.get_running_app() self.fetch_data = None self.Data = "" self.fetch_data = ComicServerConn() self.base_url = self.app.base_url self.api_url = self.app.api_url def on_pre_enter(self): self.app.show_action_bar() def on_enter(self, *args): self.base_url = self.app.base_url self.api_url = self.app.api_url if self.lists_loaded is False: self.get_comicrack_list() self.app.set_screen("ComicRack Lists") def on_leave(self): self.app.list_previous_screens.append(self.name) def get_comicrack_list(self): if self.lists_loaded is False: url_send = f"{self.api_url}/lists/" self.fetch_data.get_server_data(url_send, self) def node_expand(self, instance, node): node.icon = "folder-open" def node_collapse(self, instance, node): node.icon = "folder" def do_expand(self, instance, node): self.my_tree.toggle_node(instance) def callback_for_menu_items(self, *args): toast(args[0]) def open_readinglist(self, instance, node): def __wait_for_open(dt): if server_readinglists_screen.loading_done is True: self.app.manager.current = "server_readinglists_screen" self.loading_event.cancel() server_readinglists_screen = self.app.manager.get_screen( "server_readinglists_screen") server_readinglists_screen.setup_screen() server_readinglists_screen.page_number = 1 readinglist_Id = instance.id readinglist_name = (instance.text).split(" : ")[0] server_readinglists_screen.list_loaded = False query = ReadingList.select().where(ReadingList.slug == readinglist_Id) if query.exists(): Logger.info(f"{readinglist_name} already in Database") set_mode = "From DataBase" else: Logger.info("{} not in Database getting info from server".format( readinglist_name)) set_mode = "From Server" # set_mode = 'From Server' server_readinglists_screen.loading_done = False Clock.schedule_once( lambda dt: server_readinglists_screen.collect_readinglist_data( readinglist_name=readinglist_name, readinglist_Id=readinglist_Id, mode=set_mode, )) self.app.manager.current = "server_readinglists_screen" # self.loading_event = Clock.schedule_interval(__wait_for_open, 0.25) def got_json(self, req, result): self.ids.mytv.clear_widgets() self.my_tree = self.ids.mytv self.my_tree.clear_widgets() self.my_tree.bind(minimum_height=self.my_tree.setter("height")) self.my_tree.bind(on_node_expand=self.node_expand) self.my_tree.bind(on_node_collapse=self.node_collapse) for item in result: if item["Name"] != "Library": if (item["Type"] == "ComicLibraryListItem" or item["Type"] == "ComicSmartListItem"): new_node = self.my_tree.add_node( TreeViewItem( text=item["Name"], color=( 0.9568627450980393, 0.2627450980392157, 0.21176470588235294, 1, ), id=item["Id"], )) new_node.bind(on_touch_down=self.open_readinglist) elif item["Type"] == "ComicListItemFolder": parent = self.my_tree.add_node( TreeViewFolder( text=item["Name"], color=( 0.9568627450980393, 0.2627450980392157, 0.21176470588235294, 1, ), id=item["Id"], )) parent.bind(on_touch_down=self.do_expand) self.set_files(parent, item["Lists"]) self.lists_loaded = True def set_files(self, parent, child): for item in child: if (item["Type"] == "ComicLibraryListItem" or item["Type"] == "ComicSmartListItem" or item["Type"] == "ComicIdListItem"): new_node = self.my_tree.add_node( TreeViewItem( text=item["Name"], color=( 0.9568627450980393, 0.2627450980392157, 0.21176470588235294, 1, ), id=item["Id"], ), parent, ) new_node.bind(on_touch_down=self.open_readinglist) elif item["Type"] == "ComicListItemFolder": sub_parent = self.my_tree.add_node( TreeViewFolder( text=item["Name"], color=( 0.9568627450980393, 0.2627450980392157, 0.21176470588235294, 1, ), id=item["Id"], ), parent, ) sub_parent.bind(on_touch_down=self.do_expand) self.set_files(sub_parent, item["Lists"])
class LocalReadingListsScreen(Screen): reading_list_title = StringProperty() page_number = NumericProperty() max_books_page = NumericProperty() dynamic_ids = DictProperty({}) # declare class attribute, dynamic_ids sync_bool = BooleanProperty(False) so = BooleanProperty() new_readinglist = ObjectProperty() def __init__(self, **kwargs): super(LocalReadingListsScreen, self).__init__(**kwargs) self.app = App.get_running_app() self.fetch_data = None self.readinglist_Id = StringProperty() self.readinglist_name = "" # self.bind_to_resize() self.bind(width=self.my_width_callback) self.m_grid = "" self.main_stack = "" self.prev_button = "" self.next_button = "" self.base_url = self.app.base_url self.api_url = self.app.api_url self.api_key = self.app.config.get("General", "api_key") self.list_count = "" self.paginator_obj = ObjectProperty() self.current_page = ObjectProperty() self.list_loaded = BooleanProperty() self.page_number = 1 self.list_loaded = False self.comic_thumb_height = 240 self.comic_thumb_width = 156 self.file_download = True self.num_file_done = 0 self.max_books_page = self.app.max_books_page def callback_for_menu_items(self, *args): pass def setup_screen(self): self.api_key = self.app.config.get("General", "api_key") self.api_url = self.app.api_url self.main_stack = self.ids["main_stack"] self.m_grid = self.ids["main_grid"] self.prev_button = self.ids["prev_button"] self.next_button = self.ids["next_button"] def on_pre_enter(self, *args): self.app.show_action_bar() return super().on_pre_enter(*args) def on_leave(self, *args): self.app.list_previous_screens.append(self.name) return super().on_leave(*args) def on_enter(self, *args): self.app.set_screen(f"{self.readinglist_name}-(Local) Page 1") def my_width_callback(self, obj, value): for key, val in self.ids.items(): if key == "main_grid": c = val c.cols = (Window.width - 10) // self.comic_thumb_width def page_turn(self, c_id, new_UserLastPageRead): grid = self.m_grid for child in grid.children: if child.comic_obj.Id == c_id: if new_UserLastPageRead == 0: child.percent_read = 0 else: child.percent_read = round( new_UserLastPageRead / (child.comic_obj.PageCount - 1) * 100) child.page_count_text = f"{child.percent_read}%" def collect_readinglist_data(self, readinglist_name, readinglist_Id, mode="From DataBase"): self.readinglist_name = readinglist_name self.reading_list_title = self.readinglist_name + " Page 1" self.readinglist_Id = readinglist_Id self.mode = mode if self.mode == "From Server": self.fetch_data = ComicServerConn() lsit_count_url = f"{self.api_url}/Lists/{readinglist_Id}/Comics/" # self.fetch_data.get_list_count(lsit_count_url,self) self.fetch_data.get_server_data(lsit_count_url, self) elif self.mode == "From DataBase": self.got_db_data() def get_page(self, instance): page_num = instance.page_num self.app.set_screen(self.readinglist_name + f" Page {page_num}") self.reading_list_title = self.readinglist_name + f" Page {page_num}" page = self.paginator_obj.page(page_num) self.current_page = page if page.has_next(): self.next_button.opacity = 1 self.next_button.disabled = False self.next_button.page_num = page.next_page_number() else: self.next_button.opacity = 0 self.next_button.disabled = True self.next_button.page_num = "" if page.has_previous(): self.prev_button.opacity = 1 self.prev_button.disabled = False self.prev_button.page_num = page.previous_page_number() else: self.prev_button.opacity = 0 self.prev_button.disabled = True self.prev_button.page_num = "" self.build_page(page.object_list) self.ids.main_scroll.scroll_to(self.ids.main_grid.children[0], padding=10, animate=True) def build_page(self, object_lsit): grid = self.m_grid grid.clear_widgets() for comic in object_lsit: if comic.is_sync: c = ReadingListComicImage(comic_obj=comic) c.lines = 2 c.readinglist_obj = self.new_readinglist c.paginator_obj = self.paginator_obj y = self.comic_thumb_height if self.mode == "From Server": part_url = f"/Comics/{comic.Id}/Pages/0?" part_api = f"&apiKey={self.api_key}&height={round(dp(y))}" c_image_source = f"{self.api_url}{part_url}{part_api}" else: import os id_folder = os.path.join(self.app.sync_folder, self.new_readinglist.slug) my_thumb_dir = os.path.join(id_folder, "thumb") thumb_name = f"{comic.Id}.jpg" t_file = os.path.join(my_thumb_dir, thumb_name) c_image_source = t_file c.source = c_image_source c.PageCount = comic.PageCount c.pag_pagenum = self.current_page.number c.view_mode = "Sync" grid.add_widget(c) grid.cols = (Window.width - 10) // self.comic_thumb_width self.dynamic_ids[id] = c else: pass self.ids.page_count.text = f"Page #\n{self.current_page.number} of \ {self.paginator_obj.num_pages()}" def got_db_data(self): """ used if rl data is already stored in db. """ def _do_readinglist(): self.new_readinglist = ComicReadingList( name=self.readinglist_name, data="db_data", slug=self.readinglist_Id, mode="local_file", ) self.so = self.new_readinglist.sw_syn_this_active self.setup_options() new_readinglist_reversed = self.new_readinglist.comics self.paginator_obj = Paginator(new_readinglist_reversed, self.max_books_page) page = self.paginator_obj.page(self.page_number) self.current_page = page if page.has_next(): self.next_button.opacity = 1 self.next_button.disabled = False self.next_button.page_num = page.next_page_number() else: self.next_button.opacity = 0 self.next_button.disabled = True self.next_button.page_num = "" if page.has_previous(): self.prev_button.opacity = 1 self.prev_button.disabled = False self.prev_button.page_num = page.previous_page_number() else: self.prev_button.opacity = 0 self.prev_button.disabled = True self.prev_button.page_num = "" self.build_page(page.object_list) self.list_loaded = True Clock.schedule_once(lambda dt: _do_readinglist(), 0) # self.bind(new_readinglist=self.setter('sync_bool')) # self.max_books_page = int(self.app.config.get( # 'General', 'max_books_page')) def got_json(self, req, results): self.new_readinglist = ComicReadingList(name=self.readinglist_name, data=results, slug=self.readinglist_Id) for item in self.new_readinglist.comic_json: comic_index = self.new_readinglist.comic_json.index(item) new_comic = ComicBook( item, readlist_obj=self.new_readinglist, comic_index=comic_index, ) self.new_readinglist.add_comic(new_comic) self.setup_options() new_readinglist_reversed = self.new_readinglist.comics[::-1] self.paginator_obj = Paginator(new_readinglist_reversed, self.max_books_page) page = self.paginator_obj.page(self.page_number) self.current_page = page if page.has_next(): self.next_button.opacity = 1 self.next_button.disabled = False self.next_button.page_num = page.next_page_number() else: self.next_button.opacity = 0 self.next_button.disabled = True self.next_button.page_num = "" if page.has_previous(): self.prev_button.opacity = 1 self.prev_button.disabled = False self.prev_button.page_num = page.previous_page_number() else: self.prev_button.opacity = 0 self.prev_button.disabled = True self.prev_button.page_num = "" self.build_page(page.object_list) self.list_loaded = True def setup_options(self): s_r_l = self.new_readinglist self.sync_options = SyncOptionsPopup( size_hint=(0.76, 0.76), cb_limit_active=s_r_l.cb_limit_active, limit_num_text=str(s_r_l.limit_num), cb_only_read_active=s_r_l.cb_only_read_active, cb_purge_active=s_r_l.cb_purge_active, cb_optimize_size_active=s_r_l.cb_optimize_size_active, sw_syn_this_active=bool(s_r_l.sw_syn_this_active), ) self.sync_options.ids.limit_num.bind( on_text_validate=self.sync_options.check_input, focus=self.sync_options.check_input, ) self.sync_options.title = self.new_readinglist.name def open_sync_options(self): if self.sync_options.ids.sw_syn_this.active is True: self.sync_options.ids.syn_on_off_label.text = f"" self.sync_options.ids.syn_on_off_label.theme_text_color = "Primary" self.sync_options.open() def sync_readinglist(self): if self.sync_options.ids.sw_syn_this.active is False: self.sync_options.ids.syn_on_off_label.text = f"Sync Not Turned On" self.open_sync_options() elif self.sync_options.ids.sw_syn_this.active is True: toast(f"Starting sync of {self.new_readinglist.name}") self.new_readinglist.do_sync()
class ServerReadingListsScreen(Screen): reading_list_title = StringProperty() page_number = NumericProperty() max_books_page = NumericProperty() dynamic_ids = DictProperty({}) # declare class attribute, dynamic_ids sync_bool = BooleanProperty(False) so = BooleanProperty() new_readinglist = ObjectProperty() def __init__(self, **kwargs): super(ServerReadingListsScreen, self).__init__(**kwargs) self.app = App.get_running_app() self.fetch_data = None self.readinglist_Id = StringProperty() self.readinglist_name = "" # self.bind_to_resize() self.bind(width=self.my_width_callback) self.m_grid = "" self.main_stack = "" self.prev_button = "" self.next_button = "" self.base_url = self.app.base_url self.api_url = self.app.api_url self.api_key = self.app.config.get("General", "api_key") self.list_count = "" self.paginator_obj = ObjectProperty() self.current_page = ObjectProperty() self.list_loaded = BooleanProperty() self.page_number = 1 self.list_loaded = False self.comic_thumb_height = 240 self.comic_thumb_width = 156 self.file_download = True self.num_file_done = 0 self.max_books_page = self.app.max_books_page self.please_wait_dialog = None self.dialog_load_comic_data = None def callback_for_menu_items(self, *args): pass def setup_screen(self): self.api_key = self.app.config.get("General", "api_key") self.api_url = self.app.api_url self.main_stack = self.ids["main_stack"] self.m_grid = self.ids["main_grid"] self.prev_button = self.ids["prev_button"] self.next_button = self.ids["next_button"] def on_pre_enter(self, *args): self.app.show_action_bar() return super().on_pre_enter(*args) def on_leave(self, *args): self.app.list_previous_screens.append(self.name) return super().on_leave(*args) def my_width_callback(self, obj, value): for key, val in self.ids.items(): if key == "main_grid": c = val c.cols = (Window.width - 10) // self.comic_thumb_width def page_turn(self, c_id, new_UserLastPageRead): grid = self.m_grid for child in grid.children: if child.comic_obj.Id == c_id: if new_UserLastPageRead == 0: child.percent_read = 0 else: child.percent_read = round( new_UserLastPageRead / (child.comic_obj.PageCount - 1) * 100) child.page_count_text = f"{child.percent_read}%" def file_sync_update(self, c_id, state): grid = self.m_grid for child in grid.children: if child.comic_obj.Id == c_id: child.has_localfile = state def collect_readinglist_data( self, readinglist_name="", readinglist_Id="", mode="From Server", current_page_num=1, *largs, ): async def collect_readinglist_data(): self.readinglist_name = readinglist_name self.app.set_screen(self.readinglist_name + " Page 1") self.reading_list_title = self.readinglist_name + " Page 1" self.readinglist_Id = readinglist_Id self.page_number = current_page_num self.mode = mode if self.mode == "From Server": self.fetch_data = ComicServerConn() lsit_count_url = "{}/Lists/{}/Comics/".format( self.api_url, readinglist_Id) # self.fetch_data.get_list_count(lsit_count_url,self) self.fetch_data.get_server_data(lsit_count_url, self) elif self.mode == "From DataBase": self.got_db_data() asynckivy.start(collect_readinglist_data()) def get_page(self, instance): page_num = instance.page_num self.app.set_screen(self.readinglist_name + f" Page {page_num}") self.reading_list_title = self.readinglist_name + f" Page {page_num}" page = self.paginator_obj.page(page_num) self.current_page = page if page.has_next(): self.next_button.opacity = 1 self.next_button.disabled = False self.next_button.page_num = page.next_page_number() else: self.next_button.opacity = 0 self.next_button.disabled = True self.next_button.page_num = "" if page.has_previous(): self.prev_button.opacity = 1 self.prev_button.disabled = False self.prev_button.page_num = page.previous_page_number() else: self.prev_button.opacity = 0 self.prev_button.disabled = True self.prev_button.page_num = "" self.build_page(page.object_list) def build_page(self, object_lsit): async def _build_page(): grid = self.m_grid grid.clear_widgets() for comic in object_lsit: await asynckivy.sleep(0) c = ReadingListComicImage(comic_obj=comic) c.lines = 2 c.readinglist_obj = self.new_readinglist c.paginator_obj = self.paginator_obj y = self.comic_thumb_height thumb_filename = f"{comic.Id}.jpg" id_folder = self.app.store_dir my_thumb_dir = os.path.join(id_folder, "comic_thumbs") t_file = os.path.join(my_thumb_dir, thumb_filename) if os.path.isfile(t_file): c_image_source = t_file else: part_url = f"/Comics/{comic.Id}/Pages/0?" part_api = "&apiKey={}&height={}".format( self.api_key, round(dp(y))) c_image_source = f"{self.api_url}{part_url}{part_api}" asynckivy.start(save_thumb(comic.Id, c_image_source)) c.source = c_image_source c.PageCount = comic.PageCount c.pag_pagenum = self.current_page.number grid.add_widget(c) grid.cols = (Window.width - 10) // self.comic_thumb_width self.dynamic_ids[id] = c self.ids.page_count.text = "Page #\n{} of {}".format( self.current_page.number, self.paginator_obj.num_pages()) self.loading_done = True asynckivy.start(_build_page()) def refresh_callback(self, *args): """A method that updates the state of reading list""" def __refresh_callback(interval): self.ids.main_grid.clear_widgets() self.collect_readinglist_data( self.readinglist_name, self.readinglist_Id, current_page_num=self.page_number, mode="From DataBase", ) # self.build_page(page.object_list) # self.ids.main_scroll.refresh_done() self.tick = 0 Clock.schedule_once(__refresh_callback, 1) def got_db_data(self): """ used if rl data is already stored in db. """ async def _do_readinglist(): self.new_readinglist = ComicReadingList( name=self.readinglist_name, data="db_data", slug=self.readinglist_Id, ) await asynckivy.sleep(0) self.so = self.new_readinglist.sw_syn_this_active self.setup_options() new_readinglist_reversed = self.new_readinglist.comics self.paginator_obj = Paginator(new_readinglist_reversed, self.max_books_page) page = self.paginator_obj.page(self.page_number) self.current_page = page if page.has_next(): self.next_button.opacity = 1 self.next_button.disabled = False self.next_button.page_num = page.next_page_number() else: self.next_button.opacity = 0 self.next_button.disabled = True self.next_button.page_num = "" if page.has_previous(): self.prev_button.opacity = 1 self.prev_button.disabled = False self.prev_button.page_num = page.previous_page_number() else: self.prev_button.opacity = 0 self.prev_button.disabled = True self.prev_button.page_num = "" self.build_page(page.object_list) self.list_loaded = True asynckivy.start(_do_readinglist()) def got_json(self, req, results): print("Start got_json") async def _got_json(): print("Start _got_json") self.new_readinglist = ComicReadingList( name=self.readinglist_name, data=results, slug=self.readinglist_Id, ) totalCount = self.new_readinglist.totalCount i = 1 for item in self.new_readinglist.comic_json: await asynckivy.sleep(0) str_name = "{} #{}".format(item["Series"], item["Number"]) self.dialog_load_comic_data.name_kv_file = str_name self.dialog_load_comic_data.percent = str(i * 100 // int(totalCount)) comic_index = self.new_readinglist.comic_json.index(item) new_comic = ComicBook( item, readlist_obj=self.new_readinglist, comic_index=comic_index, ) self.new_readinglist.add_comic(new_comic) i += 1 print("End for item in self.new_readinglist.comic_json:") self.setup_options() new_readinglist_reversed = self.new_readinglist.comics[::-1] self.paginator_obj = Paginator(new_readinglist_reversed, self.max_books_page) page = self.paginator_obj.page(self.page_number) self.current_page = page if page.has_next(): self.next_button.opacity = 1 self.next_button.disabled = False self.next_button.page_num = page.next_page_number() else: self.next_button.opacity = 0 self.next_button.disabled = True self.next_button.page_num = "" if page.has_previous(): self.prev_button.opacity = 1 self.prev_button.disabled = False self.prev_button.page_num = page.previous_page_number() else: self.prev_button.opacity = 0 self.prev_button.disabled = True self.prev_button.page_num = "" self.build_page(page.object_list) self.list_loaded = True self.dialog_load_comic_data.dismiss() self.dialog_load_comic_data = DialogLoadKvFiles() self.dialog_load_comic_data.open() asynckivy.start(_got_json()) def show_please_wait_dialog(self): def __callback_for_please_wait_dialog(*args): pass self.please_wait_dialog = MDDialog( title="No ReadingList loaded.", size_hint=(0.8, 0.4), text_button_ok="Ok", text=f"No ReadingList loaded.", events_callback=__callback_for_please_wait_dialog, ) self.please_wait_dialog.open() def setup_options(self): self.sync_options = SyncOptionsPopup( size_hint=(0.76, 0.76), cb_limit_active=self.new_readinglist.cb_limit_active, limit_num_text=str(self.new_readinglist.limit_num), cb_only_read_active=self.new_readinglist.cb_only_read_active, cb_purge_active=self.new_readinglist.cb_purge_active, # noqa cb_optimize_size_active=self.new_readinglist. cb_optimize_size_active, # noqa sw_syn_this_active=bool(self.new_readinglist.sw_syn_this_active), ) self.sync_options.ids.limit_num.bind( on_text_validate=self.sync_options.check_input, focus=self.sync_options.check_input, ) self.sync_options.title = self.new_readinglist.name def open_sync_options(self): if self.sync_options.ids.sw_syn_this.active is True: self.sync_options.ids.syn_on_off_label.text = f"" self.sync_options.ids.syn_on_off_label.theme_text_color = "Primary" self.sync_options.open() def sync_readinglist(self): if self.sync_options.ids.sw_syn_this.active is False: self.sync_options.ids.syn_on_off_label.text = f"Sync Not Turned On" self.open_sync_options() elif self.sync_options.ids.sw_syn_this.active is True: toast(f"Starting sync of {self.new_readinglist.name}") self.new_readinglist.do_sync()