Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion addon.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<requires>
<import addon="xbmc.python" version="3.0.0"/>
<import addon="script.module.routing" version="0.2.3"/>
<import addon="script.module.ael" version="0.10.6"/>
<import addon="script.module.ael" version="0.10.7"/>
</requires>
<extension point="xbmc.python.pluginsource" library="addon.py">
<provides>game</provides>
Expand Down
1 change: 1 addition & 0 deletions resources/lib/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@
import resources.lib.commands.misc_commands
import resources.lib.commands.chk_commands
import resources.lib.commands.report_commands
import resources.lib.commands.search_commands
108 changes: 108 additions & 0 deletions resources/lib/commands/search_commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
#
# Advanced Emulator Launcher: Commands (search)
#
# Copyright (c) Wintermute0110 <wintermute0110@gmail.com> / Chrisism <crizizz@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

# --- Python standard library ---
from __future__ import unicode_literals
from __future__ import division

import logging
import collections
from urllib.parse import urlencode

from ael.utils import kodi
from ael import constants

from resources.lib.commands.mediator import AppMediator

from resources.lib.repositories import ROMsRepository, UnitOfWork, ROMCollectionRepository
from resources.lib import globals

logger = logging.getLogger(__name__)

@AppMediator.register('SEARCH')
def cmd_search(args):

options = collections.OrderedDict()
options['SEARCH_BY_TITLE'] = 'By ROM Title'
options['SEARCH_BY_RELEASEYEAR'] = 'By Release Year'
options['SEARCH_BY_GENRE'] = 'By Genre'
options['SEARCH_BY_DEVELOPER'] = 'By Developer'
options['SEARCH_BY_RATING'] = 'By Rating'

selected_option = kodi.OrdDictionaryDialog().select('Search ROMs...',options)
AppMediator.sync_cmd(selected_option, args)

@AppMediator.register('SEARCH_BY_TITLE')
def cmd_search_by_title(args):
romcollection_id:str = args['romcollection_id'] if 'romcollection_id' in args else None

search_string = kodi.dialog_keyboard('Enter the ROM Title search string...')
if search_string is None: return None

params = {
'filter': constants.META_TITLE_ID,
'term': search_string
}
url = globals.router.url_for_path(f'/collection/{romcollection_id}')
kodi.update_uri(url, params)

@AppMediator.register('SEARCH_BY_GENRE')
def cmd_search_by_genre(args):
romcollection_id:str = args['romcollection_id'] if 'romcollection_id' in args else None
_apply_search_query_by_options(romcollection_id, constants.META_GENRE_ID, 'Select a Genre...')

@AppMediator.register('SEARCH_BY_RELEASEYEAR')
def cmd_search_by_year(args):
romcollection_id:str = args['romcollection_id'] if 'romcollection_id' in args else None
_apply_search_query_by_options(romcollection_id, constants.META_YEAR_ID, 'Select a Release year...')

@AppMediator.register('SEARCH_BY_DEVELOPER')
def cmd_search_by_developer(args):
romcollection_id:str = args['romcollection_id'] if 'romcollection_id' in args else None
_apply_search_query_by_options(romcollection_id, constants.META_DEVELOPER_ID, 'Select a Developer...')

@AppMediator.register('SEARCH_BY_RATING')
def cmd_search_by_rating(args):
romcollection_id:str = args['romcollection_id'] if 'romcollection_id' in args else None
_apply_search_query_by_options(romcollection_id, constants.META_RATING_ID, 'Select a Rating...')

def _apply_search_query_by_options(romcollection_id:str, filter_type:str, dialog_title: str):

search_string = ''
uow = UnitOfWork(globals.g_PATHS.DATABASE_FILE_PATH)
with uow:
repository = ROMsRepository(uow)
collection_repository = ROMCollectionRepository(uow)

romcollection = collection_repository.find_romcollection(romcollection_id)
filter_values = repository.find_all_filter_values_in_romcollection(romcollection, constants.META_YEAR_ID)

options = []
options.append('[ Not Set ]')
options.extend(filter_values)

selected_index = kodi.ListDialog().select(dialog_title, options)
if selected_index is None: return None

if selected_index == 0: search_string = 'UNDEFINED'
else: search_string = options[selected_index]

params = {
'filter': filter_type,
'term': search_string
}

url = globals.router.url_for_path(f'/collection/{romcollection_id}')
kodi.update_uri(url, params)
34 changes: 31 additions & 3 deletions resources/lib/repositories.py
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,12 @@ def _get_collections_query_by_vcategory_id(self, vcategory_id:str) -> str:
QUERY_SELECT_ROM_ASSETS_BY_SET = "SELECT ra.* FROM vw_rom_assets AS ra INNER JOIN roms_in_romcollection AS rs ON rs.rom_id = ra.rom_id AND rs.romcollection_id = ?"
QUERY_SELECT_ROM_ASSETPATHS_BY_SET = "SELECT rap.* FROM vw_rom_asset_paths AS rap INNER JOIN roms_in_romcollection AS rs ON rs.rom_id = rap.rom_id AND rs.romcollection_id = ?"

# Filter values
QUERY_SELECT_GENRES_BY_COLLECTION = "SELECT DISTINCT(r.m_genre) AS genre FROM vw_roms AS r INNER JOIN roms_in_romcollection AS rs ON rs.rom_id = r.id AND rs.romcollection_id = ? ORDER BY genre"
QUERY_SELECT_YEARS_BY_COLLECTION = "SELECT DISTINCT(r.m_year) AS year FROM vw_roms AS r INNER JOIN roms_in_romcollection AS rs ON rs.rom_id = r.id AND rs.romcollection_id = ? ORDER BY year"
QUERY_SELECT_DEVELOPER_BY_COLLECTION = "SELECT DISTINCT(r.m_developer) AS developer FROM vw_roms AS r INNER JOIN roms_in_romcollection AS rs ON rs.rom_id = r.id AND rs.romcollection_id = ? ORDER BY developer"
QUERY_SELECT_RATING_BY_COLLECTION = "SELECT DISTINCT(r.m_rating) AS rating FROM vw_roms AS r INNER JOIN roms_in_romcollection AS rs ON rs.rom_id = r.id AND rs.romcollection_id = ? ORDER BY rating"

QUERY_INSERT_ROM = """
INSERT INTO roms (
id, metadata_id, name, num_of_players, esrb_rating, platform, box_size,
Expand Down Expand Up @@ -1036,7 +1042,7 @@ def _get_collections_query_by_vcategory_id(self, vcategory_id:str) -> str:
QUERY_UPDATE_ROM_LAUNCHER = "UPDATE rom_launchers SET settings = ?, is_default = ? WHERE id = ?"
QUERY_DELETE_ROM_LAUNCHERS = "DELETE FROM rom_launchers WHERE rom_id = ?"
QUERY_DELETE_ROM_LAUNCHER = "DELETE FROM rom_launchers WHERE romcollection_id = ? AND id = ?"

class ROMsRepository(object):

def __init__(self, uow: UnitOfWork):
Expand Down Expand Up @@ -1206,7 +1212,22 @@ def delete_rom(self, rom_id: str):

def delete_roms_by_romcollection(self, romcollection_id:str):
self._uow.execute(QUERY_DELETE_ROMS_BY_COLLECTION, romcollection_id)


def find_all_filter_values_in_romcollection(self, romcollection: ROMCollection, filter_type:str) -> typing.Iterator[str]:
is_virtual = romcollection.get_type() == constants.OBJ_COLLECTION_VIRTUAL
romcollection_id = romcollection.get_id()

result_set = []
if is_virtual:
pass
else:
query = self._get_query_by_filter(filter_type)
self._uow.execute(query, romcollection_id)
result_set = self._uow.result_set()

for filter_value_data in result_set:
yield filter_value_data[filter_type]

def _insert_asset(self, asset: Asset, rom_obj: ROM):
asset_db_id = text.misc_generate_random_SID()
self._uow.execute(QUERY_INSERT_ASSET, asset_db_id, asset.get_path(), asset.get_asset_info_id())
Expand Down Expand Up @@ -1267,7 +1288,14 @@ def _get_queries_by_vcollection_type(self, vcollection:VirtualCollection) -> typ
if vcollection_id == constants.VCOLLECTION_MOST_PLAYED_ID: return QUERY_SELECT_MOST_PLAYED_ROMS, QUERY_SELECT_MOST_PLAYED_ROM_ASSETS

return None, None


def _get_query_by_filter(self, filter:str) -> typing.Tuple[str, str]:
if filter == constants.META_GENRE_ID: return QUERY_SELECT_GENRES_BY_COLLECTION
if filter == constants.META_YEAR_ID: return QUERY_SELECT_YEARS_BY_COLLECTION
if filter == constants.META_DEVELOPER_ID: return QUERY_SELECT_DEVELOPER_BY_COLLECTION
if filter == constants.META_RATING_ID: return QUERY_SELECT_RATING_BY_COLLECTION
return None

#
# AelAddonRepository -> AEL Adoon objects from SQLite DB
#
Expand Down
22 changes: 13 additions & 9 deletions resources/lib/viewqueries.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import logging
import typing
import collections
from urllib.parse import urlencode

# AEL modules
Expand All @@ -36,8 +37,8 @@
from resources.lib.repositories import ViewRepository

logger = logging.getLogger(__name__)

#

# Root view items
#
def qry_get_root_items():
Expand All @@ -55,9 +56,6 @@ def qry_get_root_items():
AppMediator.async_cmd('RENDER_VIEWS')

listitem_fanart = globals.g_PATHS.FANART_FILE_PATH.getPath()
listitem_icon = globals.g_PATHS.ADDON_CODE_DIR.pjoin('media/theme/Utilities_icon.png').getPath()
listitem_poster = globals.g_PATHS.ADDON_CODE_DIR.pjoin('media/theme/Utilities_poster.png').getPath()
art = { 'icon' : listitem_icon, 'fanart' : listitem_fanart, 'poster': listitem_poster }

if not settings.getSettingAsBool('display_hide_utilities'):
listitem_name = 'Utilities'
Expand All @@ -71,14 +69,16 @@ def qry_get_root_items():
'plot': 'Execute several [COLOR orange]Utilities[/COLOR].',
'overlay': 4
},
'art': art,
'art': {
'icon' : globals.g_PATHS.ADDON_CODE_DIR.pjoin('media/theme/Utilities_icon.png').getPath(),
'fanart' : listitem_fanart,
'poster': globals.g_PATHS.ADDON_CODE_DIR.pjoin('media/theme/Utilities_poster.png').getPath()
},
'properties': { constants.AEL_CONTENT_LABEL: constants.AEL_CONTENT_VALUE_CATEGORY, 'obj_type': constants.OBJ_NONE }
})

if not settings.getSettingAsBool('display_hide_g_reports'):
listitem_name = 'Global Reports'
listitem_icon = globals.g_PATHS.ICON_FILE_PATH.getPath()
listitem_fanart = globals.g_PATHS.FANART_FILE_PATH.getPath()
container['items'].append({
'name': listitem_name,
'url': globals.router.url_for_path('globalreports'), #SHOW_GLOBALREPORTS_VLAUNCHERS'
Expand All @@ -89,7 +89,11 @@ def qry_get_root_items():
'plot': 'Generate and view [COLOR orange]Global Reports[/COLOR].',
'overlay': 4
},
'art': art,
'art': {
'icon' : globals.g_PATHS.ADDON_CODE_DIR.pjoin('media/theme/Global_Reports_icon.png').getPath(),
'fanart' : listitem_fanart,
'poster': globals.g_PATHS.ADDON_CODE_DIR.pjoin('media/theme/Global_Reports_poster.png').getPath()
},
'properties': { constants.AEL_CONTENT_LABEL: constants.AEL_CONTENT_VALUE_CATEGORY, 'obj_type': constants.OBJ_NONE }
})

Expand Down Expand Up @@ -365,7 +369,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_view',{'category_id':container_id})))
if is_romcollection:
commands.append(('Search ROM in collection', _context_menu_url_for('/search/{}'.format(container_id))))
commands.append(('Search ROM in collection', _context_menu_url_for(f'/collection/{container_id}/search')))
commands.append(('Rebuild {} view'.format(container_name),
_context_menu_url_for('execute/command/render_romcollection_view', {'romcollection_id':container_id})))
if is_virtual_category and not is_root:
Expand Down
Loading