From c10399966e39f53fce6309d593e7493072d768e0 Mon Sep 17 00:00:00 2001 From: chrisism Date: Tue, 14 Feb 2023 19:49:01 +0100 Subject: [PATCH 1/8] Fixed query naming --- resources/lib/queries.py | 42 +++++++++++++++++------------------ resources/lib/repositories.py | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/resources/lib/queries.py b/resources/lib/queries.py index 5635220f..753caffa 100644 --- a/resources/lib/queries.py +++ b/resources/lib/queries.py @@ -1,11 +1,11 @@ # Shared Queries -INSERT_METADATA = "INSERT INTO metadata (id,year,genre,developer,rating,plot,assets_path,finished) VALUES (?,?,?,?,?,?,?,?)" -INSERT_ASSET = "INSERT INTO assets (id, filepath, asset_type) VALUES (?,?,?)" -INSERT_ASSET_PATH = "INSERT INTO assetpaths (id, path, asset_type) VALUES (?,?,?)" -UPDATE_METADATA = "UPDATE metadata SET year=?, genre=?, developer=?, rating=?, plot=?, assets_path=?, finished=? WHERE id=?" -UPDATE_ASSET = "UPDATE assets SET filepath = ?, asset_type = ? WHERE id = ?" -UPDATE_ASSET_PATH = "UPDATE assetpaths SET path = ?, asset_type = ? WHERE id = ?" +INSERT_METADATA = "INSERT INTO metadata (id,year,genre,developer,rating,plot,assets_path,finished) VALUES (?,?,?,?,?,?,?,?)" +INSERT_ASSET = "INSERT INTO assets (id, filepath, asset_type) VALUES (?,?,?)" +INSERT_ASSET_PATH = "INSERT INTO assetpaths (id, path, asset_type) VALUES (?,?,?)" +UPDATE_METADATA = "UPDATE metadata SET year=?, genre=?, developer=?, rating=?, plot=?, assets_path=?, finished=? WHERE id=?" +UPDATE_ASSET = "UPDATE assets SET filepath = ?, asset_type = ? WHERE id = ?" +UPDATE_ASSET_PATH = "UPDATE assetpaths SET path = ?, asset_type = ? WHERE id = ?" # CATEGORIES SELECT_CATEGORY = "SELECT * FROM vw_categories WHERE id = ?" @@ -42,21 +42,21 @@ # # ROMCollectionRepository -> ROM Sets from SQLite DB # -COUNT_ROMCOLLECTIONS = "SELECT COUNT(*) as count FROM vw_romcollections" -SELECT_ROMCOLLECTION = "SELECT * FROM vw_romcollections WHERE id = ?" -SELECT_ROMCOLLECTIONS = "SELECT * FROM vw_romcollections ORDER BY m_name" -SELECT_ROOT_ROMCOLLECTIONS = "SELECT * FROM vw_romcollections WHERE parent_id IS NULL ORDER BY m_name" -SELECT_ROMCOLLECTIONS_BY_PARENT = "SELECT * FROM vw_romcollections WHERE parent_id = ? ORDER BY m_name" -SELECT_ROMCOLLECTIONS_BY_ROM = "SELECT rs.* FROM vw_romcollections AS rs INNER JOIN roms_in_romcollection AS rr ON rr.romcollection_id = rs.id WHERE rr.rom_id = ?" - -SELECT_VCOLLECTION_TITLES = "SELECT DISTINCT(SUBSTR(UPPER(m_name), 1,1)) AS option_value FROM vw_roms" -SELECT_VCOLLECTION_GENRES = "SELECT DISTINCT(m_genre) AS option_value FROM vw_roms" -SELECT_VCOLLECTION_DEVELOPER = "SELECT DISTINCT(m_developer) AS option_value FROM vw_roms" -SELECT_VCOLLECTION_ESRB = "SELECT DISTINCT(m_esrb) AS option_value FROM vw_roms" -SELECT_VCOLLECTION_PEGI = "SELECT DISTINCT(m_pegi) AS option_value FROM vw_roms" -SELECT_VCOLLECTION_YEAR = "SELECT DISTINCT(m_year) AS option_value FROM vw_roms" -SELECT_VCOLLECTION_NPLAYERS = "SELECT DISTINCT(m_nplayers) AS option_value FROM vw_roms" -SELECT_VCOLLECTION_RATING = "SELECT DISTINCT(m_rating) AS option_value FROM vw_roms" +COUNT_ROMCOLLECTIONS = "SELECT COUNT(*) as count FROM vw_romcollections" +SELECT_ROMCOLLECTION = "SELECT * FROM vw_romcollections WHERE id = ?" +SELECT_ROMCOLLECTIONS = "SELECT * FROM vw_romcollections ORDER BY m_name" +SELECT_ROOT_ROMCOLLECTIONS = "SELECT * FROM vw_romcollections WHERE parent_id IS NULL ORDER BY m_name" +SELECT_ROMCOLLECTIONS_BY_PARENT = "SELECT * FROM vw_romcollections WHERE parent_id = ? ORDER BY m_name" +SELECT_ROMCOLLECTIONS_BY_ROM = "SELECT rs.* FROM vw_romcollections AS rs INNER JOIN roms_in_romcollection AS rr ON rr.romcollection_id = rs.id WHERE rr.rom_id = ?" + +SELECT_VCOLLECTION_TITLES = "SELECT DISTINCT(SUBSTR(UPPER(m_name), 1,1)) AS option_value FROM vw_roms" +SELECT_VCOLLECTION_GENRES = "SELECT DISTINCT(m_genre) AS option_value FROM vw_roms" +SELECT_VCOLLECTION_DEVELOPER = "SELECT DISTINCT(m_developer) AS option_value FROM vw_roms" +SELECT_VCOLLECTION_ESRB = "SELECT DISTINCT(m_esrb) AS option_value FROM vw_roms" +SELECT_VCOLLECTION_PEGI = "SELECT DISTINCT(m_pegi) AS option_value FROM vw_roms" +SELECT_VCOLLECTION_YEAR = "SELECT DISTINCT(m_year) AS option_value FROM vw_roms" +SELECT_VCOLLECTION_NPLAYERS = "SELECT DISTINCT(m_nplayers) AS option_value FROM vw_roms" +SELECT_VCOLLECTION_RATING = "SELECT DISTINCT(m_rating) AS option_value FROM vw_roms" INSERT_ROMCOLLECTION = """ INSERT INTO romcollections ( diff --git a/resources/lib/repositories.py b/resources/lib/repositories.py index fc122a18..63cde2d5 100644 --- a/resources/lib/repositories.py +++ b/resources/lib/repositories.py @@ -573,7 +573,7 @@ def delete_category(self, category_id: str): def add_rom_to_category(self, category_id: str, rom_id: str): if category_id is None: - self._uow.execute(qry.INSERT_ROM_IN_ROOTCATEGORY, rom_id) + self._uow.execute(qry.INSERT_ROM_IN_ROOT_CATEGORY, rom_id) return self._uow.execute(qry.INSERT_ROM_IN_CATEGORY, rom_id, category_id) From c9a7684bdcf6105645bccf5886c92a064ef56526 Mon Sep 17 00:00:00 2001 From: chrisism Date: Wed, 15 Feb 2023 08:43:26 +0100 Subject: [PATCH 2/8] Rendering views with hidden items fix --- .../lib/commands/view_rendering_commands.py | 36 +++++++++++++------ resources/lib/views.py | 6 ++++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/resources/lib/commands/view_rendering_commands.py b/resources/lib/commands/view_rendering_commands.py index 48da325c..7ee7247b 100644 --- a/resources/lib/commands/view_rendering_commands.py +++ b/resources/lib/commands/view_rendering_commands.py @@ -261,14 +261,18 @@ def _render_root_view(categories_repository: CategoryRepository, romcollections_ root_items = [] for root_category in root_categories: logger.debug(f'Processing category "{root_category.get_name()}"') - root_items.append(_render_category_listitem(root_category)) + rendered_item = _render_category_listitem(root_category) + if rendered_item: + root_items.append(rendered_item) if render_sub_views: _render_category_view(root_category, categories_repository, romcollections_repository, roms_repository, views_repository, render_sub_views) for root_romcollection in root_romcollections: logger.debug(f'Processing romcollection "{root_romcollection.get_name()}"') - root_items.append(_render_romcollection_listitem(root_romcollection)) + rendered_item = _render_romcollection_listitem(root_romcollection) + if rendered_item: + root_items.append(rendered_item) if render_sub_views: collection_view_data = _render_romcollection_view(root_romcollection, roms_repository) views_repository.store_view(root_romcollection.get_id(), root_romcollection.get_type(), collection_view_data) @@ -281,7 +285,9 @@ def _render_root_view(categories_repository: CategoryRepository, romcollections_ root_vcategory = VirtualCategoryFactory.create(constants.VCATEGORY_ROOT_ID) logger.debug('Processing root virtual category') - root_items.append(_render_category_listitem(root_vcategory)) + rendered_item = _render_category_listitem(root_vcategory) + if rendered_item: + root_items.append(rendered_item) if render_sub_views: _render_category_view(root_vcategory, categories_repository, romcollections_repository, roms_repository, views_repository, render_sub_views) @@ -289,11 +295,13 @@ def _render_root_view(categories_repository: CategoryRepository, romcollections_ for vcollection_id in constants.VCOLLECTIONS: vcollection = VirtualCollectionFactory.create(vcollection_id) logger.debug(f'Processing virtual collection "{vcollection.get_name()}"') - root_items.append(_render_romcollection_listitem(vcollection)) + rendered_item = _render_romcollection_listitem(vcollection) + if rendered_item: + root_items.append(rendered_item) collection_view_data = _render_romcollection_view(vcollection, roms_repository) views_repository.store_view(vcollection.get_id(), vcollection.get_type(), collection_view_data) - logger.debug('Storing {} items in root view.'.format(len(root_items))) + logger.debug(f'Storing {len(root_items)} items in root view.') root_data['items'] = root_items views_repository.store_root_view(root_data) @@ -318,7 +326,9 @@ def _render_category_view(category_obj: Category, categories_repository: Categor if sub_category is None: continue logger.debug(f'Processing category "{sub_category.get_name()}", part of "{category_obj.get_name()}"') - view_items.append(_render_category_listitem(sub_category)) + rendered_item = _render_category_listitem(sub_category) + if rendered_item: + view_items.append(rendered_item) if render_sub_views: _render_category_view(sub_category, categories_repository, romcollections_repository, roms_repository, views_repository, render_sub_views) @@ -326,7 +336,9 @@ def _render_category_view(category_obj: Category, categories_repository: Categor for romcollection in romcollections: logger.debug(f"Processing romcollection '{romcollection.get_name()}'") try: - view_items.append(_render_romcollection_listitem(romcollection)) + rendered_item = _render_romcollection_listitem(romcollection) + if rendered_item: + view_items.append(rendered_item) except Exception: logger.exception(f"Exception while rendering list item ROM Collection '{romcollection.get_name()}'") kodi.notify_error(f"Failed to process ROM collection {romcollection.get_name()}") @@ -377,8 +389,9 @@ def _render_romcollection_view(romcollection_obj: ROMCollection, roms_repository def _render_category_listitem(category_obj: Category) -> dict: # --- Do not render row if category finished --- if category_obj.is_finished() and \ - (category_obj.get_type() in constants.OBJ_VIRTUAL_TYPES or settings.getSettingAsBool('display_hide_finished')): - return + (category_obj.get_type() in constants.OBJ_VIRTUAL_TYPES or \ + settings.getSettingAsBool('display_hide_finished')): + return None category_name = category_obj.get_name() ICON_OVERLAY = 5 if category_obj.is_finished() else 4 @@ -412,8 +425,9 @@ def _render_category_listitem(category_obj: Category) -> dict: def _render_romcollection_listitem(romcollection_obj: ROMCollection) -> dict: # --- Do not render row if romcollection finished --- if romcollection_obj.is_finished() and \ - (romcollection_obj.get_type() in constants.OBJ_VIRTUAL_TYPES or settings.getSettingAsBool('display_hide_finished')): - return + (romcollection_obj.get_type() in constants.OBJ_VIRTUAL_TYPES or \ + settings.getSettingAsBool('display_hide_finished')): + return None romcollection_name = romcollection_obj.get_name() ICON_OVERLAY = 5 if romcollection_obj.is_finished() else 4 diff --git a/resources/lib/views.py b/resources/lib/views.py index 4922fe3d..a1e37da1 100644 --- a/resources/lib/views.py +++ b/resources/lib/views.py @@ -292,6 +292,8 @@ def _render_list_items(container_data:dict, container_context_items = [], filter xbmcplugin.setProperty(router.handle, property, value) for list_item_data in container_data['items']: + if list_item_data is None: + continue if filter_method and not filter_method.is_valid(list_item_data): continue @@ -306,6 +308,8 @@ def _render_list_items(container_data:dict, container_context_items = [], filter xbmcplugin.addDirectoryItem(handle = router.handle, url = url_str, listitem = list_item, isFolder = folder_flag) def _render_list_item(list_item_data: dict) -> xbmcgui.ListItem: + if list_item_data is None: + return None name = list_item_data['name'] name2 = list_item_data['name2'] if 'name2' in list_item_data else "" item_type = list_item_data['type'] @@ -363,6 +367,8 @@ def _render_items(self): self.setContainerProperty(property, value) for list_item_data in self.container_data['items']: + if list_item_data is None: + continue list_item = _render_list_item(list_item_data) cntrl.addItem(list_item) except RuntimeError as error: From a6b5efe89419764a7fead2b892efad0611b6b74a Mon Sep 17 00:00:00 2001 From: chrisism Date: Wed, 15 Feb 2023 09:13:16 +0100 Subject: [PATCH 3/8] Added action to settings --- resources/language/resource.language.en_gb/strings.po | 4 ++++ resources/lib/viewqueries.py | 2 +- resources/settings.xml | 10 ++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index 4fa20038..8dce6cc6 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -292,6 +292,10 @@ msgctxt "#40855" msgid "Scrape ROM" msgstr "" +msgctxt "#40856" +msgid "Rebuild all views" +msgstr "" + ############################ # Scraping settings ############################ diff --git a/resources/lib/viewqueries.py b/resources/lib/viewqueries.py index 4693add3..2e04317f 100644 --- a/resources/lib/viewqueries.py +++ b/resources/lib/viewqueries.py @@ -572,7 +572,7 @@ def qry_container_context_menu_items(container_data) -> typing.List[typing.Tuple commands.append(('Rebuild {} view'.format(container_name), _context_menu_url_for('execute/command/render_vcategory_view',{'vcategory_id':container_parentid}))) - commands.append(('Rebuild all views', _context_menu_url_for('execute/command/render_views'))) + commands.append((kodi.translate(40856), _context_menu_url_for('execute/command/render_views'))) commands.append(('Open Kodi file manager', 'ActivateWindow(filemanager)')) commands.append(('AKL addon settings', 'Addon.OpenSettings({0})'.format(globals.addon_id))) diff --git a/resources/settings.xml b/resources/settings.xml index ff30e321..5b2db519 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -305,6 +305,16 @@ 40612 + + 1 + + + true + + + RunPlugin(plugin://plugin.program.akl/execute/command/render_views) + + From 7d7961b99abc1b6f395b01c5b138534326571c59 Mon Sep 17 00:00:00 2001 From: chrisism Date: Sat, 25 Feb 2023 14:18:35 +0100 Subject: [PATCH 4/8] Fix for import local asset path issue --- resources/lib/domain.py | 3 ++- resources/lib/editors.py | 58 +++++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/resources/lib/domain.py b/resources/lib/domain.py index 627aa3cd..146f904c 100644 --- a/resources/lib/domain.py +++ b/resources/lib/domain.py @@ -728,7 +728,8 @@ def get_asset_paths(self) -> typing.List[AssetPath]: return list(self.asset_paths.values()) def get_asset_path(self, asset_info: AssetInfo, fallback_to_root = True) -> io.FileName: - if not asset_info: return None + if not asset_info: + return None if asset_info.id in self.asset_paths: return self.asset_paths[asset_info.id].get_path_FN() diff --git a/resources/lib/editors.py b/resources/lib/editors.py index 323dfe3d..4c1fb871 100644 --- a/resources/lib/editors.py +++ b/resources/lib/editors.py @@ -219,9 +219,6 @@ def edit_object_assets(obj_instance:MetaDataItemABC, preselected_asset = None) - # def edit_asset(obj_instance: MetaDataItemABC, asset_info: AssetInfo) -> str: # --- Get asset object information --- - # Select/Import require: object_name, A, asset_path_noext - # Scraper additionaly requires: current_asset_path, scraper_obj, platform, rom_base_noext - asset_directory = obj_instance.get_assets_root_path() if not asset_directory: if kodi.dialog_yesno("No local assets path configured. Configure now?\n Else we will use addon default directories."): @@ -246,36 +243,36 @@ def edit_asset(obj_instance: MetaDataItemABC, asset_info: AssetInfo) -> str: 'This is a bug, please report it.') return None - asset_path_noext = g_assetFactory.assets_get_path_noext_SUFIX(asset_info.id, asset_directory, - obj_instance.get_name(), obj_instance.get_id()) - logger.info('edit_asset() Editing {} {}'.format(obj_instance.get_object_name(), asset_info.name)) - logger.info('edit_asset() Object ID {}'.format(obj_instance.get_id())) - logger.debug('edit_asset() asset_directory "{}"'.format(asset_directory.getPath())) - logger.debug('edit_asset() asset_path_noext "{}"'.format(asset_path_noext.getPath())) + asset_path_noext = asset_directory.pjoin(asset_info.path_key, isdir=True).pjoin(obj_instance.get_object_name) + + logger.info(f'edit_asset() Editing {obj_instance.get_object_name()} {asset_info.name}') + logger.info(f'edit_asset() Object ID {obj_instance.get_id()}') + logger.debug(f'edit_asset() asset_directory "{asset_directory.getPath()}"') + logger.debug(f'edit_asset() asset_path_noext "{asset_path_noext.getPath()}"') if not asset_directory.exists(): - logger.error('Directory not found "{0}"'.format(asset_directory.getPath())) + logger.error(f'Directory not found "{asset_directory.getPath()}"') kodi.dialog_OK('Directory to store artwork not found. ' 'Configure it before you can edit artwork.') return None - dialog_title = 'Change {0} {1}'.format(obj_instance.get_name(), asset_info.name) + dialog_title = f'Change {obj_instance.get_name()} {asset_info.name}' # --- Show image editing options --- options = collections.OrderedDict() - options['LINK_LOCAL'] = 'Link to local {0} image'.format(asset_info.name) - options['IMPORT_LOCAL'] = 'Import local {0} (copy and rename)'.format(asset_info.name) + options['LINK_LOCAL'] = f'Link to local {asset_info.name} image' + options['IMPORT_LOCAL'] = f'Import local {asset_info.name} (copy and rename)' options['UNSET'] = 'Unset artwork/asset' if obj_instance.get_assets_kind() == constants.KIND_ASSET_ROM: - options['SCRAPE_ASSET'] = 'Scrape {}'.format(asset_info.name) + options['SCRAPE_ASSET'] = f'Scrape {asset_info.name}' selected_option = kodi.OrdDictionaryDialog().select(dialog_title, options) # >> User canceled select box - if selected_option is None: return None - + if selected_option is None: + return None # --- Manual scrape asset --- - elif selected_option == 'SCRAPE': return selected_option - + elif selected_option == 'SCRAPE': + return selected_option # --- Link to a local image --- if selected_option == 'LINK_LOCAL': current_image_file = obj_instance.get_asset_FN(asset_info) @@ -286,19 +283,23 @@ def edit_asset(obj_instance: MetaDataItemABC, asset_info: AssetInfo) -> str: else: current_image_dir = io.FileName(current_image_file.getDir(), isdir = True) - if current_image_dir is None: current_image_dir = io.FileName('/') + if current_image_dir is None: + current_image_dir = io.FileName('/') - logger.debug('edit_asset() Asset initial dir "{0}"'.format(current_image_dir.getPath())) + logger.debug(f'edit_asset() Asset initial dir "{current_image_dir.getPath()}"') title_str = 'Select {0} {1}'.format(obj_instance.get_object_name(), asset_info.name) ext_list = asset_info.exts_dialog if asset_info.id == constants.ASSET_MANUAL_ID or asset_info.id == constants.ASSET_TRAILER_ID: new_asset_file = kodi.browse(text=title_str, mask=ext_list, preselected_path=current_image_dir.getPath()) else: new_asset_file = kodi.browse(type=2, text=title_str, mask=ext_list, preselected_path=current_image_dir.getPath()) - if not new_asset_file or new_asset_file == current_image_dir.getPath(): return None + + if not new_asset_file or new_asset_file == current_image_dir.getPath(): + return None # --- Check if image exists --- new_asset_FN = io.FileName(new_asset_file) - if not new_asset_FN.exists(): return None + if not new_asset_FN.exists(): + return None # --- Update object --- obj_instance.set_asset(asset_info, new_asset_FN) @@ -329,16 +330,17 @@ def edit_asset(obj_instance: MetaDataItemABC, asset_info: AssetInfo) -> str: else: new_asset_file_str = kodi.browse(type=2, text=title_str, mask=ext_list, preselected_path=current_image_dir.getPath()) - if not new_asset_file_str: return None + if not new_asset_file_str: + return None # >> Determine image extension and dest filename. Check for errors. new_asset_file = io.FileName(new_asset_file_str) dest_asset_file = asset_path_noext.append(new_asset_file.getExt()) - logger.debug(f'm_gui_edit_asset() new_asset_file "{new_asset_file.getPath()}"') - logger.debug(f'm_gui_edit_asset() new_asset_file ext "{new_asset_file.getExt()}"') - logger.debug(f'm_gui_edit_asset() dest_asset_file "{dest_asset_file.getPath()}"') + logger.debug(f'edit_asset() new_asset_file "{new_asset_file.getPath()}"') + logger.debug(f'edit_asset() new_asset_file ext "{new_asset_file.getExt()}"') + logger.debug(f'edit_asset() dest_asset_file "{dest_asset_file.getPath()}"') if new_asset_file.getPath() == dest_asset_file.getPath(): - logger.info('m_gui_edit_asset() new_asset_file and dest_asset_file are the same. Returning.') + logger.info('edit_asset() new_asset_file and dest_asset_file are the same. Returning.') kodi.notify_warn('new_asset_file and dest_asset_file are the same. Returning') return None @@ -352,7 +354,7 @@ def edit_asset(obj_instance: MetaDataItemABC, asset_info: AssetInfo) -> str: # NOTE deleting the destination image before copying does not work to force a cache # update. # if dest_asset_file.exists(): - # logger.debug('m_gui_edit_asset() Deleting image "{0}"'.format(dest_asset_file.getPath())) + # logger.debug('edit_asset() Deleting image "{0}"'.format(dest_asset_file.getPath())) # dest_asset_file.unlink() # --- Copy image file --- From 8a0a11b3d6ae8366c9799c9a50c1b62f91301729 Mon Sep 17 00:00:00 2001 From: chrisism Date: Sat, 25 Feb 2023 15:53:47 +0100 Subject: [PATCH 5/8] method fix --- resources/lib/editors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lib/editors.py b/resources/lib/editors.py index 4c1fb871..9b470e76 100644 --- a/resources/lib/editors.py +++ b/resources/lib/editors.py @@ -243,7 +243,7 @@ def edit_asset(obj_instance: MetaDataItemABC, asset_info: AssetInfo) -> str: 'This is a bug, please report it.') return None - asset_path_noext = asset_directory.pjoin(asset_info.path_key, isdir=True).pjoin(obj_instance.get_object_name) + asset_path_noext = asset_directory.pjoin(asset_info.path_key, isdir=True).pjoin(obj_instance.get_object_name()) logger.info(f'edit_asset() Editing {obj_instance.get_object_name()} {asset_info.name}') logger.info(f'edit_asset() Object ID {obj_instance.get_id()}') From 701174e748dee8121ead64a4717ab3c21aa8777c Mon Sep 17 00:00:00 2001 From: chrisism Date: Sat, 25 Feb 2023 17:04:46 +0100 Subject: [PATCH 6/8] assets_directory fix --- resources/lib/domain.py | 5 ++-- resources/lib/editors.py | 52 ++++++++++++++++++++++------------------ 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/resources/lib/domain.py b/resources/lib/domain.py index 146f904c..e42e0358 100644 --- a/resources/lib/domain.py +++ b/resources/lib/domain.py @@ -559,7 +559,8 @@ def __init__(self, # Core functions # -------------------------------------------------------------------------------------------- @abc.abstractmethod - def get_object_name(self) -> str: pass + def get_object_name(self) -> str: + pass @abc.abstractmethod def get_assets_kind(self) -> int: @@ -569,7 +570,7 @@ def get_assets_kind(self) -> int: def get_type(self) -> str: pass - # --- Metadata -------------------------------------------------------------------------------- + # --- Metadata -------------------------------------------------------------------------------- def get_name(self): return self.entity_data['m_name'] if 'm_name' in self.entity_data else 'Unknown' diff --git a/resources/lib/editors.py b/resources/lib/editors.py index 9b470e76..64b7392c 100644 --- a/resources/lib/editors.py +++ b/resources/lib/editors.py @@ -25,7 +25,7 @@ import xbmcgui -from akl.utils import kodi, io +from akl.utils import kodi, io, text from akl import constants, settings from resources.lib.domain import MetaDataItemABC, AssetInfo, g_assetFactory @@ -219,38 +219,38 @@ def edit_object_assets(obj_instance:MetaDataItemABC, preselected_asset = None) - # def edit_asset(obj_instance: MetaDataItemABC, asset_info: AssetInfo) -> str: # --- Get asset object information --- - asset_directory = obj_instance.get_assets_root_path() - if not asset_directory: + assets_directory = obj_instance.get_assets_root_path() + if not assets_directory: if kodi.dialog_yesno("No local assets path configured. Configure now?\n Else we will use addon default directories."): path_str = kodi.dialog_get_directory(f"Assets root path for entry '{obj_instance.get_name()}'") - asset_directory = io.FileName(path_str, True) - obj_instance.set_assets_root_path(asset_directory, None, create_default_subdirectories=True) + assets_directory = io.FileName(path_str, True) + obj_instance.set_assets_root_path(assets_directory, None, create_default_subdirectories=True) else: if obj_instance.get_assets_kind() == constants.KIND_ASSET_CATEGORY: - asset_directory = io.FileName(settings.getSetting('categories_asset_dir'), isdir = True) - obj_instance.set_assets_root_path(asset_directory, None, create_default_subdirectories=True) + assets_directory = io.FileName(settings.getSetting('categories_asset_dir'), isdir = True) + obj_instance.set_assets_root_path(assets_directory, None, create_default_subdirectories=True) elif obj_instance.get_assets_kind() == constants.KIND_ASSET_COLLECTION: - asset_directory = io.FileName(settings.getSetting('collections_asset_dir'), isdir = True) - obj_instance.set_assets_root_path(asset_directory, None, create_default_subdirectories=True) + assets_directory = io.FileName(settings.getSetting('collections_asset_dir'), isdir = True) + obj_instance.set_assets_root_path(assets_directory, None, create_default_subdirectories=True) elif obj_instance.get_assets_kind() == constants.KIND_ASSET_LAUNCHER: - asset_directory = io.FileName(settings.getSetting('launchers_asset_dir'), isdir = True) - obj_instance.set_assets_root_path(asset_directory, None, create_default_subdirectories=True) + assets_directory = io.FileName(settings.getSetting('launchers_asset_dir'), isdir = True) + obj_instance.set_assets_root_path(assets_directory, None, create_default_subdirectories=True) elif obj_instance.get_assets_kind() == constants.KIND_ASSET_ROM: - asset_directory = io.FileName(settings.getSetting('launchers_asset_dir'), isdir = True) - obj_instance.set_assets_root_path(asset_directory, None, create_default_subdirectories=True) + assets_directory = io.FileName(settings.getSetting('launchers_asset_dir'), isdir = True) + obj_instance.set_assets_root_path(assets_directory, None, create_default_subdirectories=True) else: kodi.dialog_OK('Unknown obj_instance.get_assets_kind() {}. '.format(obj_instance.get_assets_kind()) + 'This is a bug, please report it.') return None - - asset_path_noext = asset_directory.pjoin(asset_info.path_key, isdir=True).pjoin(obj_instance.get_object_name()) - + + asset_type_directory = obj_instance.get_asset_path(asset_info, False) + logger.info(f'edit_asset() Editing {obj_instance.get_object_name()} {asset_info.name}') logger.info(f'edit_asset() Object ID {obj_instance.get_id()}') - logger.debug(f'edit_asset() asset_directory "{asset_directory.getPath()}"') - logger.debug(f'edit_asset() asset_path_noext "{asset_path_noext.getPath()}"') - if not asset_directory.exists(): - logger.error(f'Directory not found "{asset_directory.getPath()}"') + logger.debug(f'edit_asset() assets_directory "{assets_directory.getPath()}"') + logger.debug(f'edit_asset() asset_type_directory "{asset_type_directory.getPath()}"') + if not assets_directory.exists(): + logger.error(f'Directory not found "{assets_directory.getPath()}"') kodi.dialog_OK('Directory to store artwork not found. ' 'Configure it before you can edit artwork.') return None @@ -270,15 +270,17 @@ def edit_asset(obj_instance: MetaDataItemABC, asset_info: AssetInfo) -> str: # >> User canceled select box if selected_option is None: return None + # --- Manual scrape asset --- - elif selected_option == 'SCRAPE': + if selected_option == 'SCRAPE': return selected_option + # --- Link to a local image --- if selected_option == 'LINK_LOCAL': current_image_file = obj_instance.get_asset_FN(asset_info) if current_image_file is None: current_image_dir = obj_instance.get_asset_path(asset_info) - if current_image_dir is None or not asset_directory.exists(): + if current_image_dir is None or not assets_directory.exists(): current_image_dir = obj_instance.get_assets_root_path() else: current_image_dir = io.FileName(current_image_file.getDir(), isdir = True) @@ -319,8 +321,9 @@ def edit_asset(obj_instance: MetaDataItemABC, asset_info: AssetInfo) -> str: # --- Import an image --- # >> Copy and rename a local image into asset directory elif selected_option == 'IMPORT_LOCAL': - current_image_dir = obj_instance.get_asset_path(asset_info, fallback_to_root=False) + current_image_dir = asset_type_directory if not current_image_dir: + logger.info("No local asset type path configured. Reverting to root.") current_image_dir = obj_instance.get_assets_root_path() title_str = f'Select {obj_instance.get_object_name()} {asset_info.name}' @@ -335,6 +338,9 @@ def edit_asset(obj_instance: MetaDataItemABC, asset_info: AssetInfo) -> str: # >> Determine image extension and dest filename. Check for errors. new_asset_file = io.FileName(new_asset_file_str) + obj_identifier = text.str_to_filename_str(obj_instance.get_name()) + + asset_path_noext = asset_type_directory.pjoin(obj_identifier) dest_asset_file = asset_path_noext.append(new_asset_file.getExt()) logger.debug(f'edit_asset() new_asset_file "{new_asset_file.getPath()}"') logger.debug(f'edit_asset() new_asset_file ext "{new_asset_file.getExt()}"') From b71633ed03c0cb20f68c29d8c8e0e1342047fb76 Mon Sep 17 00:00:00 2001 From: chrisism Date: Wed, 1 Mar 2023 10:31:57 +0100 Subject: [PATCH 7/8] Fixes for rendering category --- resources/lib/commands/rom_commands.py | 23 +++++++++++++++++++ .../commands/romcollection_roms_commands.py | 7 ------ resources/lib/domain.py | 9 +++++--- resources/lib/editors.py | 13 ++++++----- resources/lib/viewqueries.py | 2 +- 5 files changed, 37 insertions(+), 17 deletions(-) diff --git a/resources/lib/commands/rom_commands.py b/resources/lib/commands/rom_commands.py index 261c6a23..1b327bf3 100644 --- a/resources/lib/commands/rom_commands.py +++ b/resources/lib/commands/rom_commands.py @@ -54,6 +54,7 @@ def cmd_edit_rom(args): options = collections.OrderedDict() options['ROM_EDIT_METADATA'] = f'{kodi.translate(40853)} ...' options['ROM_EDIT_ASSETS'] = f'{kodi.translate(40854)} ...' + # options['ROM_EDIT_DEFAULT_ASSETS'] = 'Choose default Assets/Artwork ...' options['EDIT_ROM_STATUS'] = f'ROM status: {rom.get_finished_str()}' if rom.has_launchers(): options['EDIT_ROM_LAUNCHERS'] = 'Manage associated launchers' @@ -161,6 +162,28 @@ def cmd_rom_assets(args): AppMediator.sync_cmd('ROM_EDIT_ASSETS', {'rom_id': rom_id, 'selected_asset': asset.id}) +@AppMediator.register('ROM_EDIT_DEFAULT_ASSETS') +def cmd_rom_edit_default_assets(args): + rom_id:str = args['rom_id'] if 'rom_id' in args else None + preselected_option = args['selected_asset'] if 'selected_asset' in args else None + + uow = UnitOfWork(globals.g_PATHS.DATABASE_FILE_PATH) + with uow: + repository = ROMsRepository(uow) + rom = repository.find_rom(rom_id) + + selected_asset_to_edit = editors.edit_object_default_assets(rom, preselected_option) + if selected_asset_to_edit is None: + args["selected_asset"] = None + AppMediator.sync_cmd('EDIT_ROM', args) + return + + if editors.edit_default_asset(rom, selected_asset_to_edit): + repository.update_rom(rom) + uow.commit() + + AppMediator.sync_cmd('ROM_EDIT_DEFAULT_ASSETS', {'rom_id': rom.get_id(), 'selected_asset': selected_asset_to_edit.id}) + # # Remove ROMCollection # diff --git a/resources/lib/commands/romcollection_roms_commands.py b/resources/lib/commands/romcollection_roms_commands.py index 5c1c1089..b80a6e45 100644 --- a/resources/lib/commands/romcollection_roms_commands.py +++ b/resources/lib/commands/romcollection_roms_commands.py @@ -89,13 +89,6 @@ def cmd_manage_roms(args): def cmd_set_roms_default_artwork(args): romcollection_id:str = args['romcollection_id'] if 'romcollection_id' in args else None - # if not launcher.supports_launching_roms(): - # kodi.dialog_OK( - # 'm_subcommand_set_roms_default_artwork() ' + - # 'Launcher "{0}" is not a ROM launcher.'.format(launcher.__class__.__name__) + - # 'This is a bug, please report it.') - # return - uow = UnitOfWork(globals.g_PATHS.DATABASE_FILE_PATH) with uow: repository = ROMCollectionRepository(uow) diff --git a/resources/lib/domain.py b/resources/lib/domain.py index e42e0358..772dd634 100644 --- a/resources/lib/domain.py +++ b/resources/lib/domain.py @@ -778,7 +778,8 @@ def get_view_assets(self) -> typing.Dict[str,str]: value = asset.get_path() if self.is_mappable_asset(asset_info): - if asset_info.id == constants.ASSET_ICON_ID: fallback_str = self.get_default_icon() + if asset_info.id == constants.ASSET_ICON_ID: + fallback_str = self.get_default_icon() value = self.get_mapped_asset_str(asset_info, fallback=fallback_str) view_assets[asset_info.fname_infix] = value @@ -1546,9 +1547,11 @@ def copy(self): def get_asset_ids_list(self): return constants.ROM_ASSET_ID_LIST - def get_mappable_asset_ids_list(self): return constants.MAPPABLE_ROM_ASSET_ID_LIST + def get_mappable_asset_ids_list(self): + return constants.MAPPABLE_ROM_ASSET_ID_LIST - def get_default_icon(self) -> str: return 'DefaultProgram.png' + def get_default_icon(self) -> str: + return 'DefaultProgram.png' def create_dto(self) -> api.ROMObj: dto_data:dict = api.ROMObj.get_data_template() diff --git a/resources/lib/editors.py b/resources/lib/editors.py index 64b7392c..603aa4b0 100644 --- a/resources/lib/editors.py +++ b/resources/lib/editors.py @@ -430,7 +430,7 @@ def edit_object_default_assets(obj_instance: MetaDataItemABC, preselected_asset_ logger.debug('edit_object_default_assets() preselected_asset_id {0}'.format(preselected_asset_id)) pre_select_idx = 0 - dialog_title_str = 'Edit {0} default Assets/Artwork'.format(obj_instance.get_object_name()) + dialog_title_str = f'Edit {obj_instance.get_object_name()} default Assets/Artwork' # --- Build Dialog.select() list --- default_assets_list = obj_instance.get_mappable_asset_list() @@ -445,7 +445,7 @@ def edit_object_default_assets(obj_instance: MetaDataItemABC, preselected_asset_ mapped_asset_key = obj_instance.get_mapped_asset_key(default_asset_info) mapped_asset_info = g_assetFactory.get_asset_info_by_key(mapped_asset_key) mapped_asset_str = obj_instance.get_asset_str(mapped_asset_info) - label1_str = 'Choose asset for {0} (currently {1})'.format(default_asset_info.name, mapped_asset_info.name) + label1_str = f'Choose asset for {default_asset_info.name} (currently {mapped_asset_info.name})' label2_str = mapped_asset_str list_item = xbmcgui.ListItem(label = label1_str, label2 = label2_str) if mapped_asset_str: @@ -466,7 +466,7 @@ def edit_object_default_assets(obj_instance: MetaDataItemABC, preselected_asset_ selected_option = xbmcgui.Dialog().select( dialog_title_str, list = list_items, useDetails = True, preselect = pre_select_idx) - logger.debug('edit_object_default_assets() Main select() returned {0}'.format(selected_option)) + logger.debug(f'edit_object_default_assets() Main select() returned {selected_option}') if selected_option < 0: # >> Return to parent menu. logger.debug('edit_object_default_assets() Main selected NONE. Returning to parent menu.') @@ -476,11 +476,12 @@ def edit_object_default_assets(obj_instance: MetaDataItemABC, preselected_asset_ # >> The menu dialog is instantiated again so it reflects the changes just edited. logger.debug('edit_object_default_assets() Executing mappable asset select() dialog.') selected_asset_info:AssetInfo = asset_info_list[selected_option] - logger.debug('edit_object_default_assets() Main selected {0}.'.format(selected_asset_info.name)) + logger.debug(f'edit_object_default_assets() Main selected {selected_asset_info.name}.') return selected_asset_info def edit_default_asset(obj_instance: MetaDataItemABC, asset_info: AssetInfo) -> bool: - mappable_asset_list = obj_instance.get_mappable_asset_list() + selectable_asset_ids = obj_instance.get_asset_ids_list() + mappable_asset_list = g_assetFactory.get_asset_list_by_IDs(selectable_asset_ids, 'image') list_items = [] asset_info_list = [] secondary_pre_select_idx = 0 @@ -519,7 +520,7 @@ def edit_default_asset(obj_instance: MetaDataItemABC, asset_info: AssetInfo) -> return False new_selected_asset_info = asset_info_list[secondary_selected_option] - logger.debug('edit_default_asset() Mapable selected {0}.'.format(new_selected_asset_info.name)) + logger.debug(f'edit_default_asset() Mapable selected {new_selected_asset_info.name}.') obj_instance.set_mapped_asset_key(asset_info, new_selected_asset_info) kodi.notify('{0} {1} mapped to {2}'.format( obj_instance.get_object_name(), asset_info.name, new_selected_asset_info.name diff --git a/resources/lib/viewqueries.py b/resources/lib/viewqueries.py index 2e04317f..c147973c 100644 --- a/resources/lib/viewqueries.py +++ b/resources/lib/viewqueries.py @@ -559,7 +559,7 @@ def qry_container_context_menu_items(container_data) -> typing.List[typing.Tuple commands = [] if is_category: commands.append(('Rebuild {} view'.format(container_name), - _context_menu_url_for('execute/command/render_view',{'category_id':container_id}))) + _context_menu_url_for('execute/command/render_category_view',{'category_id':container_id}))) if is_romcollection: commands.append(('Search ROM in collection', _context_menu_url_for(f'/collection/{container_id}/search'))) From 6e0aaeb34409da5c4033f52d64de10e10e0bb3b5 Mon Sep 17 00:00:00 2001 From: chrisism Date: Wed, 1 Mar 2023 11:15:10 +0100 Subject: [PATCH 8/8] Updated changelog --- changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelog.md b/changelog.md index 509798f1..14b505b0 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,9 @@ ## Current - Custom skin view for View ROM - More details about addon plugins +- Fixed linking assets to wrong directory +- Fixed category rendering +- Added rebuild views option in settings dialog ## Previous - Added support for PEGI rating