mirror of
https://github.com/anxdpanic/plugin.video.youtube.git
synced 2025-12-06 02:30:50 -08:00
Add ViewManager
- Updated to be more self-contained and work better with unsupported skins - TODO: Add support for setting default sort order and sort direction Fix content type not being set to episodes - Fix #586, #589 Update for restructure of xbmc_plugin - Only set view mode if directory items successfully added Fix preselect on view_manager view lists Update to match new setup wizard Update for reorganised/renamed constantsfca610cUpdate for updated XbmcContext.apply_content8a8247aUpdate for new localize and logging methods Update to fix setting view mode not working if container is still updating Update to handle sort method and order and workaround #1243 Update to handle localised sort order #1309
This commit is contained in:
parent
2c701f800c
commit
6affa686e2
12 changed files with 457 additions and 2 deletions
|
|
@ -144,6 +144,7 @@ class AbstractProvider(object):
|
|||
if last_run and last_run > 1:
|
||||
self.pre_run_wizard_step(provider=self, context=context)
|
||||
wizard_steps = self.get_wizard_steps()
|
||||
wizard_steps.extend(ui.get_view_manager().get_wizard_steps())
|
||||
|
||||
step = 0
|
||||
steps = len(wizard_steps)
|
||||
|
|
|
|||
|
|
@ -186,6 +186,8 @@ PAGE = 'page'
|
|||
PLAYLIST_IDS = 'playlist_ids'
|
||||
SCREENSAVER = 'screensaver'
|
||||
SEEK = 'seek'
|
||||
SORT_DIR = 'sort_dir'
|
||||
SORT_METHOD = 'sort_method'
|
||||
START = 'start'
|
||||
VIDEO_IDS = 'video_ids'
|
||||
|
||||
|
|
@ -346,6 +348,8 @@ __all__ = (
|
|||
'PLAYLIST_IDS',
|
||||
'SCREENSAVER',
|
||||
'SEEK',
|
||||
'SORT_DIR',
|
||||
'SORT_METHOD',
|
||||
'START',
|
||||
'VIDEO_IDS',
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
from __future__ import absolute_import, division, unicode_literals
|
||||
|
||||
|
||||
VIDEO_CONTENT = 'videos'
|
||||
LIST_CONTENT = 'files'
|
||||
VIDEO_CONTENT = 'episodes'
|
||||
LIST_CONTENT = 'default'
|
||||
|
||||
COMMENTS = 'comments'
|
||||
HISTORY = 'history'
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import sys
|
|||
|
||||
from . import const_content_types as CONTENT
|
||||
from ..compatibility import (
|
||||
xbmc,
|
||||
xbmcplugin,
|
||||
)
|
||||
|
||||
|
|
@ -77,12 +78,31 @@ methods = [
|
|||
('VIDEO_ORIGINAL_TITLE', 20376, 57),
|
||||
('VIDEO_ORIGINAL_TITLE_IGNORE_THE', 20376, None),
|
||||
]
|
||||
SORT_ID_MAPPING = {}
|
||||
|
||||
SORT = sys.modules[__name__]
|
||||
name = label_id = sort_by = sort_method = None
|
||||
for name, label_id, sort_by in methods:
|
||||
sort_method = getattr(xbmcplugin, 'SORT_METHOD_' + name, 0)
|
||||
setattr(SORT, name, sort_method)
|
||||
if sort_by is not None:
|
||||
SORT_ID_MAPPING.update((
|
||||
(name, sort_by),
|
||||
(xbmc.getLocalizedString(label_id), sort_by),
|
||||
(sort_method, sort_by if sort_method else 0),
|
||||
))
|
||||
|
||||
SORT_ID_MAPPING.update((
|
||||
(CONTENT.VIDEO_CONTENT.join(('__', '__')), SORT.UNSORTED),
|
||||
(CONTENT.LIST_CONTENT.join(('__', '__')), SORT.LABEL),
|
||||
(CONTENT.COMMENTS.join(('__', '__')), SORT.CHANNEL),
|
||||
(CONTENT.HISTORY.join(('__', '__')), SORT.LASTPLAYED),
|
||||
))
|
||||
|
||||
SORT_DIR = {
|
||||
xbmc.getLocalizedString(584): 'ascending',
|
||||
xbmc.getLocalizedString(585): 'descending',
|
||||
}
|
||||
|
||||
# Label mask token details:
|
||||
# https://github.com/xbmc/xbmc/blob/master/xbmc/utils/LabelFormatter.cpp#L33-L105
|
||||
|
|
@ -179,6 +199,7 @@ COMMENTS_CONTENT_SIMPLE = (
|
|||
del (
|
||||
sys,
|
||||
CONTENT,
|
||||
xbmc,
|
||||
xbmcplugin,
|
||||
methods,
|
||||
SORT,
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ from ..constants import (
|
|||
PLAY_USING,
|
||||
SCREENSAVER,
|
||||
SEEK,
|
||||
SORT_DIR,
|
||||
SORT_METHOD,
|
||||
START,
|
||||
SUBSCRIPTION_ID,
|
||||
VIDEO_ID,
|
||||
|
|
@ -169,6 +171,8 @@ class AbstractContext(object):
|
|||
'q',
|
||||
'rating',
|
||||
'reload_path',
|
||||
SORT_DIR,
|
||||
SORT_METHOD,
|
||||
'search_type',
|
||||
SUBSCRIPTION_ID,
|
||||
'uri',
|
||||
|
|
|
|||
|
|
@ -704,6 +704,7 @@ class XbmcContext(AbstractContext):
|
|||
path=self.get_path())
|
||||
if content_type != 'default':
|
||||
xbmcplugin.setContent(self._plugin_handle, content_type)
|
||||
ui.get_view_manager().set_view_mode(content_type)
|
||||
|
||||
if category_label is None:
|
||||
category_label = self.get_param('category_label')
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ from ...constants import (
|
|||
REFRESH_CONTAINER,
|
||||
RELOAD_ACCESS_MANAGER,
|
||||
REROUTE_PATH,
|
||||
SORT_DIR,
|
||||
SORT_METHOD,
|
||||
SYNC_LISTITEM,
|
||||
TRAKT_PAUSE_FLAG,
|
||||
VIDEO_ID,
|
||||
|
|
@ -417,7 +419,31 @@ class XbmcPlugin(AbstractPlugin):
|
|||
container = ui.get_property(CONTAINER_ID)
|
||||
position = ui.get_property(CONTAINER_POSITION)
|
||||
|
||||
# set alternative view mode
|
||||
view_manager = ui.get_view_manager()
|
||||
if view_manager.is_override_view_enabled():
|
||||
post_run_actions.append((
|
||||
view_manager.apply_view_mode,
|
||||
{
|
||||
'context': context,
|
||||
},
|
||||
))
|
||||
|
||||
if is_same_path:
|
||||
sort_method = kwargs.get(SORT_METHOD)
|
||||
sort_dir = kwargs.get(SORT_DIR)
|
||||
if sort_method and sort_dir:
|
||||
post_run_actions.append((
|
||||
view_manager.apply_sort_method,
|
||||
{
|
||||
'context': context,
|
||||
SORT_METHOD: sort_method,
|
||||
SORT_DIR: sort_dir,
|
||||
CONTAINER_POSITION: position if forced else None,
|
||||
},
|
||||
))
|
||||
position = None
|
||||
|
||||
if (container and position
|
||||
and (forced or position == 'current')
|
||||
and (not played_video_id or route)):
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ from .constants import (
|
|||
CHECK_SETTINGS,
|
||||
FOLDER_URI,
|
||||
PATHS,
|
||||
SORT_DIR,
|
||||
SORT_METHOD,
|
||||
)
|
||||
from .context import XbmcContext
|
||||
from .debug import Profiler
|
||||
|
|
@ -103,6 +105,20 @@ def run(context=_context,
|
|||
refresh = context.refresh_requested(force=True, off=True, params=params)
|
||||
new_params['refresh'] = refresh if refresh else 0
|
||||
|
||||
sort_method = (
|
||||
params.get(SORT_METHOD)
|
||||
or ui.get_infolabel('Container.SortMethod')
|
||||
)
|
||||
if sort_method:
|
||||
new_kwargs[SORT_METHOD] = sort_method
|
||||
|
||||
sort_dir = (
|
||||
params.get(SORT_DIR)
|
||||
or ui.get_infolabel('Container.SortOrder')
|
||||
)
|
||||
if sort_dir:
|
||||
new_kwargs[SORT_DIR] = sort_dir
|
||||
|
||||
if new_params:
|
||||
context.set_params(**new_params)
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ class AbstractContextUI(object):
|
|||
message_template=None):
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_view_manager(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
@staticmethod
|
||||
def on_keyboard_input(title, default='', hidden=False):
|
||||
raise NotImplementedError()
|
||||
|
|
|
|||
342
resources/lib/youtube_plugin/kodion/ui/xbmc/view_manager.py
Normal file
342
resources/lib/youtube_plugin/kodion/ui/xbmc/view_manager.py
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
|
||||
Copyright (C) 2014-2016 bromix (plugin.video.youtube)
|
||||
Copyright (C) 2016-2025 plugin.video.youtube
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-only
|
||||
See LICENSES/GPL-2.0-only for more information.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, division, unicode_literals
|
||||
|
||||
from ... import logging
|
||||
from ...compatibility import xbmc
|
||||
from ...constants import (
|
||||
CONTAINER_POSITION,
|
||||
CONTENT,
|
||||
SORT,
|
||||
SORT_DIR,
|
||||
SORT_METHOD,
|
||||
)
|
||||
|
||||
|
||||
class ViewManager(object):
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
SETTINGS = {
|
||||
'override': 'kodion.view.override', # (bool)
|
||||
'view_default': 'kodion.view.default', # (int)
|
||||
'view_type': 'kodion.view.{0}', # (int)
|
||||
}
|
||||
|
||||
SUPPORTED_TYPES_MAP = {
|
||||
CONTENT.LIST_CONTENT: 'default',
|
||||
CONTENT.VIDEO_CONTENT: 'episodes',
|
||||
}
|
||||
|
||||
STRING_MAP = {
|
||||
'prompt': 30777,
|
||||
'unsupported_skin': 10109,
|
||||
'supported_skin': 14240,
|
||||
'albums': 30035,
|
||||
'artists': 30034,
|
||||
'default': 30027,
|
||||
'episodes': 30028,
|
||||
'movies': 30029,
|
||||
'songs': 30033,
|
||||
'tvshows': 30032,
|
||||
}
|
||||
|
||||
SKIN_DATA = {
|
||||
'skin.confluence': {
|
||||
'default': (
|
||||
{'name': 'List', 'id': 50},
|
||||
{'name': 'Big List', 'id': 51},
|
||||
{'name': 'Thumbnail', 'id': 500}
|
||||
),
|
||||
'movies': (
|
||||
{'name': 'List', 'id': 50},
|
||||
{'name': 'Big List', 'id': 51},
|
||||
{'name': 'Thumbnail', 'id': 500},
|
||||
{'name': 'Media info', 'id': 504},
|
||||
{'name': 'Media info 2', 'id': 503}
|
||||
),
|
||||
'episodes': (
|
||||
{'name': 'List', 'id': 50},
|
||||
{'name': 'Big List', 'id': 51},
|
||||
{'name': 'Thumbnail', 'id': 500},
|
||||
{'name': 'Media info', 'id': 504},
|
||||
{'name': 'Media info 2', 'id': 503}
|
||||
),
|
||||
'tvshows': (
|
||||
{'name': 'List', 'id': 50},
|
||||
{'name': 'Big List', 'id': 51},
|
||||
{'name': 'Thumbnail', 'id': 500},
|
||||
{'name': 'Poster', 'id': 500},
|
||||
{'name': 'Wide', 'id': 505},
|
||||
{'name': 'Media info', 'id': 504},
|
||||
{'name': 'Media info 2', 'id': 503},
|
||||
{'name': 'Fanart', 'id': 508}
|
||||
),
|
||||
'musicvideos': (
|
||||
{'name': 'List', 'id': 50},
|
||||
{'name': 'Big List', 'id': 51},
|
||||
{'name': 'Thumbnail', 'id': 500},
|
||||
{'name': 'Media info', 'id': 504},
|
||||
{'name': 'Media info 2', 'id': 503}
|
||||
),
|
||||
'songs': (
|
||||
{'name': 'List', 'id': 50},
|
||||
{'name': 'Big List', 'id': 51},
|
||||
{'name': 'Thumbnail', 'id': 500},
|
||||
{'name': 'Media info', 'id': 506}
|
||||
),
|
||||
'albums': (
|
||||
{'name': 'List', 'id': 50},
|
||||
{'name': 'Big List', 'id': 51},
|
||||
{'name': 'Thumbnail', 'id': 500},
|
||||
{'name': 'Media info', 'id': 506}
|
||||
),
|
||||
'artists': (
|
||||
{'name': 'List', 'id': 50},
|
||||
{'name': 'Big List', 'id': 51},
|
||||
{'name': 'Thumbnail', 'id': 500},
|
||||
{'name': 'Media info', 'id': 506}
|
||||
)
|
||||
},
|
||||
'skin.aeon.nox.5': {
|
||||
'default': (
|
||||
{'name': 'List', 'id': 50},
|
||||
{'name': 'Episodes', 'id': 502},
|
||||
{'name': 'LowList', 'id': 501},
|
||||
{'name': 'BannerWall', 'id': 58},
|
||||
{'name': 'Shift', 'id': 57},
|
||||
{'name': 'Posters', 'id': 56},
|
||||
{'name': 'ShowCase', 'id': 53},
|
||||
{'name': 'Landscape', 'id': 52},
|
||||
{'name': 'InfoWall', 'id': 51}
|
||||
)
|
||||
},
|
||||
'skin.xperience1080+': {
|
||||
'default': (
|
||||
{'name': 'List', 'id': 50},
|
||||
{'name': 'Thumbnail', 'id': 500},
|
||||
),
|
||||
'episodes': (
|
||||
{'name': 'List', 'id': 50},
|
||||
{'name': 'Info list', 'id': 52},
|
||||
{'name': 'Fanart', 'id': 502},
|
||||
{'name': 'Landscape', 'id': 54},
|
||||
{'name': 'Poster', 'id': 55},
|
||||
{'name': 'Thumbnail', 'id': 500},
|
||||
{'name': 'Banner', 'id': 60}
|
||||
),
|
||||
},
|
||||
'skin.xperience1080': {
|
||||
'default': (
|
||||
{'name': 'List', 'id': 50},
|
||||
{'name': 'Thumbnail', 'id': 500},
|
||||
),
|
||||
'episodes': (
|
||||
{'name': 'List', 'id': 50},
|
||||
{'name': 'Info list', 'id': 52},
|
||||
{'name': 'Fanart', 'id': 502},
|
||||
{'name': 'Landscape', 'id': 54},
|
||||
{'name': 'Poster', 'id': 55},
|
||||
{'name': 'Thumbnail', 'id': 500},
|
||||
{'name': 'Banner', 'id': 60}
|
||||
),
|
||||
},
|
||||
'skin.estuary': {
|
||||
'default': (
|
||||
{'name': 'IconWall', 'id': 52},
|
||||
{'name': 'WideList', 'id': 55},
|
||||
),
|
||||
'videos': (
|
||||
{'name': 'Shift', 'id': 53},
|
||||
{'name': 'InfoWall', 'id': 54},
|
||||
{'name': 'WideList', 'id': 55},
|
||||
{'name': 'Wall', 'id': 500},
|
||||
),
|
||||
'episodes': (
|
||||
{'name': 'InfoWall', 'id': 54},
|
||||
{'name': 'Wall', 'id': 500},
|
||||
{'name': 'WideList', 'id': 55},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, context):
|
||||
self._context = context
|
||||
self._view_mode = None
|
||||
|
||||
def is_override_view_enabled(self):
|
||||
return self._context.get_settings().get_bool(self.SETTINGS['override'])
|
||||
|
||||
def get_wizard_steps(self):
|
||||
return (self.run,)
|
||||
|
||||
def run(self, context, step, steps, **_kwargs):
|
||||
localize = context.localize
|
||||
|
||||
skin_id = xbmc.getSkinDir()
|
||||
if skin_id in self.SKIN_DATA:
|
||||
status = localize(self.STRING_MAP['supported_skin'])
|
||||
else:
|
||||
status = localize(self.STRING_MAP['unsupported_skin'])
|
||||
prompt_text = localize(self.STRING_MAP['prompt'], (skin_id, status))
|
||||
|
||||
step += 1
|
||||
if context.get_ui().on_yes_no_input(
|
||||
'{youtube} - {setup_wizard} ({step}/{steps})'.format(
|
||||
youtube=localize('youtube'),
|
||||
setup_wizard=localize('setup_wizard'),
|
||||
step=step,
|
||||
steps=steps,
|
||||
),
|
||||
localize('setup_wizard.prompt.x', prompt_text)
|
||||
):
|
||||
for view_type in self.SUPPORTED_TYPES_MAP:
|
||||
self.update_view_mode(skin_id, view_type)
|
||||
return step
|
||||
|
||||
def get_view_mode(self):
|
||||
if self._view_mode is None:
|
||||
self.set_view_mode()
|
||||
return self._view_mode
|
||||
|
||||
def set_view_mode(self, view_type='default'):
|
||||
settings = self._context.get_settings()
|
||||
default = settings.get_int(self.SETTINGS['view_default'], 50)
|
||||
if view_type == 'default':
|
||||
view_mode = default
|
||||
else:
|
||||
view_type = self.SUPPORTED_TYPES_MAP.get(view_type, 'default')
|
||||
view_mode = settings.get_int(
|
||||
self.SETTINGS['view_type'].format(view_type), default
|
||||
)
|
||||
self._view_mode = view_mode
|
||||
|
||||
def update_view_mode(self, skin_id, view_type='default'):
|
||||
view_id = -1
|
||||
settings = self._context.get_settings()
|
||||
ui = self._context.get_ui()
|
||||
|
||||
content_type = self.SUPPORTED_TYPES_MAP[view_type]
|
||||
|
||||
if content_type not in self.STRING_MAP:
|
||||
self.log.warning('Unsupported content type: %r', content_type)
|
||||
return False
|
||||
title = self._context.localize(self.STRING_MAP[content_type])
|
||||
|
||||
view_setting = self.SETTINGS['view_type'].format(content_type)
|
||||
current_value = settings.get_int(view_setting)
|
||||
if current_value == -1:
|
||||
self.log.warning('No setting for content type: %r', content_type)
|
||||
return False
|
||||
|
||||
skin_data = self.SKIN_DATA.get(skin_id, {})
|
||||
view_type_data = skin_data.get(view_type) or skin_data.get(content_type)
|
||||
if view_type_data:
|
||||
items = []
|
||||
preselect = -1
|
||||
for view_data in view_type_data:
|
||||
view_id = view_data['id']
|
||||
items.append((view_data['name'], view_id))
|
||||
if view_id == current_value:
|
||||
preselect = len(items) - 1
|
||||
view_id = ui.on_select(title, items, preselect=preselect)
|
||||
else:
|
||||
self.log.warning('Unsupported view: %r', view_type)
|
||||
|
||||
if view_id == -1:
|
||||
result, view_id = ui.on_numeric_input(title, current_value)
|
||||
if not result:
|
||||
return False
|
||||
|
||||
if view_id > -1:
|
||||
settings.set_int(view_setting, view_id)
|
||||
settings.set_bool(self.SETTINGS['override'], True)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def apply_view_mode(self, context):
|
||||
view_mode = self.get_view_mode()
|
||||
if view_mode is None:
|
||||
return
|
||||
|
||||
self.log.debug('Applying view mode: %r', view_mode)
|
||||
context.execute('Container.SetViewMode(%s)' % view_mode)
|
||||
|
||||
@classmethod
|
||||
def apply_sort_method(cls, context, **kwargs):
|
||||
execute = context.execute
|
||||
get_infobool = xbmc.getCondVisibility
|
||||
|
||||
sort_method = (
|
||||
kwargs.get(SORT_METHOD)
|
||||
or CONTENT.VIDEO_CONTENT.join(('__', '__'))
|
||||
)
|
||||
sort_id = SORT.SORT_ID_MAPPING.get(sort_method)
|
||||
if sort_id is None:
|
||||
cls.log.warning('Unknown sort method: %r', sort_method)
|
||||
return
|
||||
|
||||
sort_dir = kwargs.get(SORT_DIR)
|
||||
_sort_dir = SORT.SORT_DIR.get(sort_dir)
|
||||
if _sort_dir is None:
|
||||
cls.log.warning('Invalid sort direction: %r', sort_dir)
|
||||
return
|
||||
|
||||
position = kwargs.get(CONTAINER_POSITION)
|
||||
if position is not None:
|
||||
context.get_ui().focus_container(position=position)
|
||||
|
||||
# Workaround for Container.SetSortMethod failing for some sort methods
|
||||
num_attempts = 0
|
||||
while num_attempts < 4:
|
||||
# Workaround for Container.SetSortMethod(0) being a noop
|
||||
# https://github.com/xbmc/xbmc/blob/7e1a55cb861342cd9062745161d88aca08dcead1/xbmc/windows/GUIMediaWindow.cpp#L502
|
||||
if sort_id == 0:
|
||||
# Sort by track number to reset sort order to default order
|
||||
if not num_attempts % 2:
|
||||
_sort_method = 'TRACKNUM'
|
||||
_sort_id = SORT.SORT_ID_MAPPING.get(_sort_method)
|
||||
sort_action = 'Container.SetSortMethod(%s)' % _sort_id
|
||||
# Then switch to previous sort method which is default/unsorted
|
||||
# as per the order set in XbmcContext.apply_content
|
||||
else:
|
||||
_sort_method = 'UNSORTED'
|
||||
_sort_id = SORT.SORT_ID_MAPPING.get(_sort_method)
|
||||
sort_action = 'Container.PreviousSortMethod'
|
||||
else:
|
||||
_sort_method = sort_method
|
||||
_sort_id = sort_id
|
||||
sort_action = 'Container.SetSortMethod(%s)' % _sort_id
|
||||
|
||||
cls.log.debug('Applying sort method: {method!r} ({id})',
|
||||
method=_sort_method,
|
||||
id=_sort_id)
|
||||
execute(sort_action)
|
||||
context.sleep(0.1)
|
||||
|
||||
if not get_infobool('Container.SortDirection(%s)' % _sort_dir):
|
||||
cls.log.debug('Applying sort direction: %r', sort_dir)
|
||||
# This builtin should be Container.SortDirection but has been
|
||||
# broken since Kodi v16
|
||||
# https://github.com/xbmc/xbmc/commit/ac870b64b16dfd0fc2bd0496c14529cf6d563f41
|
||||
execute('Container.SetSortDirection')
|
||||
context.sleep(0.1)
|
||||
|
||||
num_attempts += 1
|
||||
|
||||
if get_infobool('Container.SortMethod(%s)' % sort_id):
|
||||
break
|
||||
else:
|
||||
cls.log.warning('Unable to apply sorting:'
|
||||
' {sort_method!r} ({sort_id}) {sort_dir!r}',
|
||||
sort_method=sort_method,
|
||||
sort_id=sort_id,
|
||||
sort_dir=sort_dir)
|
||||
|
|
@ -12,6 +12,7 @@ from __future__ import absolute_import, division, unicode_literals
|
|||
|
||||
from weakref import proxy
|
||||
|
||||
from .view_manager import ViewManager
|
||||
from ..abstract_context_ui import AbstractContextUI
|
||||
from ... import logging
|
||||
from ...compatibility import string_type, xbmc, xbmcgui
|
||||
|
|
@ -47,6 +48,7 @@ class XbmcContextUI(AbstractContextUI):
|
|||
def __init__(self, context):
|
||||
super(XbmcContextUI, self).__init__()
|
||||
self._context = context
|
||||
self._view_manager = None
|
||||
|
||||
def create_progress_dialog(self,
|
||||
heading,
|
||||
|
|
@ -77,6 +79,12 @@ class XbmcContextUI(AbstractContextUI):
|
|||
),
|
||||
)
|
||||
|
||||
def get_view_manager(self):
|
||||
if self._view_manager is None:
|
||||
self._view_manager = ViewManager(self._context)
|
||||
|
||||
return self._view_manager
|
||||
|
||||
@staticmethod
|
||||
def on_keyboard_input(title, default='', hidden=False):
|
||||
# Starting with Gotham (13.X > ...)
|
||||
|
|
|
|||
|
|
@ -896,6 +896,35 @@
|
|||
</constraints>
|
||||
<control format="string" type="spinner"/>
|
||||
</setting>
|
||||
<setting id="kodion.view.override" type="boolean" label="30026" help="">
|
||||
<level>0</level>
|
||||
<default>false</default>
|
||||
<control type="toggle"/>
|
||||
</setting>
|
||||
<setting id="kodion.view.default" type="integer" parent="kodion.view.override" label="30027" help="">
|
||||
<level>0</level>
|
||||
<default>55</default>
|
||||
<dependencies>
|
||||
<dependency type="enable">
|
||||
<condition setting="kodion.view.override" operator="is">true</condition>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<control format="integer" type="edit">
|
||||
<heading>30027</heading>
|
||||
</control>
|
||||
</setting>
|
||||
<setting id="kodion.view.episodes" type="integer" parent="kodion.view.override" label="30028" help="">
|
||||
<level>0</level>
|
||||
<default>55</default>
|
||||
<dependencies>
|
||||
<dependency type="enable">
|
||||
<condition setting="kodion.view.override" operator="is">true</condition>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<control format="integer" type="edit">
|
||||
<heading>30028</heading>
|
||||
</control>
|
||||
</setting>
|
||||
</group>
|
||||
<group id="regional" label="14222">
|
||||
<setting id="youtube.language_region.configure" type="action" label="30527" help="">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue