diff --git a/resources/lib/youtube_plugin/kodion/abstract_provider.py b/resources/lib/youtube_plugin/kodion/abstract_provider.py
index 1998c20b6..09633ce21 100644
--- a/resources/lib/youtube_plugin/kodion/abstract_provider.py
+++ b/resources/lib/youtube_plugin/kodion/abstract_provider.py
@@ -92,6 +92,7 @@ def run_wizard(self, context):
settings.set_bool(settings.SETUP_WIZARD, False)
wizard_steps = self.get_wizard_steps(context)
+ wizard_steps.extend(ui.get_view_manager().get_wizard_steps())
if (wizard_steps and ui.on_yes_no_input(
context.get_name(), context.localize('setup_wizard.execute')
diff --git a/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py b/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
index 0e51d6a02..1071a28e1 100644
--- a/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
+++ b/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
@@ -413,6 +413,7 @@ def set_content(self, content_type, sub_type=None, category_label=None):
type=(sub_type or content_type), path=self.get_path()
))
xbmcplugin.setContent(self._plugin_handle, content_type)
+ self.get_ui().get_view_manager().set_view_mode(content_type)
if category_label is None:
category_label = self.get_param('category_label')
if category_label:
diff --git a/resources/lib/youtube_plugin/kodion/plugin/xbmc/xbmc_runner.py b/resources/lib/youtube_plugin/kodion/plugin/xbmc/xbmc_runner.py
index c06ae42d4..08ef84302 100644
--- a/resources/lib/youtube_plugin/kodion/plugin/xbmc/xbmc_runner.py
+++ b/resources/lib/youtube_plugin/kodion/plugin/xbmc/xbmc_runner.py
@@ -106,6 +106,15 @@ def run(self, provider, context):
updateListing=options.get(provider.RESULT_UPDATE_LISTING, False),
cacheToDisc=options.get(provider.RESULT_CACHE_TO_DISC, True)
)
+
+ # set alternative view mode
+ view_manager = ui.get_view_manager()
+ if view_manager.is_override_view_enabled():
+ view_mode = view_manager.get_view_mode()
+ if view_mode is not None:
+ context.log_debug('Override view mode to "%d"' % view_mode)
+ context.execute('Container.SetViewMode(%d)' % view_mode)
+
return succeeded
def _set_resolved_url(self, context, base_item, show_fanart):
diff --git a/resources/lib/youtube_plugin/kodion/ui/abstract_context_ui.py b/resources/lib/youtube_plugin/kodion/ui/abstract_context_ui.py
index e9a2fa780..4bf1f0c9c 100644
--- a/resources/lib/youtube_plugin/kodion/ui/abstract_context_ui.py
+++ b/resources/lib/youtube_plugin/kodion/ui/abstract_context_ui.py
@@ -18,6 +18,9 @@ def __init__(self):
def create_progress_dialog(self, heading, text=None, background=False):
raise NotImplementedError()
+ def get_view_manager(self):
+ raise NotImplementedError()
+
def on_keyboard_input(self, title, default='', hidden=False):
raise NotImplementedError()
diff --git a/resources/lib/youtube_plugin/kodion/ui/xbmc/view_manager.py b/resources/lib/youtube_plugin/kodion/ui/xbmc/view_manager.py
new file mode 100644
index 000000000..f0509d2bc
--- /dev/null
+++ b/resources/lib/youtube_plugin/kodion/ui/xbmc/view_manager.py
@@ -0,0 +1,236 @@
+# -*- coding: utf-8 -*-
+"""
+
+ Copyright (C) 2014-2016 bromix (plugin.video.youtube)
+ Copyright (C) 2016-2018 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 ...compatibility import xbmc
+from ...constants import content
+
+
+class ViewManager(object):
+ 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',
+ }
+
+ TYPES_STRING_MAP = {
+ '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):
+ skin_id = xbmc.getSkinDir()
+ if skin_id not in self.SKIN_DATA:
+ self._context.log_info('ViewManager: Unsupported skin |{skin}|'.format(
+ skin=skin_id
+ ))
+ return [
+ (self.update_view_mode, (skin_id, view_type,))
+ for view_type in self.SUPPORTED_TYPES_MAP
+ ]
+
+ 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
+ log_info = self._context.log_info
+ settings = self._context.get_settings()
+ ui = self._context.get_ui()
+
+ content_type = self.SUPPORTED_TYPES_MAP[view_type]
+
+ if content_type not in self.TYPES_STRING_MAP:
+ log_info('ViewManager: Unsupported content type |{content_type}|'
+ .format(content_type=content_type))
+ return
+ title = self._context.localize(self.TYPES_STRING_MAP[content_type])
+
+ view_setting = self.SETTINGS['view_type'].format(content_type)
+ current_value = settings.get_int(view_setting)
+ if current_value == -1:
+ log_info('ViewManager: No setting for content type |{content_type}|'
+ .format(content_type=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 = [
+ (view_data['name'], view_data['id'])
+ for view_data in view_type_data
+ ]
+ view_id = ui.on_select(title, items, preselect=current_value)
+ else:
+ log_info('ViewManager: Unsupported view |{view_type}|'
+ .format(view_type=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
diff --git a/resources/lib/youtube_plugin/kodion/ui/xbmc/xbmc_context_ui.py b/resources/lib/youtube_plugin/kodion/ui/xbmc/xbmc_context_ui.py
index 0180834f8..62a79cf50 100644
--- a/resources/lib/youtube_plugin/kodion/ui/xbmc/xbmc_context_ui.py
+++ b/resources/lib/youtube_plugin/kodion/ui/xbmc/xbmc_context_ui.py
@@ -10,6 +10,7 @@
from __future__ import absolute_import, division, unicode_literals
+from .view_manager import ViewManager
from .xbmc_progress_dialog import XbmcProgressDialog, XbmcProgressDialogBG
from ..abstract_context_ui import AbstractContextUI
from ...compatibility import xbmc, xbmcgui
@@ -24,6 +25,7 @@ def __init__(self, xbmc_addon, context):
self._xbmc_addon = xbmc_addon
self._context = context
+ self._view_manager = None
def create_progress_dialog(self, heading, text=None, background=False):
if background:
@@ -31,6 +33,11 @@ def create_progress_dialog(self, heading, text=None, background=False):
return XbmcProgressDialog(heading, text)
+ def get_view_manager(self):
+ if self._view_manager is None:
+ self._view_manager = ViewManager(self._context)
+
+ return self._view_manager
def on_keyboard_input(self, title, default='', hidden=False):
# Starting with Gotham (13.X > ...)
diff --git a/resources/settings.xml b/resources/settings.xml
index 45e7a332d..6590a75ca 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -703,6 +703,37 @@
+
+ 0
+ false
+
+
+
+ 0
+ 55
+
+
+ true
+
+
+
+ 30027
+
+
+
+ 0
+ 55
+
+
+ true
+
+
+
+ 30028
+
+
+
+
0
20
@@ -721,7 +752,7 @@
-
+
0
en-US