def _update_widgets(self): self._refresh(True) while not self.abortRequested(): for _ in self.tick(15, 60 * 15): # TODO: somehow delay to all other plugins loaded? unrefreshed_widgets = set() for hash, widget_ids in utils.next_cache_queue(): effected_widgets = cache_and_update(widget_ids) utils.remove_cache_queue( hash ) # Just in queued path's widget defintion has changed and it didn't update this path unrefreshed_widgets = unrefreshed_widgets.union( effected_widgets).difference(set(widget_ids)) # # wait 5s or for the skin to reload the widget # # this should reduce churn at startup where widgets take too long too long show up # before_update = time.time() # TODO: have .access file so we can put above update # while _ in self.tick(1, 10, lambda: utils.last_read(hash) > before_update): # pass # utils.log("paused queue until read {:.2} for {}".format(utils.last_read(hash)-before_update, hash[:5]), 'info') if self.abortRequested(): break for widget_id in unrefreshed_widgets: widget_def = manage.get_widget_by_id(widget_id) if not widget_def: continue _update_strings(widget_def) if self.abortRequested(): break if not self._refresh(): continue
def update_path(widget_id, target, path=None): widget_def = manage.get_widget_by_id(widget_id) if not widget_def: return stack = widget_def.get("stack", []) if target == "next" and path: utils.log("Next Page selected from {}".format(widget_id), "debug") path_def = manage.get_path_by_id(widget_def["path"], widget_def["group"]) if isinstance(path_def, dict): widget_def["label"] = path_def["label"] stack.append(path) widget_def["stack"] = stack elif target == "back" and widget_def.get("stack"): utils.log("Previous Page selected from {}".format(widget_id), "debug") widget_def["stack"] = widget_def["stack"][:-1] elif target == "reset": if len(stack) > 0: # simple compatibility with pre-3.3.0 widgets if isinstance(stack[0], dict): widget_def["path"] = stack[0].get("id", "") widget_def["stack"] = [] manage.save_path_details(widget_def) _update_strings(widget_def) utils.update_container(True) back_to_top(target)
def edit_widget_dialog(widget_id): dialog = xbmcgui.Dialog() updated = False if advanced and not warning_shown: _warn() widget_def = manage.get_widget_by_id(widget_id) if not widget_def: return options = _get_widget_options(widget_def) remove_label = utils.get_string(32025) if widget_id else utils.get_string( 32023) options.append('[COLOR firebrick]{}[/COLOR]'.format(remove_label)) idx = dialog.select(utils.get_string(32048), options) if idx < 0: return elif idx == len(options) - 1: _remove_widget(widget_id) utils.update_container() return else: key = _clean_key(options[idx]) updated = _get_widget_value(widget_def, key) utils.log(updated, xbmc.LOGNOTICE) if updated: convert.save_path_details(widget_def, widget_id) utils.update_container() edit_widget_dialog(widget_id)
def refresh(widget_id, widget_def=None, paths=None, force=False, single=False): if not widget_def: widget_def = manage.get_widget_by_id(widget_id) if widget_def["action"] in ["static", "merged"]: return paths current_time = time.time() updated_at = widget_def.get("updated", 0) default_refresh = settings.get_setting_float("service.refresh_duration") refresh_duration = float(widget_def.get("refresh", default_refresh)) if updated_at <= current_time - (3600 * refresh_duration) or force: group_id = widget_def["group"] action = widget_def.get("action") current = int(widget_def.get("current", 0)) widget_def["stack"] = [] if not paths: cycle_paths = widget_def.get("cycle_paths") if cycle_paths is None: cycle_paths = [ p.get("id") for p in manage.find_defined_paths(group_id) ] widget_def["cycle_paths"] = cycle_paths paths = [p for p in cycle_paths] if action: if len(paths) > 0: next = 0 if action == "next": next = (current + 1) % len(paths) elif action == "random": random.shuffle(paths) next = random.randrange(len(paths)) widget_def["current"] = next path_id = paths[next] paths.remove(paths[next]) widget_def["path"] = path_id if widget_def["path"]: path_label = manage.get_path_by_id(path_id, group_id).get( "label", "") widget_def["label"] = path_label widget_def["updated"] = 0 if force else current_time manage.save_path_details(widget_def) _update_strings(widget_def) if single: utils.update_container(True) return paths
def merged_path(group_id, widget_id): _window = utils.get_active_window() group_def = manage.get_group_by_id(group_id) group_name = group_def.get("label", "") paths = group_def.get("paths", []) if len(paths) == 0: directory.add_menu_item(title=30019, art=utils.get_art("alert"), isFolder=False) return True, group_name, None widget_def = manage.get_widget_by_id(widget_id, group_id) if widget_def and _window != "dialog": paths = widget_def["path"] elif not widget_def: idxs = manage.choose_paths(utils.get_string(30089), paths, 5) if idxs is not None: if len(idxs) > 0: widget_def = manage.initialize(group_def, "merged", widget_id, keep=idxs) paths = widget_def["path"] if widget_def: titles = [] for idx, path in enumerate(paths): # simple compatibility with pre-3.3.0 widgets if isinstance(path, dict): path = path.get("id", "") paths[idx] = path widget_def["path"] = paths manage.save_path_details(widget_def) path_def = manage.get_path_by_id(path, group_id) titles, cat, type = show_path( group_id, path_def["label"], widget_id, path_def, idx=idx, titles=titles, num=len(paths), merged=True, ) return titles, cat, type else: directory.add_menu_item(title=30045, art=info, isFolder=True) return True, group_name, None
def refresh(widget_id, widget_def=None, paths=None, force=False, single=False): if not widget_def: widget_def = manage.get_widget_by_id(widget_id) if widget_def["action"] in ["static", "merged"]: return paths current_time = time.time() updated_at = widget_def.get("updated", 0) default_refresh = utils.get_setting_float("service.refresh_duration") refresh_duration = float(widget_def.get("refresh", default_refresh)) if updated_at <= current_time - (3600 * refresh_duration) or force: group_id = widget_def["group"] action = widget_def.get("action") current = int(widget_def.get("current", -1)) widget_def["stack"] = [] widget_def["label"] = "" if not paths: paths = manage.find_defined_paths(group_id) if action: if len(paths) > 0: next = 0 if action == "next": next = (current + 1) % len(paths) elif action == "random": random.shuffle(paths) next = random.randrange(len(paths)) elif action == 'randomized': next = manage.get_inactive_path(paths) if next == []: next = current widget_def['current'] = next path_def = paths[next] paths.remove(paths[next]) widget_def["path"] = path_def if widget_def["path"]: widget_def["updated"] = 0 if force else current_time manage.save_path_details(widget_def) _update_strings(widget_def) if single: utils.update_container(True) return paths
def merged_path(group_id, widget_id): _window = utils.get_active_window() group_def = manage.get_group_by_id(group_id) group_name = group_def.get("label", "") paths = group_def.get("paths", []) if len(paths) == 0: directory.add_menu_item(title=32032, art=utils.get_art("alert"), isFolder=False) return True, group_name widget_def = manage.get_widget_by_id(widget_id, group_id) if widget_def and _window != "dialog": paths = widget_def["path"] elif not widget_def: dialog = xbmcgui.Dialog() idxs = dialog.multiselect( utils.get_string(32115), [i["label"] for i in paths], preselect=list(range(len(paths))) if len(paths) <= 5 else [], ) if idxs is not None: if len(idxs) > 0: widget_def = manage.initialize(group_def, "merged", widget_id, keep=idxs) paths = widget_def["path"] if widget_def: titles = [] for idx, path_def in enumerate(paths): titles, cat = show_path( group_id, path_def["label"], widget_id, path_def["file"]["file"], idx=idx, titles=titles, num=len(paths), merged=True, ) return titles, cat else: directory.add_menu_item(title=32067, art=utils.get_art("information_outline"), isFolder=True) return True, group_name
def edit_widget_dialog(widget_id): updated = False if advanced and not warning_shown: _warn() widget_def = manage.get_widget_by_id(widget_id) if not widget_def: return updated = _show_widget_options(widget_def) if updated: manage.save_path_details(widget_def) utils.update_container(True) edit_widget_dialog(widget_id)
def refresh(widget_id, widget_def=None, paths=None, force=False, single=False): if not widget_def: widget_def = manage.get_widget_by_id(widget_id) if widget_def['action'] in ['static', 'merged']: return paths current_time = time.time() updated_at = widget_def.get('updated', 0) default_refresh = utils.get_setting_float('service.refresh_duration') refresh_duration = float(widget_def.get('refresh', default_refresh)) if updated_at <= current_time - (3600 * refresh_duration) or force: group_id = widget_def['group'] action = widget_def.get('action') current = int(widget_def.get('current', -1)) widget_def['stack'] = [] widget_def['label'] = '' if not paths: paths = manage.find_defined_paths(group_id) if action: if len(paths) > 0: next = 0 if action == 'next': next = (current + 1) % len(paths) elif action == 'random': random.shuffle(paths) next = random.randrange(len(paths)) widget_def['current'] = next path_def = paths[next] paths.remove(paths[next]) widget_def['path'] = path_def if widget_def['path']: widget_def['updated'] = 0 if force else current_time manage.save_path_details(widget_def) _update_strings(widget_def) if single: utils.update_container(True) return paths
def cache_and_update(widget_ids): """a widget might have many paths. Ensure each path is either queued for an update or is expired and if so force it to be refreshed. When going through the queue this could mean we refresh paths that other widgets also use. These will then be skipped. """ assert widget_ids effected_widgets = set() for widget_id in widget_ids: widget_def = manage.get_widget_by_id(widget_id) if not widget_def: continue changed = False widget_path = widget_def.get("path", {}) utils.log( "trying to update {} with widget def {}".format( widget_id, widget_def), "inspect", ) if type(widget_path) != list: widget_path = [widget_path] for path in widget_path: if isinstance(path, dict): _label = path["label"] path = path["file"]["file"] hash = utils.path2hash(path) # TODO: we might be updating paths used by widgets that weren't initiall queued. # We need to return those and ensure they get refreshed also. effected_widgets = effected_widgets.union( utils.widgets_for_path(path)) if utils.is_cache_queue(hash): # we need to update this path regardless new_files, files_changed = utils.cache_files(path, widget_id) changed = changed or files_changed utils.remove_cache_queue(hash) # else: # # double check this hasn't been updated already when updating another widget # expiry, _ = utils.cache_expiry(hash, widget_id, no_queue=True) # if expiry <= time.time(): # utils.cache_files(path, widget_id) # else: # pass # Skipping this path because its already been updated # TODO: only need to do that if a path has changed which we can tell from the history if changed: _update_strings(widget_def) return effected_widgets
def refresh(widget_id, widget_def=None, paths=None, force=False): if not widget_def: widget_def = manage.get_widget_by_id(widget_id) current_time = time.time() updated_at = widget_def.get('updated', 0) default_refresh = utils.get_setting_float('service.refresh_duration') refresh_duration = float(widget_def.get('refresh', default_refresh)) if updated_at <= current_time - (3600 * refresh_duration) or force: path_def = {} _id = widget_def['id'] group_id = widget_def['group'] action = widget_def.get('action') setting = widget_def.get('path_setting') label_setting = widget_def.get('label_setting') current = int(widget_def.get('current', -1)) if not paths: paths = manage.find_defined_paths(group_id) random.shuffle(paths) if action: if len(paths) > 0: next = 0 if action == 'next': next = (current + 1) % len(paths) elif action == 'random': next = random.randrange(len(paths)) widget_def['current'] = next path_def = paths[next] paths.remove(paths[next]) widget_def['path'] = path_def.get('id') if widget_def['path']: widget_def['updated'] = 0 if force else current_time convert.save_path_details(widget_def, _id) _update_strings(_id, path_def, setting, label_setting) utils.update_container() return paths
def merged_path(group_id, widget_id): _window = utils.get_active_window() group_def = manage.get_group_by_id(group_id) group_name = group_def.get('label', '') paths = group_def.get('paths', []) if len(paths) == 0: directory.add_menu_item(title=32032, art=utils.get_art('alert'), isFolder=False) return True, group_name widget_def = manage.get_widget_by_id(widget_id, group_id) if widget_def and _window != 'dialog': paths = widget_def['path'] elif not widget_def: dialog = xbmcgui.Dialog() idxs = dialog.multiselect( utils.get_string(32115), [i['label'] for i in paths], preselect=list(range(len(paths))) if len(paths) <= 5 else []) if idxs is not None: if len(idxs) > 0: widget_def = manage.initialize(group_def, 'merged', widget_id, keep=idxs) paths = widget_def['path'] if widget_def: titles = [] for idx, path_def in enumerate(paths): titles, cat = show_path(group_id, path_def['label'], widget_id, path_def['file']['file'], idx=idx, num=len(paths), merged=True) return titles, cat else: directory.add_menu_item(title=32067, art=utils.get_art('information_outline'), isFolder=True) return True, group_name
def update_path(widget_id, target, path=None): widget_def = manage.get_widget_by_id(widget_id) if not widget_def: return stack = widget_def.get("stack", []) if target == "next" and path: utils.log("Next Page selected from {}".format(widget_id), "debug") path_def = widget_def["path"] if isinstance(path_def, dict): widget_def["label"] = path_def["label"] stack.append(widget_def["path"]) widget_def["stack"] = stack widget_def["path"] = path elif target == "back" and widget_def.get("stack"): utils.log("Previous Page selected from {}".format(widget_id), "debug") widget_def["path"] = widget_def["stack"][-1] widget_def["stack"] = widget_def["stack"][:-1] if len(widget_def["stack"]) == 0: widget_def["label"] = "" elif target == "reset": if len(stack) > 0: widget_def["path"] = widget_def["stack"][0] widget_def["stack"] = [] widget_def["label"] = "" action = widget_def[ "path"] if widget_def["action"] != "merged" else "merged" if isinstance(widget_def["path"], dict): action = widget_def["path"]["file"]["file"] manage.save_path_details(widget_def) _update_strings(widget_def) utils.update_container(True) back_to_top(target)
def update_path(widget_id, target, path=None): widget_def = manage.get_widget_by_id(widget_id) if not widget_def: return stack = widget_def.get('stack', []) if target == 'next' and path: utils.log('Next Page selected from {}'.format(widget_id), 'debug') path_def = widget_def['path'] if isinstance(path_def, dict): widget_def['label'] = path_def['label'] stack.append(widget_def['path']) widget_def['stack'] = stack widget_def['path'] = path elif target == 'back' and widget_def.get('stack'): utils.log('Previous Page selected from {}'.format(widget_id), 'debug') widget_def['path'] = widget_def['stack'][-1] widget_def['stack'] = widget_def['stack'][:-1] if len(widget_def['stack']) == 0: widget_def['label'] = '' elif target == 'reset': if len(stack) > 0: widget_def['path'] = widget_def['stack'][0] widget_def['stack'] = [] widget_def['label'] = '' action = widget_def[ 'path'] if widget_def['action'] != 'merged' else 'merged' if isinstance(widget_def['path'], dict): action = widget_def['path']['file']['file'] manage.save_path_details(widget_def) _update_strings(widget_def) utils.update_container(True) back_to_top(target)
def cache_and_update(path, widget_id, cache_data, notify=None): """a widget might have many paths. Ensure each path is either queued for an update or is expired and if so force it to be refreshed. When going through the queue this could mean we refresh paths that other widgets also use. These will then be skipped. """ assert widget_id assert cache_data.get("path") == path assert widget_id in cache_data["widgets"] hash = path2hash(path) if not is_cache_queue(hash): return [] if notify is not None: widget_def = manage.get_widget_by_id(widget_id) if widget_def is not None: notify(widget_def.get("label", ""), path) new_files, files_changed = cache_files(path, widget_id) remove_cache_queue(hash) # TODO: this is all widgets that ever requested this path. do we # need to update all of them? return cache_data["widgets"] if files_changed else []
def path_menu(group_id, action, widget_id): group_def = manage.get_group_by_id(group_id) if not group_def: directory.add_menu_item(title=32073, info={'plot': utils.get_string(32075)}, art=utils.get_art('alert'), isFolder=True) return True, 'AutoWidget' group_name = group_def.get('label', '') paths = group_def.get('paths', []) if len(paths) == 0: directory.add_menu_item(title=32032, art=utils.get_art('alert'), isFolder=True) return True, group_name widget_def = manage.get_widget_by_id(widget_id, group_id) if not widget_def: dialog = xbmcgui.Dialog() if action == 'static': idx = dialog.select(utils.get_string(32114), [i['label'] for i in paths]) if idx == -1: return True, 'AutoWidget' widget_def = manage.initialize(group_def, action, widget_id, keep=idx) elif action == 'cycling': idx = dialog.select( utils.get_string(32081), [utils.get_string(32079), utils.get_string(32080)]) if idx == -1: return True, 'AutoWidget' _action = 'random' if idx == 0 else 'next' widget_def = manage.initialize(group_def, _action, widget_id) if widget_def: widget_path = widget_def.get('path', {}) if isinstance(widget_path, dict): _label = widget_path['label'] widget_path = widget_path['file']['file'] else: stack = widget_def.get('stack', []) if stack: _label = stack[0]['label'] else: _label = widget_def.get('label', '') utils.log('Showing widget {}'.format(widget_id), 'debug') titles, cat = show_path(group_id, _label, widget_id, widget_path) return titles, cat else: directory.add_menu_item(title=32067, art=utils.get_art('information_outline'), isFolder=True) return True, group_name
def show_path(group_id, path_label, widget_id, path, idx=0, titles=None, num=1, merged=False): hide_watched = utils.get_setting_bool('widgets.hide_watched') show_next = utils.get_setting_int('widgets.show_next') paged_widgets = utils.get_setting_bool('widgets.paged') default_color = utils.get_setting('ui.color') widget_def = manage.get_widget_by_id(widget_id) if not widget_def: return True, 'AutoWidget' if not titles: titles = [] files = refresh.get_files_list(path, titles, widget_id) if not files: return titles, path_label utils.log('Loading items from {}'.format(path), 'debug') if isinstance(widget_def['path'], list): color = widget_def['path'][idx].get('color', default_color) elif isinstance(widget_def['path'], six.text_type): color = widget_def['stack'][0].get('color', default_color) else: color = widget_def['path'].get('color', default_color) stack = widget_def.get('stack', []) if stack: title = utils.get_string(32110).format(len(stack)) directory.add_menu_item(title=title, params={ 'mode': 'path', 'action': 'update', 'id': widget_id, 'path': '', 'target': 'back' }, art=utils.get_art('back', color), isFolder=num > 1, props={ 'specialsort': 'top', 'autoLabel': path_label }) for file in files: properties = {'autoLabel': path_label, 'autoID': widget_id} if 'customproperties' in file: for prop in file['customproperties']: properties[prop] = file['customproperties'][prop] clean_pattern = '[^\w \xC0-\xFF]' tag_pattern = '(\[[^\]]*\])' next_pattern = ( '(?:^(?:next)?\s*(?:(?:>>)|(?:\.*)$)?)\s*' '(?:page\s*(?:(?:\d+\D*\d?$)|(?:(?:>>)|(?:\.*)$)|(?:\(\d+|.*\)$))?)?$' ) prev_pattern = '^(?:previous(?: page)?)$|^(?:back)$' cleaned_title = re.sub(tag_pattern, '', file.get('label', '').lower()).strip() next_item = re.search(next_pattern, cleaned_title) prev_item = re.search(prev_pattern, cleaned_title) if (prev_item and stack) or (next_item and show_next == 0): continue elif next_item and show_next > 0: label = utils.get_string(32111) properties['specialsort'] = 'bottom' if num > 1: if show_next == 1: continue label = '{} - {}'.format(label, path_label) update_params = { 'mode': 'path', 'action': 'update', 'id': widget_id, 'path': file['file'], 'target': 'next' } directory.add_menu_item( title=label, params=update_params if paged_widgets and not merged else None, path=file['file'] if not paged_widgets or merged else None, art=utils.get_art('next_page', color), info=file, isFolder=not paged_widgets or merged, props=properties) else: dupe = False title = (file['label'], file.get('imdbnumber')) for t in titles: if t == title: dupe = True if (hide_watched and file.get('playcount', 0) > 0) or dupe: continue directory.add_menu_item(title=title[0], path=file['file'], art=file['art'], info=file, isFolder=file['filetype'] == 'directory', props=properties) titles.append(title) return titles, path_label
def path_menu(group_id, action, widget_id): group_def = manage.get_group_by_id(group_id) if not group_def: directory.add_menu_item( title=32073, info={"plot": utils.get_string(32075)}, art=utils.get_art("alert"), isFolder=True, ) return True, "AutoWidget" group_name = group_def.get("label", "") paths = group_def.get("paths", []) if len(paths) == 0: directory.add_menu_item(title=32032, art=utils.get_art("alert"), isFolder=True) return True, group_name widget_def = manage.get_widget_by_id(widget_id, group_id) if not widget_def: dialog = xbmcgui.Dialog() if action == "static": idx = dialog.select(utils.get_string(32114), [i["label"] for i in paths]) if idx == -1: return True, "AutoWidget" widget_def = manage.initialize(group_def, action, widget_id, keep=idx) elif action == 'cycling': idx = dialog.select(utils.get_string(32081), [ utils.get_string(32079), utils.get_string(32080), utils.get_string(32242) ]) if idx == -1: return True, 'AutoWidget' elif idx == 0: _action = 'random' elif idx == 1: _action = 'next' else: _action = 'randomized' widget_def = manage.initialize(group_def, _action, widget_id) if widget_def: widget_path = widget_def.get("path", {}) if isinstance(widget_path, dict): _label = widget_path["label"] widget_path = widget_path["file"]["file"] else: stack = widget_def.get("stack", []) if stack: _label = stack[0]["label"] else: _label = widget_def.get("label", "") utils.log("Showing widget {}".format(widget_id), "debug") titles, cat = show_path(group_id, _label, widget_id, widget_path) return titles, cat else: directory.add_menu_item(title=32067, art=utils.get_art("information_outline"), isFolder=True) return True, group_name
def show_path(group_id, path_label, widget_id, path, idx=0, titles=None, num=1, merged=False): hide_watched = utils.get_setting_bool("widgets.hide_watched") show_next = utils.get_setting_int("widgets.show_next") paged_widgets = utils.get_setting_bool("widgets.paged") default_color = utils.get_setting("ui.color") widget_def = manage.get_widget_by_id(widget_id) if not widget_def: return True, "AutoWidget" if not titles: titles = [] files = refresh.get_files_list(path, widget_id) if not files: return titles, path_label utils.log("Loading items from {}".format(path), "debug") if isinstance(widget_def["path"], list): color = widget_def["path"][idx].get("color", default_color) elif isinstance(widget_def["path"], six.text_type): color = widget_def["stack"][0].get("color", default_color) else: color = widget_def["path"].get("color", default_color) stack = widget_def.get("stack", []) if stack: title = utils.get_string(32110).format(len(stack)) directory.add_menu_item( title=title, params={ "mode": "path", "action": "update", "id": widget_id, "path": "", "target": "back", }, art=utils.get_art("back", color), isFolder=num > 1, props={ "specialsort": "top", "autoLabel": path_label }, ) for file in files: properties = {"autoLabel": path_label, "autoID": widget_id} if "customproperties" in file: for prop in file["customproperties"]: properties[prop] = file["customproperties"][prop] clean_pattern = "[^\w \xC0-\xFF]" tag_pattern = "(\[[^\]]*\])" next_pattern = ( "(?:^(?:next)?\s*(?:(?:>>)|(?:\.*)$)?)\s*" "(?:page\s*(?:(?:\d+\D*\d?$)|(?:(?:>>)|(?:\.*)$)|(?:\(\d+|.*\)$))?)?$" ) prev_pattern = "^(?:previous(?: page)?)$|^(?:back)$" cleaned_title = re.sub(tag_pattern, "", file.get("label", "").lower()).strip() next_item = re.search(next_pattern, cleaned_title) prev_item = re.search(prev_pattern, cleaned_title) if (prev_item and stack) or (next_item and show_next == 0): continue elif next_item and show_next > 0: label = utils.get_string(32111) properties["specialsort"] = "bottom" if num > 1: if show_next == 1: continue label = "{} - {}".format(label, path_label) update_params = { "mode": "path", "action": "update", "id": widget_id, "path": file["file"], "target": "next", } directory.add_menu_item( title=label, params=update_params if paged_widgets and not merged else None, path=file["file"] if not paged_widgets or merged else None, art=utils.get_art("next_page", color), info=file, isFolder=not paged_widgets or merged, props=properties, ) else: title = { "type": file.get("type"), "label": file.get("label"), "imdbnumber": file.get("imdbnumber"), "showtitle": file.get("showtitle"), } dupe = refresh.is_duplicate(title, titles) if (hide_watched and file.get("playcount", 0) > 0) or dupe: continue art = file.get("art", {}) if not art.get("landscape") and art.get("thumb"): art["landscape"] = art["thumb"] directory.add_menu_item( title=file["label"], path=file["file"], art=art, info=file, isFolder=file["filetype"] == "directory", props=properties, ) titles.append(title) return titles, path_label
def show_path( group_id, path_label, widget_id, widget_path, idx=0, titles=None, num=1, merged=False, ): hide_watched = settings.get_setting_bool("widgets.hide_watched") show_next = settings.get_setting_int("widgets.show_next") paged_widgets = settings.get_setting_bool("widgets.paged") default_color = settings.get_setting_string("ui.color") widget_def = manage.get_widget_by_id(widget_id) if not widget_def: return True, "AutoWidget", None content = widget_path.get("content") action = widget_def.get("action", "") if not titles: titles = [] stack = widget_def.get("stack", []) path = widget_path["file"]["file"] if not stack else stack[-1] files, hash = refresh.get_files_list(path, widget_id) # if not files: # properties = { # "autoLabel": path_label, # "autoID": widget_id, # "autoAction": action, # "autoCache": hash, # } # if files is None: # show_error(path_label, properties) # elif files == []: # show_empty(path_label, properties) # return titles if titles else True, path_label, content utils.log("Loading items from {}".format(path), "debug") color = widget_path.get("color", default_color) if stack: title = _previous # title = utils.get_string(30085).format(len(stack)) directory.add_menu_item( title=title, params={ "mode": "path", "action": "update", "id": widget_id, "path": "", "target": "back", }, art=utils.get_art("back", color), isFolder=num > 1, props={ "specialsort": "top", "autoLabel": path_label }, ) for pos, file in enumerate(files): properties = { "autoLabel": path_label, "autoID": widget_id, "autoAction": action, "autoCache": hash, } next_item = False prev_item = False is_folder = file["filetype"] == "directory" if pos == len(files) - 1 and is_folder: next_item = _is_page_item(file.get("label", "")) elif pos == 0 and is_folder: prev_item = _is_page_item(file.get("label", ""), next=False) if (prev_item and stack) or (next_item and show_next == 0): continue elif next_item and show_next > 0: label = _next_page properties["specialsort"] = "bottom" if num > 1: if show_next == 1: continue label = "{} - {}".format(label, path_label) update_params = { "mode": "path", "action": "update", "id": widget_id, "path": file["file"], "target": "next", } directory.add_menu_item( title=label, params=update_params if paged_widgets and not merged else None, path=file["file"] if not paged_widgets or merged else None, art=utils.get_art("next_page", color), info=file, isFolder=not paged_widgets or merged, props=properties, ) else: filetype = file.get("type", "") title = { "type": filetype, "label": file.get("label"), "imdbnumber": file.get("imdbnumber"), "showtitle": file.get("showtitle"), } dupe = refresh.is_duplicate(title, titles) if (hide_watched and file.get("playcount", 0) > 0) or dupe: continue filepath = "" info_type = directory.info_types.get(filetype, "video") if (path.startswith("library://{}/".format(info_type)) or path.startswith("{}db://".format(info_type) or path.endswith(".xsp"))) and is_folder: filepath = directory.make_library_path(info_type, filetype, file.get("id", -1)) directory.add_menu_item( title=file["label"], path=file["file"] if not filepath else filepath, info=file, isFolder=is_folder, props=properties, ) titles.append(title) return titles, path_label, content
def path_menu(group_id, action, widget_id): group_def = manage.get_group_by_id(group_id) if not group_def: directory.add_menu_item( title=30051, info={"plot": utils.get_string(30053)}, art=utils.get_art("alert"), isFolder=True, ) return True, "AutoWidget", None group_name = group_def.get("label", "") paths = group_def.get("paths", []) if len(paths) == 0: directory.add_menu_item(title=30019, art=utils.get_art("alert"), isFolder=True) return True, group_name, None widget_def = manage.get_widget_by_id(widget_id, group_id) if not widget_def: dialog = xbmcgui.Dialog() if action == "static": idx = manage.choose_paths(utils.get_string(30088), paths, indices=True, single=True) if idx == -1: return True, "AutoWidget", None widget_def = manage.initialize(group_def, action, widget_id, keep=idx) elif action == "cycling": idx = dialog.select( utils.get_string(30059), [utils.get_string(30057), utils.get_string(30058)], ) if idx == -1: del dialog return True, "AutoWidget", None _action = "random" if idx == 0 else "next" cycle_paths = manage.choose_paths(utils.get_string(30123), paths, threshold=-1, indices=True) widget_def = manage.initialize(group_def, _action, widget_id, keep=cycle_paths) del dialog if widget_def: widget_path = widget_def.get("path", "") # simple compatibility with pre-3.3.0 widgets if isinstance(widget_path, dict): widget_path = widget_def.get("path", {}).get("id", "") widget_def["path"] = widget_path manage.save_path_details(widget_def) widget_path = manage.get_path_by_id(widget_path, group_id) _label = "" if isinstance(widget_path, dict): _label = widget_path.get("label", "") utils.log("Showing widget {}".format(widget_id), "debug") titles, cat, type = show_path(group_id, _label, widget_id, widget_path) return titles, cat, type else: directory.add_menu_item(title=30045, art=info, isFolder=True) return True, group_name, None
def _update_widgets(self): self._refresh(True) while not self.abortRequested(): for _ in self.tick(step=1, max=60 * 15): # don't process cache queue during video playback if self.player.isPlayingVideo(): continue # TODO: somehow delay till all other plugins loaded? updated = False unrefreshed_widgets = set() queue = list(cache.next_cache_queue()) # class Progress(object): # dialog = None # service = self # done = set() # def __call__(self, groupname, path): # if self.dialog is None: # self.dialog = xbmcgui.DialogProgressBG() # self.dialog.create("AutoWidget", utils.get_string(30141)) # if not self.service.player.isPlayingVideo(): # percent = ( # len(self.done) # / float(len(queue) + len(self.done) + 1) # * 100 # ) # self.dialog.update( # int(percent), "AutoWidget", message=groupname # ) # self.done.add(path) # progress = Progress() while queue: path, cache_data, widget_id = queue.pop(0) hash = cache.path2hash(path) utils.log("Dequeued cache update: {}".format(hash[:5]), "notice") affected_widgets = set( cache.cache_and_update( path, widget_id, cache_data, # notify=progress ) ) if affected_widgets: updated = True unrefreshed_widgets = unrefreshed_widgets.union(affected_widgets) # # wait 5s or for the skin to reload the widget # # this should reduce churn at startup where widgets take too long too long show up # before_update = time.time() # TODO: have .access file so we can put above update # while _ in self.tick(1, 10, lambda: cache.last_read(hash) > before_update): # pass # utils.log("paused queue until read {:.2} for {}".format(cache.last_read(hash)-before_update, hash[:5]), 'info') if self.abortRequested(): break if self.player.isPlayingVideo(): # Video stop will cause another refresh anyway. break queue = list(cache.next_cache_queue()) for widget_id in unrefreshed_widgets: widget_def = manage.get_widget_by_id(widget_id) if not widget_def: continue _update_strings(widget_def) if ( os.path.exists(os.path.join(_addon_data, "refresh.time")) and utils.get_active_window() == "home" ): utils.update_container(True) # if progress.dialog is not None: # progress.dialog.update(100) # progress.dialog.close() if ( updated and self.refresh_enabled == 1 and not self.player.isPlayingVideo() ): dialog = xbmcgui.Dialog() dialog.notification( u"AutoWidget", utils.get_string(30142), sound=False ) if self.abortRequested(): break if not self._refresh(): continue
def show_path(group_id, path_label, widget_id, path, idx=0, titles=None, num=1, merged=False): hide_watched = utils.get_setting_bool("widgets.hide_watched") show_next = utils.get_setting_int("widgets.show_next") paged_widgets = utils.get_setting_bool("widgets.paged") default_color = utils.get_setting("ui.color") widget_def = manage.get_widget_by_id(widget_id) if not widget_def: return True, "AutoWidget" if not titles: titles = [] files = refresh.get_files_list(path, widget_id) if not files: return titles, path_label utils.log("Loading items from {}".format(path), "debug") if isinstance(widget_def["path"], list): color = widget_def["path"][idx].get("color", default_color) elif isinstance(widget_def["path"], six.text_type): color = widget_def["stack"][0].get("color", default_color) else: color = widget_def["path"].get("color", default_color) stack = widget_def.get("stack", []) if stack: title = _previous # title = utils.get_string(30085).format(len(stack)) directory.add_menu_item( title=title, params={ "mode": "path", "action": "update", "id": widget_id, "path": "", "target": "back", }, art=utils.get_art("back", color), isFolder=num > 1, props={ "specialsort": "top", "autoLabel": path_label }, ) for pos, file in enumerate(files): properties = {"autoLabel": path_label, "autoID": widget_id} next_item = False prev_item = False if "customproperties" in file: for prop in file["customproperties"]: properties[prop] = file["customproperties"][prop] if pos == len(files) - 1: next_item = _is_page_item(file.get("label", "")) elif pos == 0: prev_item = _is_page_item(file.get("label", ""), next=False) if (prev_item and stack) or (next_item and show_next == 0): continue elif next_item and show_next > 0: label = _next_page properties["specialsort"] = "bottom" if num > 1: if show_next == 1: continue label = "{} - {}".format(label, path_label) update_params = { "mode": "path", "action": "update", "id": widget_id, "path": file["file"], "target": "next", } directory.add_menu_item( title=label, params=update_params if paged_widgets and not merged else None, path=file["file"] if not paged_widgets or merged else None, art=utils.get_art("next_page", color), info=file, isFolder=not paged_widgets or merged, props=properties, ) else: title = { "type": file.get("type"), "label": file.get("label"), "imdbnumber": file.get("imdbnumber"), "showtitle": file.get("showtitle"), } dupe = refresh.is_duplicate(title, titles) if (hide_watched and file.get("playcount", 0) > 0) or dupe: continue art = file.get("art", {}) if not art.get("landscape") and art.get("thumb"): art["landscape"] = art["thumb"] directory.add_menu_item( title=file["label"], path=file["file"], art=art, info=file, isFolder=file["filetype"] == "directory", props=properties, ) titles.append(title) return titles, path_label