Add custom show lists to home page

This commit is contained in:
adam 2015-04-07 11:10:50 +08:00 committed by Adam
parent e0b25b68cf
commit 65ce53b289
15 changed files with 260 additions and 119 deletions

View file

@ -25,6 +25,7 @@
* Fix display of search status for an alternative release after episode is manually set to "Failed" on the Display Show page
* Change handle more varieties of media quality
* Change to prevent another scheduled search when one of the same type is already running
* Add custom show lists to home page
### 0.8.3 (2015-04-25 08:48:00 UTC)

View file

@ -619,7 +619,7 @@ home.tmpl
border-radius:3px
}
#container, #container-anime{
#container{
margin:0 auto
}
@ -1591,6 +1591,12 @@ td.col-subtitles{
text-align:center
}
th.col-simple,
td.col-simple{
width: 150px;
text-align: center
}
th.col-status,
td.col-status{
width:200px;

View file

@ -242,6 +242,29 @@
</label>
</div>
<div class="field-pair">
<label for="showlist_tagview">
<span class="component-title">Show list split view style:</span>
<span class="component-desc">
<select id="showlist_tagview" name="showlist_tagview" class="form-control input-sm">
<option value="standard"#echo ('', $selected)['standard' == $sickbeard.SHOWLIST_TAGVIEW]#>No Lists</option>
<option value="anime"#echo ('', $selected)['anime' == $sickbeard.SHOWLIST_TAGVIEW]#>Show / Anime Lists</option>
<option value="custom"#echo ('', $selected)['custom' == $sickbeard.SHOWLIST_TAGVIEW]#>Custom Lists</option>
</select>
</span>
</label>
</div>
<div class="field-pair #if $sickbeard.SHOWLIST_TAGVIEW != 'custom' then 'hidden' else ''#">
<label for="show_tags">
<span class="component-title">Show tags:</span>
<span class="component-desc">
<input type="text" name="show_tags" id="show_tags" value="$show_tags" class="form-control input-sm input300">
<p class="clear-left note">show tags are to be selected from these comma seperated words</p>
</span>
</label>
</div>
<div class="field-pair">
<label for="use_imdb_info">
<span class="component-title">Enable IMDb info</span>

View file

@ -80,21 +80,12 @@ $displayshowlist.append('\t\t\t<optgroup label="%s">' % $curShowType)
#end if
#for $curShow in $curShowList
#set void = $displayshowlist.append('\t\t\t<option value="%s"%s>%s</option>' % ($curShow.indexerid, ('', ' selected="selected"')[$curShow == $show], $curShow.name))
#if $curShow == $show
#set $cur_sel = len($displayshowlist)
#end if
#end for
#if 1 < len($sortedShowLists)
#set void = $displayshowlist.append('\t\t\t</optgroup>')
#end if
#end for
#set $last_item = len($displayshowlist)
#set $prev_option = $displayshowlist[($cur_sel - 2, $last_item - 1)[1 == $cur_sel]]
#set $next_option = $displayshowlist[($cur_sel, 0)[$last_item == $cur_sel]]
#set $next_match = re.search(r'<opt[^>]+>(.*?)</opt', $prev_option)
#set $prev_match = re.search(r'<opt[^>]+>(.*?)</opt', $next_option)
#set $prev_title = 'Prev show' if not $next_match else 'Prev show, ' + $next_match.group(1)
#set $next_title = 'Next show' if not $prev_match else 'Next show, ' + $prev_match.group(1)
#slurp
<div class="navShow"><img id="prevShow" src="$sbRoot/images/prev.png" alt="&lt;&lt;" title="$prev_title" class="addQTip" /></div>
<select id="pickShow" class="form-control form-control-inline input-sm">

View file

@ -49,6 +49,8 @@
}
\$('#indexerLangSelectEdit').html(resultStr)
$('tag')
});
});
//-->
@ -65,6 +67,20 @@
<div id="editShow" class="stepDiv linefix">
<div class="field-pair #if $sickbeard.SHOWLIST_TAGVIEW != 'custom' then 'hidden' else ''#" style="margin-bottom:10px">
<label for="tag">
<span class="component-title">Tag</span>
<span class="component-desc">
<select name="tag" id="tag" class="form-control form-control-inline input-sm">
#for $tag in $sickbeard.SHOW_TAGS:
<option value="$tag" #if $tag == $show.tag then "selected=\"selected\"" else ""#>$tag</option>
#end for
</select>
<span>used for show list page split view</span>
</span>
</label>
</div>
<div class="field-pair">
<label for="paused">
<span class="component-title">Paused</span>

View file

@ -29,7 +29,7 @@
return (s || '').replace(/^(?:(?:A(?!\s+to)n?)|The)\s(\w)/i, '$1');
#else:
return (s || '');
#end if
#end if
},
type: 'text'
});
@ -39,20 +39,18 @@
is: function(s) {
return false;
},
format: function(s) {
format: function(s) {
return s.replace('hd1080p',5).replace('hd720p',4).replace('hd',3).replace('sd',2).replace('any',1).replace('custom',7);
},
type: 'numeric'
});
\$(document).ready(function(){
\$("img#network").on('error', function(){
\$(this).parent().text(\$(this).attr('alt'));
\$(this).remove();
});
\$(document).ready(function(){
\$("#showListTableShows:has(tbody tr)").tablesorter({
#for $curShowlist in $showlists
#set $curListID = $curShowlist[0]
#if $layout != 'poster'
\$("#$curListID:has(tbody tr)").tablesorter({
sortList: [[5,1],[1,0]],
textExtraction: {
0: function(node) { return \$(node).find("span").text().toLowerCase(); },
@ -74,49 +72,12 @@
},
sortStable: true
});
\$("#showListTableAnime:has(tbody tr)").tablesorter({
sortList: [[5,1],[1,0]],
textExtraction: {
0: function(node) { return \$(node).find("span").text().toLowerCase(); },
2: function(node) { return \$(node).find("span").text().toLowerCase(); },
3: function(node) { return \$(node).find("span").text().toLowerCase(); },
4: function(node) { return \$(node).find("span").text(); },
5: function(node) { return \$(node).find("img").attr("alt"); }
},
widgets: ['saveSort', 'zebra', 'stickyHeaders', 'filter'],
headers: {
0: { sorter: 'isoDate' },
1: { sorter: 'loadingNames' },
3: { sorter: 'quality' },
4: { sorter: 'eps' }
},
widgetOptions : {
filter_columnFilters: false,
filter_reset: '.resetanime'
},
sortStable: true
});
\$.tablesorter.filter.bindSearch( "#showListTableShows", \$('.search') );
#if $sickbeard.ANIME_SPLIT_HOME:
\$.tablesorter.filter.bindSearch( "#showListTableAnime", \$('.search') );
#end if
\$.tablesorter.filter.bindSearch( "#$curListID", \$('.search') );
#set $fuzzydate = 'airdate'
#if $sickbeard.FUZZY_DATING:
fuzzyMoment({
dtInline : #if $layout == 'poster' then "true" else "false"#,
containerClass : '.${fuzzydate}',
dateHasTime : false,
dateFormat : '${sickbeard.DATE_PRESET}',
timeFormat : '${sickbeard.TIME_PRESET}',
trimZero : #if $sickbeard.TRIM_ZERO then "true" else "false"#
});
#end if
#else
var \$container = [\$('#container'), \$('#container-anime')];
var \$container = [\$('#$curListID')]
jQuery.each(\$container, function (j) {
this.isotope({
@ -129,13 +90,13 @@
isFitWidth: true
},
getSortData: {
name: function( itemElem ) {
name: function( itemElem ) {
var name = \$( itemElem ).attr('data-name');
#if not $sickbeard.SORT_ARTICLE:
return (name || '').replace(/^(?:(?:A(?!\s+to)n?)|The)\s(\w)/i, '$1');
#else:
return (name || '');
#end if
#end if
},
network: '[data-network]',
date: function( itemElem ) {
@ -152,18 +113,37 @@
\$('#postersort').on( 'change', function() {
var sortValue = this.value;
\$('#container').isotope({ sortBy: sortValue });
\$('#container-anime').isotope({ sortBy: sortValue });
\$('#$curListID').isotope({ sortBy: sortValue });
\$.get(this.options[this.selectedIndex].getAttribute('data-sort'));
});
\$('#postersortdirection').on( 'change', function() {
var sortDirection = this.value;
sortDirection = sortDirection == 'true';
\$('#container').isotope({ sortAscending: sortDirection });
\$('#container-anime').isotope({ sortAscending: sortDirection });
\$('#$curListID').isotope({ sortAscending: sortDirection });
\$.get(this.options[this.selectedIndex].getAttribute('data-sort'));
});
#end if
#end for
\$("img#network").on('error', function(){
\$(this).parent().text(\$(this).attr('alt'));
\$(this).remove();
});
#set $fuzzydate = 'airdate'
#if $sickbeard.FUZZY_DATING:
fuzzyMoment({
dtInline : #if $layout == 'poster' then "true" else "false"#,
containerClass : '.${fuzzydate}',
dateHasTime : false,
dateFormat : '${sickbeard.DATE_PRESET}',
timeFormat : '${sickbeard.TIME_PRESET}',
trimZero : #if $sickbeard.TRIM_ZERO then "true" else "false"#
});
#end if
#if $sickbeard.HOME_SEARCH_FOCUS
\$('#search_show_name').focus();
#end if
@ -172,9 +152,9 @@
//-->
</script>
#if $varExists('header')
<h1 class="header" style="margin-bottom:0">$header</h1>
#else
#if $varExists('header')
<h1 class="header" style="margin-bottom:0">$showlists[0][1]</h1>
#else
<h1 class="title" style="margin-bottom:0">$title</h1>
#end if
@ -222,14 +202,15 @@
#for $curShowlist in $showlists:
#set $curListType = $curShowlist[0]
#set $myShowList = $list($curShowlist[1])
#if $curListType == "Anime":
<h1 class="header">Anime List</h1>
#set $curListID = $curShowlist[0]
#set $curListName = $curShowlist[1]
#set $myShowList = $list($curShowlist[2])
#if $curShowlist != $showlists[0]:
<h1 class="header">$curListName</h1>
#end if
#if $layout == 'poster':
<div id=#if $curListType == "Anime" and $layout == 'poster' then "container-anime" else "container"# class="clearfix">
<div id="$curListID" class="clearfix container">
<div class="posterview">
#for $curLoadingShow in $sickbeard.showQueueScheduler.action.loadingShowList:
@ -406,18 +387,18 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
#else
<table id="showListTable$curListType" class="tablesorter" cellspacing="1" border="0" cellpadding="0">
<table id="$curListID" class="tablesorter" cellspacing="1" border="0" cellpadding="0">
<thead>
<tr>
<th class="nowrap">Next Ep</th>
<th>Show</th>
<th>Network</th>
<th>Quality</th>
<th>Downloads</th>
<th>Active</th>
<th>Status</th>
</tr>
<tr>
<th class="col-airdate">Next Ep</th>
<th class="col-name">Show</th>
<th class="col-simple">Network</th>
<th class="col-simple">Quality</th>
<th class="col-simple">Downloads</th>
<th class="col-simple">Active</th>
<th class="col-simple">Status</th>
</tr>
</thead>
<tfoot>

View file

@ -26,6 +26,22 @@
#set global $bestQualities = $qualities[1]
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_qualityChooser.tmpl')
</div>
<div class="field-pair #if $sickbeard.SHOWLIST_TAGVIEW != 'custom' then 'hidden' else ''#" style="margin-bottom:10px">
<label for="tag">
<span class="component-title">Tag</span>
<span class="component-desc">
<select name="tag" id="tag" class="form-control form-control-inline input-sm">
#for $tag in $sickbeard.SHOW_TAGS:
<option value="$tag" #if $tag == $sickbeard.DEFAULT_SHOW_TAG then "selected=\"selected\"" else ""#>$tag</option>
#end for
</select>
<span>used for show list page split view</span>
</span>
</label>
</div>
#try:
#if True == $enable_default_wanted:
<div class="field-pair alt">

View file

@ -164,6 +164,18 @@
</div><br />
</div>
<div class="optionWrapper #if $sickbeard.SHOWLIST_TAGVIEW != 'custom' then 'hidden' else ''#">
<span class="selectTitle">Tag</span>
<div class="selectChoices">
<select id="edit_tag" name="tag" class="form-control form-control-inline input-sm">
<option value="keep">&lt; keep &gt;</option>
#for $tag in $sickbeard.SHOW_TAGS:
<option value="$tag" #if $tag_value == $tag then $selected else ''#>$tag</option>
#end for
</select>
</div><br />
</div>
<div class="optionWrapper" style="font-size:13px;margin-top:15px">
<span class="separator" style="font-size:1.2em; font-weight:700">*</span>
Changing these settings will cause selected shows to be refreshed

View file

@ -61,7 +61,7 @@ CFG = None
CONFIG_FILE = None
# This is the version of the config we EXPECT to find
CONFIG_VERSION = 10
CONFIG_VERSION = 11
# Default encryption version (0 for None)
ENCRYPTION_VERSION = 0
@ -158,6 +158,9 @@ DEBUG = False
DISPLAY_BACKGROUND = False
DISPLAY_BACKGROUND_TRANSPARENT = None
DISPLAY_ALL_SEASONS = True
SHOW_TAGS = []
DEFAULT_SHOW_TAG = ''
SHOWLIST_TAGVIEW = ''
USE_LISTVIEW = False
METADATA_XBMC = None
@ -531,7 +534,8 @@ def initialize(consoleLogging=True):
AUTOPOSTPROCESSER_FREQUENCY, DEFAULT_AUTOPOSTPROCESSER_FREQUENCY, MIN_AUTOPOSTPROCESSER_FREQUENCY, \
ANIME_DEFAULT, NAMING_ANIME, USE_ANIDB, ANIDB_USERNAME, ANIDB_PASSWORD, ANIDB_USE_MYLIST, \
ANIME_SPLIT_HOME, SCENE_DEFAULT, BACKLOG_DAYS, SEARCH_UNAIRED, ANIME_TREAT_AS_HDTV, \
COOKIE_SECRET, USE_IMDB_INFO, DISPLAY_BACKGROUND, DISPLAY_BACKGROUND_TRANSPARENT, DISPLAY_ALL_SEASONS
COOKIE_SECRET, USE_IMDB_INFO, DISPLAY_BACKGROUND, DISPLAY_BACKGROUND_TRANSPARENT, DISPLAY_ALL_SEASONS, \
SHOW_TAGS, DEFAULT_SHOW_TAG, SHOWLIST_TAGVIEW
if __INITIALIZED__:
return False
@ -605,6 +609,9 @@ def initialize(consoleLogging=True):
DISPLAY_BACKGROUND = bool(check_setting_int(CFG, 'General', 'display_background', 0))
DISPLAY_BACKGROUND_TRANSPARENT = check_setting_str(CFG, 'General', 'display_background_transparent', 'transparent')
DISPLAY_ALL_SEASONS = bool(check_setting_int(CFG, 'General', 'display_all_seasons', 1))
SHOW_TAGS = check_setting_str(CFG, 'GUI', 'show_tags', 'Show List').split(',')
DEFAULT_SHOW_TAG = check_setting_str(CFG, 'GUI', 'default_show_tag', 'Show List')
SHOWLIST_TAGVIEW = check_setting_str(CFG, 'GUI', 'showlist_tagview', 'standard')
ACTUAL_LOG_DIR = check_setting_str(CFG, 'General', 'log_dir', 'Logs')
# put the log dir inside the data dir, unless an absolute path
@ -1842,6 +1849,9 @@ def save_config():
new_config['GUI']['episode_view_missed_range'] = int(EPISODE_VIEW_MISSED_RANGE)
new_config['GUI']['poster_sortby'] = POSTER_SORTBY
new_config['GUI']['poster_sortdir'] = POSTER_SORTDIR
new_config['GUI']['show_tags'] = ','.join(SHOW_TAGS)
new_config['GUI']['showlist_tagview'] = SHOWLIST_TAGVIEW
new_config['GUI']['default_tag'] = DEFAULT_SHOW_TAG
new_config['Subtitles'] = {}
new_config['Subtitles']['use_subtitles'] = int(USE_SUBTITLES)
@ -1864,7 +1874,6 @@ def save_config():
new_config['ANIDB']['anidb_use_mylist'] = int(ANIDB_USE_MYLIST)
new_config['ANIME'] = {}
new_config['ANIME']['anime_split_home'] = int(ANIME_SPLIT_HOME)
new_config['ANIME']['anime_treat_as_hdtv'] = int(ANIME_TREAT_AS_HDTV)
new_config.write()

View file

@ -441,7 +441,9 @@ class ConfigMigrator():
6: 'Rename daily search to recent search',
7: 'Rename coming episodes to episode view',
8: 'Disable searches on start',
9: 'Rename pushbullet variables'}
9: 'Rename pushbullet variables',
10: 'Reset backlog frequency to default',
11: 'Migrate anime split view to new layout'}
def migrate_config(self):
""" Calls each successive migration until the config is the same version as SG expects """
@ -740,4 +742,9 @@ class ConfigMigrator():
def _migrate_v10(self):
# reset backlog frequency to default
sickbeard.BACKLOG_FREQUENCY = sickbeard.DEFAULT_BACKLOG_FREQUENCY
sickbeard.BACKLOG_FREQUENCY = sickbeard.DEFAULT_BACKLOG_FREQUENCY
def _migrate_v11(self):
if check_setting_int(self.config_obj, 'ANIME', 'anime_split_home', ''):
sickbeard.SHOWLIST_TAGVIEW = 'anime'
else:
sickbeard.SHOWLIST_TAGVIEW = 'default'

View file

@ -27,7 +27,7 @@ from sickbeard import encodingKludge as ek
from sickbeard.name_parser.parser import NameParser, InvalidNameException, InvalidShowException
MIN_DB_VERSION = 9 # oldest db version we support migrating from
MAX_DB_VERSION = 20002
MAX_DB_VERSION = 20003
class MainSanityCheck(db.DBSanityCheck):
@ -1034,3 +1034,13 @@ class AddTvShowOverview(db.SchemaUpgrade):
self.setDBVersion(20002)
return self.checkDBVersion()
# 20002 -> 20003
class AddTvShowTags(db.SchemaUpgrade):
def execute(self):
db.backup_database('sickbeard.db', self.checkDBVersion())
logger.log(u'Adding tag to tv_shows')
self.addColumn('tv_shows', 'tag', 'TEXT', 'Show List')
self.setDBVersion(20003)
return self.checkDBVersion()

View file

@ -421,6 +421,7 @@ def MigrationCode(myDB):
20000: sickbeard.mainDB.DBIncreaseTo20001,
20001: sickbeard.mainDB.AddTvShowOverview,
20002: sickbeard.mainDB.AddTvShowTags,
# 20002: sickbeard.mainDB.AddCoolSickGearFeature3,
}

View file

@ -135,10 +135,10 @@ class ShowQueue(generic_queue.GenericQueue):
def addShow(self, indexer, indexer_id, showDir, default_status=None, quality=None, flatten_folders=None,
lang="en", subtitles=None, anime=None, scene=None, paused=None, blacklist=None, whitelist=None,
wanted_begin=None, wanted_latest=None):
wanted_begin=None, wanted_latest=None, tag=None):
queueItemObj = QueueItemAdd(indexer, indexer_id, showDir, default_status, quality, flatten_folders, lang,
subtitles, anime, scene, paused, blacklist, whitelist,
wanted_begin, wanted_latest)
wanted_begin, wanted_latest, tag)
self.add_item(queueItemObj)
@ -194,7 +194,7 @@ class ShowQueueItem(generic_queue.QueueItem):
class QueueItemAdd(ShowQueueItem):
def __init__(self, indexer, indexer_id, showDir, default_status, quality, flatten_folders, lang, subtitles, anime,
scene, paused, blacklist, whitelist, default_wanted_begin, default_wanted_latest):
scene, paused, blacklist, whitelist, default_wanted_begin, default_wanted_latest, tag):
self.indexer = indexer
self.indexer_id = indexer_id
@ -211,6 +211,7 @@ class QueueItemAdd(ShowQueueItem):
self.paused = paused
self.blacklist = blacklist
self.whitelist = whitelist
self.tag = tag
self.show = None
@ -299,6 +300,7 @@ class QueueItemAdd(ShowQueueItem):
self.show.anime = self.anime if self.anime != None else sickbeard.ANIME_DEFAULT
self.show.scene = self.scene if self.scene != None else sickbeard.SCENE_DEFAULT
self.show.paused = self.paused if self.paused != None else False
self.show.tag = self.tag
if self.show.anime:
self.show.release_groups = BlackAndWhiteList(self.show.indexerid)

View file

@ -99,6 +99,7 @@ class TVShow(object):
self._rls_ignore_words = ""
self._rls_require_words = ""
self._overview = ''
self._tag = ''
self.dirty = True
@ -143,6 +144,7 @@ class TVShow(object):
rls_ignore_words = property(lambda self: self._rls_ignore_words, dirty_setter("_rls_ignore_words"))
rls_require_words = property(lambda self: self._rls_require_words, dirty_setter("_rls_require_words"))
overview = property(lambda self: self._overview, dirty_setter('_overview'))
tag = property(lambda self: self._tag, dirty_setter('_tag'))
@property
def is_anime(self):
@ -848,6 +850,10 @@ class TVShow(object):
if not self.overview:
self.overview = sqlResults[0]['overview']
self.tag = sqlResults[0]['tag']
if not self.tag:
self.tag = 'Show List'
logger.log(str(self.indexerid) + u': Show info [%s] loaded from database' % self.name)
# Get IMDb_info from database
@ -1204,7 +1210,8 @@ class TVShow(object):
"last_update_indexer": self.last_update_indexer,
"rls_ignore_words": self.rls_ignore_words,
'rls_require_words': self.rls_require_words,
'overview': self.overview
'overview': self.overview,
'tag': self.tag,
}
myDB = db.DBConnection()

View file

@ -27,7 +27,6 @@ import random
import traceback
from mimetypes import MimeTypes
from Cheetah.Template import Template
import sickbeard
@ -60,6 +59,11 @@ try:
except ImportError:
from lib import simplejson as json
try:
from collections import OrderedDict
except ImportError:
from requests.packages.urllib3.packages.ordered_dict import OrderedDict
class PageTemplate(Template):
def __init__(self, headers, *args, **KWs):
@ -573,18 +577,24 @@ class Home(MainHandler):
def showlistView(self):
t = PageTemplate(headers=self.request.headers, file='home.tmpl')
if sickbeard.ANIME_SPLIT_HOME:
shows = []
anime = []
for show in sickbeard.showList:
if show.is_anime:
anime.append(show)
else:
shows.append(show)
t.showlists = [['Shows', shows],
['Anime', anime]]
t.showlists = []
index = 0
if sickbeard.SHOWLIST_TAGVIEW == 'custom':
for name in sickbeard.SHOW_TAGS:
results = filter(lambda x: x.tag == name, sickbeard.showList)
if results:
t.showlists.append(['container%s' % index, name, results])
index += 1
elif sickbeard.SHOWLIST_TAGVIEW == 'anime':
show_results = filter(lambda x: not x.anime, sickbeard.showList)
anime_results = filter(lambda x: x.anime, sickbeard.showList)
if show_results:
t.showlists.append(['container%s' % index, 'Show List', show_results])
index += 1
if anime_results:
t.showlists.append(['container%s' % index, 'Anime List', anime_results])
else:
t.showlists = [['Shows', sickbeard.showList]]
t.showlists.append(['container%s' % index, 'Show List', sickbeard.showList])
t.submenu = self.HomeMenu()
t.layout = sickbeard.HOME_LAYOUT
@ -1131,7 +1141,13 @@ class Home(MainHandler):
def titler(x):
return (remove_article(x), x)[not x or sickbeard.SORT_ARTICLE]
if sickbeard.ANIME_SPLIT_HOME:
if sickbeard.SHOWLIST_TAGVIEW == 'custom':
t.sortedShowLists = []
for tag in sickbeard.SHOW_TAGS:
results = filter(lambda x: x.tag == tag, sickbeard.showList)
if results:
t.sortedShowLists.append([tag, sorted(results, lambda x, y: cmp(titler(x.name), titler(y.name)))])
elif sickbeard.SHOWLIST_TAGVIEW == 'anime':
shows = []
anime = []
for show in sickbeard.showList:
@ -1144,14 +1160,22 @@ class Home(MainHandler):
else:
t.sortedShowLists = [
['Shows', sorted(sickbeard.showList, lambda x, y: cmp(titler(x.name), titler(y.name)))]]
['Show List', sorted(sickbeard.showList, lambda x, y: cmp(titler(x.name), titler(y.name)))]]
tvshows = []
tvshow_names = []
for tvshow_types in t.sortedShowLists:
for tvshow in tvshow_types[1]:
tvshows.append(tvshow.indexerid)
tvshow_names.append(tvshow.name)
if showObj.indexerid == tvshow.indexerid:
cur_sel = len(tvshow_names)
t.tvshow_id_csv = ','.join(str(x) for x in tvshows)
last_item = len(tvshow_names)
t.prev_title = 'Prev show, %s' % tvshow_names[(cur_sel - 2, last_item - 1)[1 == cur_sel]]
t.next_title = 'Next show, %s' % tvshow_names[(cur_sel, 0)[last_item == cur_sel]]
t.bwl = None
if showObj.is_anime:
t.bwl = showObj.release_groups
@ -1196,7 +1220,7 @@ class Home(MainHandler):
flatten_folders=None, paused=None, directCall=False, air_by_date=None, sports=None, dvdorder=None,
indexerLang=None, subtitles=None, archive_firstmatch=None, rls_ignore_words=None,
rls_require_words=None, anime=None, blacklist=None, whitelist=None,
scene=None):
scene=None, tag=None):
if show is None:
errString = 'Invalid show ID: ' + str(show)
@ -1275,7 +1299,7 @@ class Home(MainHandler):
if type(exceptions_list) != list:
exceptions_list = [exceptions_list]
# If directCall from mass_edit_update no scene exceptions handling or blackandwhite list handling
# If directCall from mass_edit_update no scene exceptions handling or blackandwhite list handling or tags
if directCall:
do_update_exceptions = False
else:
@ -1320,6 +1344,7 @@ class Home(MainHandler):
showObj.sports = sports
showObj.subtitles = subtitles
showObj.air_by_date = air_by_date
showObj.tag = tag
if not directCall:
showObj.lang = indexer_lang
@ -2320,7 +2345,7 @@ class NewHomeAddShows(Home):
def addNewShow(self, whichSeries=None, indexerLang='en', rootDir=None, defaultStatus=None,
anyQualities=None, bestQualities=None, flatten_folders=None, subtitles=None,
fullShowPath=None, other_shows=None, skipShow=None, providedIndexer=None, anime=None,
scene=None, blacklist=None, whitelist=None, wanted_begin=None, wanted_latest=None):
scene=None, blacklist=None, whitelist=None, wanted_begin=None, wanted_latest=None, tag=None):
"""
Receive tvdb id, dir, and other options and create a show from them. If extra show dirs are
provided then it forwards back to newShow, if not it goes to /home.
@ -2426,7 +2451,7 @@ class NewHomeAddShows(Home):
sickbeard.showQueueScheduler.action.addShow(indexer, indexer_id, show_dir, int(defaultStatus), newQuality,
flatten_folders, indexerLang, subtitles, anime,
scene, None, blacklist, whitelist,
wanted_begin, wanted_latest) # @UndefinedVariable
wanted_begin, wanted_latest, tag) # @UndefinedVariable
# ui.notifications.message('Show added', 'Adding the specified show into ' + show_dir)
return finishAddShow()
@ -2833,6 +2858,9 @@ class Manage(MainHandler):
paused_all_same = True
last_paused = None
tag_all_same = True
last_tag = None
anime_all_same = True
last_anime = None
@ -2874,6 +2902,13 @@ class Manage(MainHandler):
else:
last_paused = curShow.paused
if tag_all_same:
# if we had a value already and this value is different then they're not all the same
if last_tag not in (None, curShow.tag):
tag_all_same = False
else:
last_tag = curShow.tag
if anime_all_same:
# if we had a value already and this value is different then they're not all the same
if last_anime not in (None, curShow.is_anime):
@ -2920,6 +2955,7 @@ class Manage(MainHandler):
t.showList = toEdit
t.archive_firstmatch_value = last_archive_firstmatch if archive_firstmatch_all_same else None
t.paused_value = last_paused if paused_all_same else None
t.tag_value = last_tag if tag_all_same else None
t.anime_value = last_anime if anime_all_same else None
t.flatten_folders_value = last_flatten_folders if flatten_folders_all_same else None
t.quality_value = last_quality if quality_all_same else None
@ -2931,10 +2967,9 @@ class Manage(MainHandler):
return t.respond()
def massEditSubmit(self, archive_firstmatch=None, paused=None, anime=None, sports=None, scene=None, flatten_folders=None,
quality_preset=False,
subtitles=None, air_by_date=None, anyQualities=[], bestQualities=[], toEdit=None, *args,
**kwargs):
def massEditSubmit(self, archive_firstmatch=None, paused=None, anime=None, sports=None, scene=None,
flatten_folders=None, quality_preset=False, subtitles=None, air_by_date=None, anyQualities=[],
bestQualities=[], toEdit=None, tag=None, *args, **kwargs):
dir_map = {}
for cur_arg in kwargs:
@ -2973,6 +3008,12 @@ class Manage(MainHandler):
new_paused = True if paused == 'enable' else False
new_paused = 'on' if new_paused else 'off'
if tag == 'keep':
new_tag = showObj.tag
else:
new_tag = tag
if anime == 'keep':
new_anime = showObj.anime
else:
@ -3022,7 +3063,7 @@ class Manage(MainHandler):
paused=new_paused, sports=new_sports,
subtitles=new_subtitles, anime=new_anime,
scene=new_scene, air_by_date=new_air_by_date,
directCall=True)
tag=new_tag, directCall=True)
if curErrors:
logger.log(u'Errors: ' + str(curErrors), logger.ERROR)
@ -3376,6 +3417,7 @@ class ConfigGeneral(Config):
t = PageTemplate(headers=self.request.headers, file='config_general.tmpl')
t.submenu = self.ConfigMenu
t.show_tags = ','.join(sickbeard.SHOW_TAGS)
return t.respond()
def saveRootDirs(self, rootDirString=None):
@ -3430,7 +3472,8 @@ class ConfigGeneral(Config):
proxy_setting=None, proxy_indexers=None, anon_redirect=None, git_path=None, git_remote=None, calendar_unprotected=None,
fuzzy_dating=None, trim_zero=None, date_preset=None, date_preset_na=None, time_preset=None,
indexer_timeout=None, rootDir=None, theme_name=None, default_home=None, use_imdb_info=None,
display_background=None, display_background_transparent=None, display_all_seasons=None):
display_background=None, display_background_transparent=None, display_all_seasons=None,
show_tags=None, showlist_tagview=None):
results = []
@ -3455,6 +3498,22 @@ class ConfigGeneral(Config):
sickbeard.SORT_ARTICLE = config.checkbox_to_value(sort_article)
sickbeard.CPU_PRESET = cpu_preset
sickbeard.FILE_LOGGING_PRESET = file_logging_preset
sickbeard.SHOWLIST_TAGVIEW = showlist_tagview
# Convert csv to list, must always contain Show List as a default fallback and strip leading/trailing spaces
show_tags = show_tags.split(',')
if 'Show List' not in show_tags:
show_tags.append('Show List')
show_tags = [x.strip() for x in show_tags if x]
# Don't allow deletion of tags that are still assigned to shows
myDB = db.DBConnection('sickbeard.db')
sql_results = myDB.select('SELECT DISTINCT tag FROM tv_shows')
if sql_results:
for tag in sql_results[0]:
show_tags.append(tag)
sickbeard.SHOW_TAGS = list(OrderedDict.fromkeys(show_tags)) # remove dupes
logger.log_set_level()