diff --git a/gui/slick/css/light.css b/gui/slick/css/light.css index 0b5212cc10c070a0d898b1ee4f521ce98bd42071..fa568f726ac8cf2c66dee018212a1a754ef8f2a5 100644 --- a/gui/slick/css/light.css +++ b/gui/slick/css/light.css @@ -64,6 +64,14 @@ displayShow.mako text-align: left !important; } +/* ======================================================================= +testRename.mako +========================================================================== */ + +tr.seasonheader { + color: #000 !important; +} + /* ======================================================================= comingEpisodes.mako ========================================================================== */ diff --git a/gui/slick/css/style.css b/gui/slick/css/style.css index 1b84437cb1aeb512ffcd58bbac3f996e910a6c75..1409ab909d8079d3d3b1b8b22eaad0a9dca0e25e 100644 --- a/gui/slick/css/style.css +++ b/gui/slick/css/style.css @@ -2142,6 +2142,22 @@ input, textarea, select, .uneditable-input { color: #ffffff; } +.navbar-default .navbar-nav > li.navbar-split > a { + display: inline-block; + float: left; +} + +.navbar-default .navbar-nav > li.navbar-split > a:first-child { + border-width: 0 1px 0 0; + border-style: solid; + border-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 20%, #ddd, rgba(0, 0, 0, 0) 80%) 1 100%; + padding-right: 8px; +} + +.navbar-default .navbar-nav > li.navbar-split > a:nth-child(2) { + padding-left: 8px; +} + @media (max-width: 767px) { .navbar-default .navbar-nav .open .dropdown-menu > li > a { color: #dddddd; diff --git a/gui/slick/js/config.js b/gui/slick/js/config.js new file mode 100644 index 0000000000000000000000000000000000000000..7c852360b89e1f1ea408996f73d007bc5d69b81d --- /dev/null +++ b/gui/slick/js/config.js @@ -0,0 +1,115 @@ +$(document).ready(function(){ + $(".enabler").each(function(){ + if (!$(this).prop('checked')) $('#content_'+$(this).attr('id')).hide(); + }); + + $(".enabler").click(function() { + if ($(this).prop('checked')){ + $('#content_'+$(this).attr('id')).fadeIn("fast", "linear"); + } else { + $('#content_'+$(this).attr('id')).fadeOut("fast", "linear"); + } + }); + + $(".viewIf").click(function() { + if ($(this).prop('checked')) { + $('.hide_if_'+$(this).attr('id')).css('display','none'); + $('.show_if_'+$(this).attr('id')).fadeIn("fast", "linear"); + } else { + $('.show_if_'+$(this).attr('id')).css('display','none'); + $('.hide_if_'+$(this).attr('id')).fadeIn("fast", "linear"); + } + }); + + $(".datePresets").click(function() { + var def = $('#date_presets').val(); + if ($(this).prop('checked') && '%x' == def) { + def = '%a, %b %d, %Y'; + $('#date_use_system_default').html('1'); + } else if (!$(this).prop('checked') && '1' == $('#date_use_system_default').html()){ + def = '%x'; + } + + $('#date_presets').attr('name', 'date_preset_old'); + $('#date_presets').attr('id', 'date_presets_old'); + + $('#date_presets_na').attr('name', 'date_preset'); + $('#date_presets_na').attr('id', 'date_presets'); + + $('#date_presets_old').attr('name', 'date_preset_na'); + $('#date_presets_old').attr('id', 'date_presets_na'); + + if (def) $('#date_presets').val(def); + }); + + // bind 'myForm' and provide a simple callback function + $('#configForm').ajaxForm({ + beforeSubmit: function(){ + $('.config_submitter .config_submitter_refresh').each(function(){ + $(this).attr("disabled", "disabled"); + $(this).after('<span><img src="' + srRoot + '/images/loading16' + themeSpinner + '.gif"> Saving...</span>'); + $(this).hide(); + }); + }, + success: function(){ + setTimeout(function () { + "use strict"; + config_success(); + }, 2000); + } + }); + + $('#api_key').click(function(){ + $('#api_key').select(); + }); + + $("#generate_new_apikey").click(function(){ + $.get(srRoot + '/config/general/generateApiKey', + function(data){ + if (data.error !== undefined) { + alert(data.error); + return; + } + $('#api_key').val(data); + }); + }); + + $('#branchCheckout').click(function() { + var url = srRoot+'/home/branchCheckout?branch='+$("#branchVersion").val(); + var checkDBversion = srRoot + "/home/getDBcompare"; + $.getJSON(checkDBversion, function(data){ + if (data.status == "success") { + if (data.message == "equal") { + //Checkout Branch + window.location.href = url; + } + if (data.message == "upgrade") { + if ( confirm("Changing branch will upgrade your database.\nYou won't be able to downgrade afterward.\nDo you want to continue?") ) { + //Checkout Branch + window.location.href = url; + } + } + if (data.message == "downgrade") { + alert("Can't switch branch as this will result in a database downgrade."); + } + } + }); + }); + +}); + +function config_success(){ + $('.config_submitter').each(function(){ + $(this).removeAttr("disabled"); + $(this).next().remove(); + $(this).show(); + }); + $('.config_submitter_refresh').each(function(){ + $(this).removeAttr("disabled"); + $(this).next().remove(); + $(this).show(); + url = srRoot+'/config/providers/'; + window.location.href = url; + }); + $('#email_show').trigger('notify'); +} diff --git a/gui/slick/js/fancybox/blank.gif b/gui/slick/js/fancybox/blank.gif deleted file mode 100644 index 35d42e808f0a8017b8d52a06be2f8fec0b466a66..0000000000000000000000000000000000000000 Binary files a/gui/slick/js/fancybox/blank.gif and /dev/null differ diff --git a/gui/slick/js/fancybox/fancybox_loading.gif b/gui/slick/js/fancybox/fancybox_loading.gif deleted file mode 100644 index a03a40c097ee728709f65d4ea7397903a389d484..0000000000000000000000000000000000000000 Binary files a/gui/slick/js/fancybox/fancybox_loading.gif and /dev/null differ diff --git a/gui/slick/js/fancybox/fancybox_loading@2x.gif b/gui/slick/js/fancybox/fancybox_loading@2x.gif deleted file mode 100644 index 9205aeb09fffa6b571b4c6beee30b18400829c03..0000000000000000000000000000000000000000 Binary files a/gui/slick/js/fancybox/fancybox_loading@2x.gif and /dev/null differ diff --git a/gui/slick/js/fancybox/fancybox_overlay.png b/gui/slick/js/fancybox/fancybox_overlay.png deleted file mode 100644 index a4391396a9d6b6d7ff3b781f16904732fea40bdd..0000000000000000000000000000000000000000 Binary files a/gui/slick/js/fancybox/fancybox_overlay.png and /dev/null differ diff --git a/gui/slick/js/fancybox/fancybox_sprite.png b/gui/slick/js/fancybox/fancybox_sprite.png deleted file mode 100644 index 45fc726e4e01d9e3acb3e143d80be78b618e9356..0000000000000000000000000000000000000000 Binary files a/gui/slick/js/fancybox/fancybox_sprite.png and /dev/null differ diff --git a/gui/slick/js/fancybox/fancybox_sprite@2x.png b/gui/slick/js/fancybox/fancybox_sprite@2x.png deleted file mode 100644 index d0e4779f4bed43fe339f0cf1eb045d8cb9430c87..0000000000000000000000000000000000000000 Binary files a/gui/slick/js/fancybox/fancybox_sprite@2x.png and /dev/null differ diff --git a/gui/slick/js/fancybox/jquery.fancybox.css b/gui/slick/js/fancybox/jquery.fancybox.css deleted file mode 100644 index 367890a4af658d073d2b79c06829337d45434b84..0000000000000000000000000000000000000000 --- a/gui/slick/js/fancybox/jquery.fancybox.css +++ /dev/null @@ -1,274 +0,0 @@ -/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */ -.fancybox-wrap, -.fancybox-skin, -.fancybox-outer, -.fancybox-inner, -.fancybox-image, -.fancybox-wrap iframe, -.fancybox-wrap object, -.fancybox-nav, -.fancybox-nav span, -.fancybox-tmp -{ - padding: 0; - margin: 0; - border: 0; - outline: none; - vertical-align: top; -} - -.fancybox-wrap { - position: absolute; - top: 0; - left: 0; - z-index: 8020; -} - -.fancybox-skin { - position: relative; - background: #f9f9f9; - color: #444; - text-shadow: none; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.fancybox-opened { - z-index: 8030; -} - -.fancybox-opened .fancybox-skin { - -webkit-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); - -moz-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); - box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); -} - -.fancybox-outer, .fancybox-inner { - position: relative; -} - -.fancybox-inner { - overflow: hidden; -} - -.fancybox-type-iframe .fancybox-inner { - -webkit-overflow-scrolling: touch; -} - -.fancybox-error { - color: #444; - font: 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; - margin: 0; - padding: 15px; - white-space: nowrap; -} - -.fancybox-image, .fancybox-iframe { - display: block; - width: 100%; - height: 100%; -} - -.fancybox-image { - max-width: 100%; - max-height: 100%; -} - -#fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span { - background-image: url('fancybox_sprite.png'); -} - -#fancybox-loading { - position: fixed; - top: 50%; - left: 50%; - margin-top: -22px; - margin-left: -22px; - background-position: 0 -108px; - opacity: 0.8; - cursor: pointer; - z-index: 8060; -} - -#fancybox-loading div { - width: 44px; - height: 44px; - background: url('fancybox_loading.gif') center center no-repeat; -} - -.fancybox-close { - position: absolute; - top: -18px; - right: -18px; - width: 36px; - height: 36px; - cursor: pointer; - z-index: 8040; -} - -.fancybox-nav { - position: absolute; - top: 0; - width: 40%; - height: 100%; - cursor: pointer; - text-decoration: none; - background: transparent url('blank.gif'); /* helps IE */ - -webkit-tap-highlight-color: rgba(0,0,0,0); - z-index: 8040; -} - -.fancybox-prev { - left: 0; -} - -.fancybox-next { - right: 0; -} - -.fancybox-nav span { - position: absolute; - top: 50%; - width: 36px; - height: 34px; - margin-top: -18px; - cursor: pointer; - z-index: 8040; - visibility: hidden; -} - -.fancybox-prev span { - left: 10px; - background-position: 0 -36px; -} - -.fancybox-next span { - right: 10px; - background-position: 0 -72px; -} - -.fancybox-nav:hover span { - visibility: visible; -} - -.fancybox-tmp { - position: absolute; - top: -99999px; - left: -99999px; - visibility: hidden; - max-width: 99999px; - max-height: 99999px; - overflow: visible !important; -} - -/* Overlay helper */ - -.fancybox-lock { - overflow: hidden !important; - width: auto; -} - -.fancybox-lock body { - overflow: hidden !important; -} - -.fancybox-lock-test { - overflow-y: hidden !important; -} - -.fancybox-overlay { - position: absolute; - top: 0; - left: 0; - overflow: hidden; - display: none; - z-index: 8010; - background: url('fancybox_overlay.png'); -} - -.fancybox-overlay-fixed { - position: fixed; - bottom: 0; - right: 0; -} - -.fancybox-lock .fancybox-overlay { - overflow: auto; - overflow-y: scroll; -} - -/* Title helper */ - -.fancybox-title { - visibility: hidden; - font: normal 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; - position: relative; - text-shadow: none; - z-index: 8050; -} - -.fancybox-opened .fancybox-title { - visibility: visible; -} - -.fancybox-title-float-wrap { - position: absolute; - bottom: 0; - right: 50%; - margin-bottom: -35px; - z-index: 8050; - text-align: center; -} - -.fancybox-title-float-wrap .child { - display: inline-block; - margin-right: -100%; - padding: 2px 20px; - background: transparent; /* Fallback for web browsers that doesn't support RGBa */ - background: rgba(0, 0, 0, 0.8); - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; - text-shadow: 0 1px 2px #222; - color: #FFF; - font-weight: bold; - line-height: 24px; - white-space: nowrap; -} - -.fancybox-title-outside-wrap { - position: relative; - margin-top: 10px; - color: #fff; -} - -.fancybox-title-inside-wrap { - padding-top: 10px; -} - -.fancybox-title-over-wrap { - position: absolute; - bottom: 0; - left: 0; - color: #fff; - padding: 10px; - background: #000; - background: rgba(0, 0, 0, .8); -} - -/*Retina graphics!*/ -@media only screen and (-webkit-min-device-pixel-ratio: 1.5), - only screen and (min--moz-device-pixel-ratio: 1.5), - only screen and (min-device-pixel-ratio: 1.5){ - - #fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span { - background-image: url('fancybox_sprite@2x.png'); - background-size: 44px 152px; /*The size of the normal image, half the size of the hi-res image*/ - } - - #fancybox-loading div { - background-image: url('fancybox_loading@2x.gif'); - background-size: 24px 24px; /*The size of the normal image, half the size of the hi-res image*/ - } -} \ No newline at end of file diff --git a/gui/slick/js/fancybox/jquery.fancybox.pack.js b/gui/slick/js/fancybox/jquery.fancybox.pack.js deleted file mode 100644 index 73f757843855f1eb0b23d8c81a8fb7f001989b66..0000000000000000000000000000000000000000 --- a/gui/slick/js/fancybox/jquery.fancybox.pack.js +++ /dev/null @@ -1,46 +0,0 @@ -/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */ -(function(r,G,f,v){var J=f("html"),n=f(r),p=f(G),b=f.fancybox=function(){b.open.apply(this,arguments)},I=navigator.userAgent.match(/msie/i),B=null,s=G.createTouch!==v,t=function(a){return a&&a.hasOwnProperty&&a instanceof f},q=function(a){return a&&"string"===f.type(a)},E=function(a){return q(a)&&0<a.indexOf("%")},l=function(a,d){var e=parseInt(a,10)||0;d&&E(a)&&(e*=b.getViewport()[d]/100);return Math.ceil(e)},w=function(a,b){return l(a,b)+"px"};f.extend(b,{version:"2.1.5",defaults:{padding:15,margin:20, -width:800,height:600,minWidth:100,minHeight:100,maxWidth:9999,maxHeight:9999,pixelRatio:1,autoSize:!0,autoHeight:!1,autoWidth:!1,autoResize:!0,autoCenter:!s,fitToView:!0,aspectRatio:!1,topRatio:0.5,leftRatio:0.5,scrolling:"auto",wrapCSS:"",arrows:!0,closeBtn:!0,closeClick:!1,nextClick:!1,mouseWheel:!0,autoPlay:!1,playSpeed:3E3,preload:3,modal:!1,loop:!0,ajax:{dataType:"html",headers:{"X-fancyBox":!0}},iframe:{scrolling:"auto",preload:!0},swf:{wmode:"transparent",allowfullscreen:"true",allowscriptaccess:"always"}, -keys:{next:{13:"left",34:"up",39:"left",40:"up"},prev:{8:"right",33:"down",37:"right",38:"down"},close:[27],play:[32],toggle:[70]},direction:{next:"left",prev:"right"},scrollOutside:!0,index:0,type:null,href:null,content:null,title:null,tpl:{wrap:'<div class="fancybox-wrap" tabIndex="-1"><div class="fancybox-skin"><div class="fancybox-outer"><div class="fancybox-inner"></div></div></div></div>',image:'<img class="fancybox-image" src="{href}" alt="" />',iframe:'<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen'+ -(I?' allowtransparency="true"':"")+"></iframe>",error:'<p class="fancybox-error">The requested content cannot be loaded.<br/>Please try again later.</p>',closeBtn:'<a title="Close" class="fancybox-item fancybox-close" href="javascript:;"></a>',next:'<a title="Next" class="fancybox-nav fancybox-next" href="javascript:;"><span></span></a>',prev:'<a title="Previous" class="fancybox-nav fancybox-prev" href="javascript:;"><span></span></a>'},openEffect:"fade",openSpeed:250,openEasing:"swing",openOpacity:!0, -openMethod:"zoomIn",closeEffect:"fade",closeSpeed:250,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:250,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",prevSpeed:250,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:!0,title:!0},onCancel:f.noop,beforeLoad:f.noop,afterLoad:f.noop,beforeShow:f.noop,afterShow:f.noop,beforeChange:f.noop,beforeClose:f.noop,afterClose:f.noop},group:{},opts:{},previous:null,coming:null,current:null,isActive:!1, -isOpen:!1,isOpened:!1,wrap:null,skin:null,outer:null,inner:null,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(a,d){if(a&&(f.isPlainObject(d)||(d={}),!1!==b.close(!0)))return f.isArray(a)||(a=t(a)?f(a).get():[a]),f.each(a,function(e,c){var k={},g,h,j,m,l;"object"===f.type(c)&&(c.nodeType&&(c=f(c)),t(c)?(k={href:c.data("fancybox-href")||c.attr("href"),title:c.data("fancybox-title")||c.attr("title"),isDom:!0,element:c},f.metadata&&f.extend(!0,k, -c.metadata())):k=c);g=d.href||k.href||(q(c)?c:null);h=d.title!==v?d.title:k.title||"";m=(j=d.content||k.content)?"html":d.type||k.type;!m&&k.isDom&&(m=c.data("fancybox-type"),m||(m=(m=c.prop("class").match(/fancybox\.(\w+)/))?m[1]:null));q(g)&&(m||(b.isImage(g)?m="image":b.isSWF(g)?m="swf":"#"===g.charAt(0)?m="inline":q(c)&&(m="html",j=c)),"ajax"===m&&(l=g.split(/\s+/,2),g=l.shift(),l=l.shift()));j||("inline"===m?g?j=f(q(g)?g.replace(/.*(?=#[^\s]+$)/,""):g):k.isDom&&(j=c):"html"===m?j=g:!m&&(!g&& -k.isDom)&&(m="inline",j=c));f.extend(k,{href:g,type:m,content:j,title:h,selector:l});a[e]=k}),b.opts=f.extend(!0,{},b.defaults,d),d.keys!==v&&(b.opts.keys=d.keys?f.extend({},b.defaults.keys,d.keys):!1),b.group=a,b._start(b.opts.index)},cancel:function(){var a=b.coming;a&&!1!==b.trigger("onCancel")&&(b.hideLoading(),b.ajaxLoad&&b.ajaxLoad.abort(),b.ajaxLoad=null,b.imgPreload&&(b.imgPreload.onload=b.imgPreload.onerror=null),a.wrap&&a.wrap.stop(!0,!0).trigger("onReset").remove(),b.coming=null,b.current|| -b._afterZoomOut(a))},close:function(a){b.cancel();!1!==b.trigger("beforeClose")&&(b.unbindEvents(),b.isActive&&(!b.isOpen||!0===a?(f(".fancybox-wrap").stop(!0).trigger("onReset").remove(),b._afterZoomOut()):(b.isOpen=b.isOpened=!1,b.isClosing=!0,f(".fancybox-item, .fancybox-nav").remove(),b.wrap.stop(!0,!0).removeClass("fancybox-opened"),b.transitions[b.current.closeMethod]())))},play:function(a){var d=function(){clearTimeout(b.player.timer)},e=function(){d();b.current&&b.player.isActive&&(b.player.timer= -setTimeout(b.next,b.current.playSpeed))},c=function(){d();p.unbind(".player");b.player.isActive=!1;b.trigger("onPlayEnd")};if(!0===a||!b.player.isActive&&!1!==a){if(b.current&&(b.current.loop||b.current.index<b.group.length-1))b.player.isActive=!0,p.bind({"onCancel.player beforeClose.player":c,"onUpdate.player":e,"beforeLoad.player":d}),e(),b.trigger("onPlayStart")}else c()},next:function(a){var d=b.current;d&&(q(a)||(a=d.direction.next),b.jumpto(d.index+1,a,"next"))},prev:function(a){var d=b.current; -d&&(q(a)||(a=d.direction.prev),b.jumpto(d.index-1,a,"prev"))},jumpto:function(a,d,e){var c=b.current;c&&(a=l(a),b.direction=d||c.direction[a>=c.index?"next":"prev"],b.router=e||"jumpto",c.loop&&(0>a&&(a=c.group.length+a%c.group.length),a%=c.group.length),c.group[a]!==v&&(b.cancel(),b._start(a)))},reposition:function(a,d){var e=b.current,c=e?e.wrap:null,k;c&&(k=b._getPosition(d),a&&"scroll"===a.type?(delete k.position,c.stop(!0,!0).animate(k,200)):(c.css(k),e.pos=f.extend({},e.dim,k)))},update:function(a){var d= -a&&a.type,e=!d||"orientationchange"===d;e&&(clearTimeout(B),B=null);b.isOpen&&!B&&(B=setTimeout(function(){var c=b.current;c&&!b.isClosing&&(b.wrap.removeClass("fancybox-tmp"),(e||"load"===d||"resize"===d&&c.autoResize)&&b._setDimension(),"scroll"===d&&c.canShrink||b.reposition(a),b.trigger("onUpdate"),B=null)},e&&!s?0:300))},toggle:function(a){b.isOpen&&(b.current.fitToView="boolean"===f.type(a)?a:!b.current.fitToView,s&&(b.wrap.removeAttr("style").addClass("fancybox-tmp"),b.trigger("onUpdate")), -b.update())},hideLoading:function(){p.unbind(".loading");f("#fancybox-loading").remove()},showLoading:function(){var a,d;b.hideLoading();a=f('<div id="fancybox-loading"><div></div></div>').click(b.cancel).appendTo("body");p.bind("keydown.loading",function(a){if(27===(a.which||a.keyCode))a.preventDefault(),b.cancel()});b.defaults.fixed||(d=b.getViewport(),a.css({position:"absolute",top:0.5*d.h+d.y,left:0.5*d.w+d.x}))},getViewport:function(){var a=b.current&&b.current.locked||!1,d={x:n.scrollLeft(), -y:n.scrollTop()};a?(d.w=a[0].clientWidth,d.h=a[0].clientHeight):(d.w=s&&r.innerWidth?r.innerWidth:n.width(),d.h=s&&r.innerHeight?r.innerHeight:n.height());return d},unbindEvents:function(){b.wrap&&t(b.wrap)&&b.wrap.unbind(".fb");p.unbind(".fb");n.unbind(".fb")},bindEvents:function(){var a=b.current,d;a&&(n.bind("orientationchange.fb"+(s?"":" resize.fb")+(a.autoCenter&&!a.locked?" scroll.fb":""),b.update),(d=a.keys)&&p.bind("keydown.fb",function(e){var c=e.which||e.keyCode,k=e.target||e.srcElement; -if(27===c&&b.coming)return!1;!e.ctrlKey&&(!e.altKey&&!e.shiftKey&&!e.metaKey&&(!k||!k.type&&!f(k).is("[contenteditable]")))&&f.each(d,function(d,k){if(1<a.group.length&&k[c]!==v)return b[d](k[c]),e.preventDefault(),!1;if(-1<f.inArray(c,k))return b[d](),e.preventDefault(),!1})}),f.fn.mousewheel&&a.mouseWheel&&b.wrap.bind("mousewheel.fb",function(d,c,k,g){for(var h=f(d.target||null),j=!1;h.length&&!j&&!h.is(".fancybox-skin")&&!h.is(".fancybox-wrap");)j=h[0]&&!(h[0].style.overflow&&"hidden"===h[0].style.overflow)&& -(h[0].clientWidth&&h[0].scrollWidth>h[0].clientWidth||h[0].clientHeight&&h[0].scrollHeight>h[0].clientHeight),h=f(h).parent();if(0!==c&&!j&&1<b.group.length&&!a.canShrink){if(0<g||0<k)b.prev(0<g?"down":"left");else if(0>g||0>k)b.next(0>g?"up":"right");d.preventDefault()}}))},trigger:function(a,d){var e,c=d||b.coming||b.current;if(c){f.isFunction(c[a])&&(e=c[a].apply(c,Array.prototype.slice.call(arguments,1)));if(!1===e)return!1;c.helpers&&f.each(c.helpers,function(d,e){if(e&&b.helpers[d]&&f.isFunction(b.helpers[d][a]))b.helpers[d][a](f.extend(!0, -{},b.helpers[d].defaults,e),c)});p.trigger(a)}},isImage:function(a){return q(a)&&a.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i)},isSWF:function(a){return q(a)&&a.match(/\.(swf)((\?|#).*)?$/i)},_start:function(a){var d={},e,c;a=l(a);e=b.group[a]||null;if(!e)return!1;d=f.extend(!0,{},b.opts,e);e=d.margin;c=d.padding;"number"===f.type(e)&&(d.margin=[e,e,e,e]);"number"===f.type(c)&&(d.padding=[c,c,c,c]);d.modal&&f.extend(!0,d,{closeBtn:!1,closeClick:!1,nextClick:!1,arrows:!1, -mouseWheel:!1,keys:null,helpers:{overlay:{closeClick:!1}}});d.autoSize&&(d.autoWidth=d.autoHeight=!0);"auto"===d.width&&(d.autoWidth=!0);"auto"===d.height&&(d.autoHeight=!0);d.group=b.group;d.index=a;b.coming=d;if(!1===b.trigger("beforeLoad"))b.coming=null;else{c=d.type;e=d.href;if(!c)return b.coming=null,b.current&&b.router&&"jumpto"!==b.router?(b.current.index=a,b[b.router](b.direction)):!1;b.isActive=!0;if("image"===c||"swf"===c)d.autoHeight=d.autoWidth=!1,d.scrolling="visible";"image"===c&&(d.aspectRatio= -!0);"iframe"===c&&s&&(d.scrolling="scroll");d.wrap=f(d.tpl.wrap).addClass("fancybox-"+(s?"mobile":"desktop")+" fancybox-type-"+c+" fancybox-tmp "+d.wrapCSS).appendTo(d.parent||"body");f.extend(d,{skin:f(".fancybox-skin",d.wrap),outer:f(".fancybox-outer",d.wrap),inner:f(".fancybox-inner",d.wrap)});f.each(["Top","Right","Bottom","Left"],function(a,b){d.skin.css("padding"+b,w(d.padding[a]))});b.trigger("onReady");if("inline"===c||"html"===c){if(!d.content||!d.content.length)return b._error("content")}else if(!e)return b._error("href"); -"image"===c?b._loadImage():"ajax"===c?b._loadAjax():"iframe"===c?b._loadIframe():b._afterLoad()}},_error:function(a){f.extend(b.coming,{type:"html",autoWidth:!0,autoHeight:!0,minWidth:0,minHeight:0,scrolling:"no",hasError:a,content:b.coming.tpl.error});b._afterLoad()},_loadImage:function(){var a=b.imgPreload=new Image;a.onload=function(){this.onload=this.onerror=null;b.coming.width=this.width/b.opts.pixelRatio;b.coming.height=this.height/b.opts.pixelRatio;b._afterLoad()};a.onerror=function(){this.onload= -this.onerror=null;b._error("image")};a.src=b.coming.href;!0!==a.complete&&b.showLoading()},_loadAjax:function(){var a=b.coming;b.showLoading();b.ajaxLoad=f.ajax(f.extend({},a.ajax,{url:a.href,error:function(a,e){b.coming&&"abort"!==e?b._error("ajax",a):b.hideLoading()},success:function(d,e){"success"===e&&(a.content=d,b._afterLoad())}}))},_loadIframe:function(){var a=b.coming,d=f(a.tpl.iframe.replace(/\{rnd\}/g,(new Date).getTime())).attr("scrolling",s?"auto":a.iframe.scrolling).attr("src",a.href); -f(a.wrap).bind("onReset",function(){try{f(this).find("iframe").hide().attr("src","//about:blank").end().empty()}catch(a){}});a.iframe.preload&&(b.showLoading(),d.one("load",function(){f(this).data("ready",1);s||f(this).bind("load.fb",b.update);f(this).parents(".fancybox-wrap").width("100%").removeClass("fancybox-tmp").show();b._afterLoad()}));a.content=d.appendTo(a.inner);a.iframe.preload||b._afterLoad()},_preloadImages:function(){var a=b.group,d=b.current,e=a.length,c=d.preload?Math.min(d.preload, -e-1):0,f,g;for(g=1;g<=c;g+=1)f=a[(d.index+g)%e],"image"===f.type&&f.href&&((new Image).src=f.href)},_afterLoad:function(){var a=b.coming,d=b.current,e,c,k,g,h;b.hideLoading();if(a&&!1!==b.isActive)if(!1===b.trigger("afterLoad",a,d))a.wrap.stop(!0).trigger("onReset").remove(),b.coming=null;else{d&&(b.trigger("beforeChange",d),d.wrap.stop(!0).removeClass("fancybox-opened").find(".fancybox-item, .fancybox-nav").remove());b.unbindEvents();e=a.content;c=a.type;k=a.scrolling;f.extend(b,{wrap:a.wrap,skin:a.skin, -outer:a.outer,inner:a.inner,current:a,previous:d});g=a.href;switch(c){case "inline":case "ajax":case "html":a.selector?e=f("<div>").html(e).find(a.selector):t(e)&&(e.data("fancybox-placeholder")||e.data("fancybox-placeholder",f('<div class="fancybox-placeholder"></div>').insertAfter(e).hide()),e=e.show().detach(),a.wrap.bind("onReset",function(){f(this).find(e).length&&e.hide().replaceAll(e.data("fancybox-placeholder")).data("fancybox-placeholder",!1)}));break;case "image":e=a.tpl.image.replace("{href}", -g);break;case "swf":e='<object id="fancybox-swf" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="movie" value="'+g+'"></param>',h="",f.each(a.swf,function(a,b){e+='<param name="'+a+'" value="'+b+'"></param>';h+=" "+a+'="'+b+'"'}),e+='<embed src="'+g+'" type="application/x-shockwave-flash" width="100%" height="100%"'+h+"></embed></object>"}(!t(e)||!e.parent().is(a.inner))&&a.inner.append(e);b.trigger("beforeShow");a.inner.css("overflow","yes"===k?"scroll": -"no"===k?"hidden":k);b._setDimension();b.reposition();b.isOpen=!1;b.coming=null;b.bindEvents();if(b.isOpened){if(d.prevMethod)b.transitions[d.prevMethod]()}else f(".fancybox-wrap").not(a.wrap).stop(!0).trigger("onReset").remove();b.transitions[b.isOpened?a.nextMethod:a.openMethod]();b._preloadImages()}},_setDimension:function(){var a=b.getViewport(),d=0,e=!1,c=!1,e=b.wrap,k=b.skin,g=b.inner,h=b.current,c=h.width,j=h.height,m=h.minWidth,u=h.minHeight,n=h.maxWidth,p=h.maxHeight,s=h.scrolling,q=h.scrollOutside? -h.scrollbarWidth:0,x=h.margin,y=l(x[1]+x[3]),r=l(x[0]+x[2]),v,z,t,C,A,F,B,D,H;e.add(k).add(g).width("auto").height("auto").removeClass("fancybox-tmp");x=l(k.outerWidth(!0)-k.width());v=l(k.outerHeight(!0)-k.height());z=y+x;t=r+v;C=E(c)?(a.w-z)*l(c)/100:c;A=E(j)?(a.h-t)*l(j)/100:j;if("iframe"===h.type){if(H=h.content,h.autoHeight&&1===H.data("ready"))try{H[0].contentWindow.document.location&&(g.width(C).height(9999),F=H.contents().find("body"),q&&F.css("overflow-x","hidden"),A=F.outerHeight(!0))}catch(G){}}else if(h.autoWidth|| -h.autoHeight)g.addClass("fancybox-tmp"),h.autoWidth||g.width(C),h.autoHeight||g.height(A),h.autoWidth&&(C=g.width()),h.autoHeight&&(A=g.height()),g.removeClass("fancybox-tmp");c=l(C);j=l(A);D=C/A;m=l(E(m)?l(m,"w")-z:m);n=l(E(n)?l(n,"w")-z:n);u=l(E(u)?l(u,"h")-t:u);p=l(E(p)?l(p,"h")-t:p);F=n;B=p;h.fitToView&&(n=Math.min(a.w-z,n),p=Math.min(a.h-t,p));z=a.w-y;r=a.h-r;h.aspectRatio?(c>n&&(c=n,j=l(c/D)),j>p&&(j=p,c=l(j*D)),c<m&&(c=m,j=l(c/D)),j<u&&(j=u,c=l(j*D))):(c=Math.max(m,Math.min(c,n)),h.autoHeight&& -"iframe"!==h.type&&(g.width(c),j=g.height()),j=Math.max(u,Math.min(j,p)));if(h.fitToView)if(g.width(c).height(j),e.width(c+x),a=e.width(),y=e.height(),h.aspectRatio)for(;(a>z||y>r)&&(c>m&&j>u)&&!(19<d++);)j=Math.max(u,Math.min(p,j-10)),c=l(j*D),c<m&&(c=m,j=l(c/D)),c>n&&(c=n,j=l(c/D)),g.width(c).height(j),e.width(c+x),a=e.width(),y=e.height();else c=Math.max(m,Math.min(c,c-(a-z))),j=Math.max(u,Math.min(j,j-(y-r)));q&&("auto"===s&&j<A&&c+x+q<z)&&(c+=q);g.width(c).height(j);e.width(c+x);a=e.width(); -y=e.height();e=(a>z||y>r)&&c>m&&j>u;c=h.aspectRatio?c<F&&j<B&&c<C&&j<A:(c<F||j<B)&&(c<C||j<A);f.extend(h,{dim:{width:w(a),height:w(y)},origWidth:C,origHeight:A,canShrink:e,canExpand:c,wPadding:x,hPadding:v,wrapSpace:y-k.outerHeight(!0),skinSpace:k.height()-j});!H&&(h.autoHeight&&j>u&&j<p&&!c)&&g.height("auto")},_getPosition:function(a){var d=b.current,e=b.getViewport(),c=d.margin,f=b.wrap.width()+c[1]+c[3],g=b.wrap.height()+c[0]+c[2],c={position:"absolute",top:c[0],left:c[3]};d.autoCenter&&d.fixed&& -!a&&g<=e.h&&f<=e.w?c.position="fixed":d.locked||(c.top+=e.y,c.left+=e.x);c.top=w(Math.max(c.top,c.top+(e.h-g)*d.topRatio));c.left=w(Math.max(c.left,c.left+(e.w-f)*d.leftRatio));return c},_afterZoomIn:function(){var a=b.current;a&&(b.isOpen=b.isOpened=!0,b.wrap.css("overflow","visible").addClass("fancybox-opened"),b.update(),(a.closeClick||a.nextClick&&1<b.group.length)&&b.inner.css("cursor","pointer").bind("click.fb",function(d){!f(d.target).is("a")&&!f(d.target).parent().is("a")&&(d.preventDefault(), -b[a.closeClick?"close":"next"]())}),a.closeBtn&&f(a.tpl.closeBtn).appendTo(b.skin).bind("click.fb",function(a){a.preventDefault();b.close()}),a.arrows&&1<b.group.length&&((a.loop||0<a.index)&&f(a.tpl.prev).appendTo(b.outer).bind("click.fb",b.prev),(a.loop||a.index<b.group.length-1)&&f(a.tpl.next).appendTo(b.outer).bind("click.fb",b.next)),b.trigger("afterShow"),!a.loop&&a.index===a.group.length-1?b.play(!1):b.opts.autoPlay&&!b.player.isActive&&(b.opts.autoPlay=!1,b.play()))},_afterZoomOut:function(a){a= -a||b.current;f(".fancybox-wrap").trigger("onReset").remove();f.extend(b,{group:{},opts:{},router:!1,current:null,isActive:!1,isOpened:!1,isOpen:!1,isClosing:!1,wrap:null,skin:null,outer:null,inner:null});b.trigger("afterClose",a)}});b.transitions={getOrigPosition:function(){var a=b.current,d=a.element,e=a.orig,c={},f=50,g=50,h=a.hPadding,j=a.wPadding,m=b.getViewport();!e&&(a.isDom&&d.is(":visible"))&&(e=d.find("img:first"),e.length||(e=d));t(e)?(c=e.offset(),e.is("img")&&(f=e.outerWidth(),g=e.outerHeight())): -(c.top=m.y+(m.h-g)*a.topRatio,c.left=m.x+(m.w-f)*a.leftRatio);if("fixed"===b.wrap.css("position")||a.locked)c.top-=m.y,c.left-=m.x;return c={top:w(c.top-h*a.topRatio),left:w(c.left-j*a.leftRatio),width:w(f+j),height:w(g+h)}},step:function(a,d){var e,c,f=d.prop;c=b.current;var g=c.wrapSpace,h=c.skinSpace;if("width"===f||"height"===f)e=d.end===d.start?1:(a-d.start)/(d.end-d.start),b.isClosing&&(e=1-e),c="width"===f?c.wPadding:c.hPadding,c=a-c,b.skin[f](l("width"===f?c:c-g*e)),b.inner[f](l("width"=== -f?c:c-g*e-h*e))},zoomIn:function(){var a=b.current,d=a.pos,e=a.openEffect,c="elastic"===e,k=f.extend({opacity:1},d);delete k.position;c?(d=this.getOrigPosition(),a.openOpacity&&(d.opacity=0.1)):"fade"===e&&(d.opacity=0.1);b.wrap.css(d).animate(k,{duration:"none"===e?0:a.openSpeed,easing:a.openEasing,step:c?this.step:null,complete:b._afterZoomIn})},zoomOut:function(){var a=b.current,d=a.closeEffect,e="elastic"===d,c={opacity:0.1};e&&(c=this.getOrigPosition(),a.closeOpacity&&(c.opacity=0.1));b.wrap.animate(c, -{duration:"none"===d?0:a.closeSpeed,easing:a.closeEasing,step:e?this.step:null,complete:b._afterZoomOut})},changeIn:function(){var a=b.current,d=a.nextEffect,e=a.pos,c={opacity:1},f=b.direction,g;e.opacity=0.1;"elastic"===d&&(g="down"===f||"up"===f?"top":"left","down"===f||"right"===f?(e[g]=w(l(e[g])-200),c[g]="+=200px"):(e[g]=w(l(e[g])+200),c[g]="-=200px"));"none"===d?b._afterZoomIn():b.wrap.css(e).animate(c,{duration:a.nextSpeed,easing:a.nextEasing,complete:b._afterZoomIn})},changeOut:function(){var a= -b.previous,d=a.prevEffect,e={opacity:0.1},c=b.direction;"elastic"===d&&(e["down"===c||"up"===c?"top":"left"]=("up"===c||"left"===c?"-":"+")+"=200px");a.wrap.animate(e,{duration:"none"===d?0:a.prevSpeed,easing:a.prevEasing,complete:function(){f(this).trigger("onReset").remove()}})}};b.helpers.overlay={defaults:{closeClick:!0,speedOut:200,showEarly:!0,css:{},locked:!s,fixed:!0},overlay:null,fixed:!1,el:f("html"),create:function(a){a=f.extend({},this.defaults,a);this.overlay&&this.close();this.overlay= -f('<div class="fancybox-overlay"></div>').appendTo(b.coming?b.coming.parent:a.parent);this.fixed=!1;a.fixed&&b.defaults.fixed&&(this.overlay.addClass("fancybox-overlay-fixed"),this.fixed=!0)},open:function(a){var d=this;a=f.extend({},this.defaults,a);this.overlay?this.overlay.unbind(".overlay").width("auto").height("auto"):this.create(a);this.fixed||(n.bind("resize.overlay",f.proxy(this.update,this)),this.update());a.closeClick&&this.overlay.bind("click.overlay",function(a){if(f(a.target).hasClass("fancybox-overlay"))return b.isActive? -b.close():d.close(),!1});this.overlay.css(a.css).show()},close:function(){var a,b;n.unbind("resize.overlay");this.el.hasClass("fancybox-lock")&&(f(".fancybox-margin").removeClass("fancybox-margin"),a=n.scrollTop(),b=n.scrollLeft(),this.el.removeClass("fancybox-lock"),n.scrollTop(a).scrollLeft(b));f(".fancybox-overlay").remove().hide();f.extend(this,{overlay:null,fixed:!1})},update:function(){var a="100%",b;this.overlay.width(a).height("100%");I?(b=Math.max(G.documentElement.offsetWidth,G.body.offsetWidth), -p.width()>b&&(a=p.width())):p.width()>n.width()&&(a=p.width());this.overlay.width(a).height(p.height())},onReady:function(a,b){var e=this.overlay;f(".fancybox-overlay").stop(!0,!0);e||this.create(a);a.locked&&(this.fixed&&b.fixed)&&(e||(this.margin=p.height()>n.height()?f("html").css("margin-right").replace("px",""):!1),b.locked=this.overlay.append(b.wrap),b.fixed=!1);!0===a.showEarly&&this.beforeShow.apply(this,arguments)},beforeShow:function(a,b){var e,c;b.locked&&(!1!==this.margin&&(f("*").filter(function(){return"fixed"=== -f(this).css("position")&&!f(this).hasClass("fancybox-overlay")&&!f(this).hasClass("fancybox-wrap")}).addClass("fancybox-margin"),this.el.addClass("fancybox-margin")),e=n.scrollTop(),c=n.scrollLeft(),this.el.addClass("fancybox-lock"),n.scrollTop(e).scrollLeft(c));this.open(a)},onUpdate:function(){this.fixed||this.update()},afterClose:function(a){this.overlay&&!b.coming&&this.overlay.fadeOut(a.speedOut,f.proxy(this.close,this))}};b.helpers.title={defaults:{type:"float",position:"bottom"},beforeShow:function(a){var d= -b.current,e=d.title,c=a.type;f.isFunction(e)&&(e=e.call(d.element,d));if(q(e)&&""!==f.trim(e)){d=f('<div class="fancybox-title fancybox-title-'+c+'-wrap">'+e+"</div>");switch(c){case "inside":c=b.skin;break;case "outside":c=b.wrap;break;case "over":c=b.inner;break;default:c=b.skin,d.appendTo("body"),I&&d.width(d.width()),d.wrapInner('<span class="child"></span>'),b.current.margin[2]+=Math.abs(l(d.css("margin-bottom")))}d["top"===a.position?"prependTo":"appendTo"](c)}}};f.fn.fancybox=function(a){var d, -e=f(this),c=this.selector||"",k=function(g){var h=f(this).blur(),j=d,k,l;!g.ctrlKey&&(!g.altKey&&!g.shiftKey&&!g.metaKey)&&!h.is(".fancybox-wrap")&&(k=a.groupAttr||"data-fancybox-group",l=h.attr(k),l||(k="rel",l=h.get(0)[k]),l&&(""!==l&&"nofollow"!==l)&&(h=c.length?f(c):e,h=h.filter("["+k+'="'+l+'"]'),j=h.index(this)),a.index=j,!1!==b.open(h,a)&&g.preventDefault())};a=a||{};d=a.index||0;!c||!1===a.live?e.unbind("click.fb-start").bind("click.fb-start",k):p.undelegate(c,"click.fb-start").delegate(c+ -":not('.fancybox-item, .fancybox-nav')","click.fb-start",k);this.filter("[data-fancybox-start=1]").trigger("click");return this};p.ready(function(){var a,d;f.scrollbarWidth===v&&(f.scrollbarWidth=function(){var a=f('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo("body"),b=a.children(),b=b.innerWidth()-b.height(99).innerWidth();a.remove();return b});if(f.support.fixedPosition===v){a=f.support;d=f('<div style="position:fixed;top:20px;"></div>').appendTo("body");var e=20=== -d[0].offsetTop||15===d[0].offsetTop;d.remove();a.fixedPosition=e}f.extend(b.defaults,{scrollbarWidth:f.scrollbarWidth(),fixed:f.support.fixedPosition,parent:f("body")});a=f(r).width();J.addClass("fancybox-lock-test");d=f(r).width();J.removeClass("fancybox-lock-test");f("<style type='text/css'>.fancybox-margin{margin-right:"+(d-a)+"px;}</style>").appendTo("head")})})(window,document,jQuery); \ No newline at end of file diff --git a/gui/slick/js/formwizard.js b/gui/slick/js/formwizard.js deleted file mode 100644 index 195342900fa636859a7e96907ef5d50462e3b2f0..0000000000000000000000000000000000000000 --- a/gui/slick/js/formwizard.js +++ /dev/null @@ -1,212 +0,0 @@ -/*jQuery Form to Form Wizard (Initial: Oct 1st, 2010) -* This notice must stay intact for usage -* Author: Dynamic Drive at http://www.dynamicdrive.com/ -* Visit http://www.dynamicdrive.com/ for full source code -*/ - -//Oct 21st, 2010: Script updated to v1.1, which adds basic form validation functionality, triggered each time the user goes from one page to the next, or tries to submit the form. - -//jQuery.noConflict() - - -function formtowizard(options){ - this.setting=jQuery.extend({persistsection:false, revealfx:['slide', 500], oninit:function(){}, onpagechangestart:function(){}}, options) - this.currentsection=-1 - this.init(this.setting) -} - -formtowizard.prototype={ - - createfieldsets:function($theform, arr){ //reserved function for future version (dynamically wraps form elements with a fieldset element) - $theform.find('fieldset.sectionwrap').removeClass('sectionwrap') //make sure no fieldsets carry 'sectionwrap' before proceeding - var $startelement=$theform.find(':first-child') //reference first element inside form - for (var i=0; i<arr.length; i++){ //loop thru "break" elements - var $fieldsetelements=$startelement.nextUntil('#'+arr[i].breakafter+', *[name='+arr[i].breakafter+']').andSelf() //reference all elements from start element to break element (nextUntil() is jQuery 1.4 function) - $fieldsetelements.add($fieldsetelements.next()).wrapAll('<fieldset class="sectionwrap" />') //wrap these elements with fieldset element - $startelement=$theform.find('fieldset.sectionwrap').eq(i).prepend('<legend class="legendStep">'+arr[i].legend+'</legend>').next() //increment startelement to begin at the end of the just inserted fieldset element - } - }, - - loadsection:function(rawi, bypasshooks){ - var thiswizard=this - //doload Boolean checks to see whether to load next section (true if bypasshooks param is true or onpagechangestart() event handler doesn't return false) - var doload=bypasshooks || this.setting.onpagechangestart(jQuery, this.currentsection, this.sections.$sections.eq(this.currentsection)) - doload=(doload===false)? false : true //unless doload is explicitly false, set to true - if (!bypasshooks && this.setting.validate){ - var outcome=this.validate(this.currentsection) - if (outcome===false) - doload=false - } - var i=(rawi=="prev")? this.currentsection-1 : (rawi=="next")? this.currentsection+1 : parseInt(rawi) //get index of next section to show - i=(i<0)? this.sections.count-1 : (i>this.sections.count-1)? 0 : i //make sure i doesn't exceed min/max limit - if (i<this.sections.count && doload){ //if next section to show isn't the same as the current section shown - this.$thesteps.eq(this.currentsection).addClass('disabledstep').end().eq(i).removeClass('disabledstep') //dull current "step" text then highlight next "step" text - if (this.setting.revealfx[0]=="slide"){ - this.sections.$sections.css("visibility", "visible") - this.sections.$outerwrapper.stop().animate({height: this.sections.$sections.eq(i).outerHeight()}, this.setting.revealfx[1]) //animate fieldset wrapper's height to accomodate next section's height - this.sections.$innerwrapper.stop().animate({left:-i*this.maxfieldsetwidth}, this.setting.revealfx[1], function(){ //slide next section into view - thiswizard.sections.$sections.each(function(thissec){ - if (thissec!=i) //hide fieldset sections currently not in veiw, so tabbing doesn't go to elements within them (and mess up layout) - thiswizard.sections.$sections.eq(thissec).css("visibility", "hidden") - }) - }) - } - else if (this.setting.revealfx[0]=="fade"){ //if fx is "fade" - this.sections.$sections.eq(this.currentsection).hide().end().eq(i).fadeIn(this.setting.revealfx[1], function(){ - if (document.all && this.style && this.style.removeAttribute) - this.style.removeAttribute('filter') //fix IE clearType problem - }) - } - else{ - this.sections.$sections.eq(this.currentsection).hide().end().eq(i).show() - } - this.paginatediv.$status.text("Page "+(i+1)+" of "+this.sections.count) //update current page status text - this.paginatediv.$navlinks.css('visibility', 'visible') - if (i==0) //hide "prev" link - this.paginatediv.$navlinks.eq(0).css('visibility', 'hidden') - else if (i==this.sections.count-1) //hide "next" link - this.paginatediv.$navlinks.eq(1).css('visibility', 'hidden') - if (this.setting.persistsection) //enable persistence? - formtowizard.routines.setCookie(this.setting.formid+"_persist", i) - this.currentsection=i - if(i === 0) { setTimeout(function() { $('#nameToSearch').focus(); }, 250); } - } - }, - - addvalidatefields:function(){ - var $=jQuery, setting=this.setting, theform=this.$theform.get(0), validatefields=[] - var validatefields=setting.validate //array of form element ids to validate - for (var i=0; i<validatefields.length; i++){ - var el=theform.elements[validatefields[i]] //reference form element - if (el){ //if element is defined - var $section=$(el).parents('fieldset.sectionwrap:eq(0)') //find fieldset.sectionwrap this form element belongs to - if ($section.length==1){ //if element is within a fieldset.sectionwrap element - $section.data('elements').push(el) //cache this element inside corresponding section - } - } - } - }, - - validate:function(section){ - var elements=this.sections.$sections.eq(section).data('elements') //reference elements within this section that should be validated - var validated=true, invalidtext=["Please fill out the following fields:\n"] - function invalidate(el){ - validated=false - invalidtext.push("- "+ (el.id || el.name)) - } - for (var i=0; i<elements.length; i++){ - if (/(text)/.test(elements[i].type) && elements[i].value==""){ //text and textarea elements - invalidate(elements[i]) - } - else if (/(select)/.test(elements[i].type) && (elements[i].selectedIndex==-1 || elements[i].options[elements[i].selectedIndex].text=="")){ //select elements - invalidate(elements[i]) - } - else if (elements[i].type==undefined && elements[i].length>0){ //radio and checkbox elements - var onechecked=false - for (var r=0; r<elements[i].length; r++){ - if (elements[i][r].checked==true){ - onechecked=true - break - } - } - if (!onechecked){ - invalidate(elements[i][0]) - } - } - } - if (!validated) - alert(invalidtext.join('\n')) - return validated - }, - - - init:function(setting){ - var thiswizard=this - jQuery(function($){ //on document.ready - var $theform=$('#'+setting.formid) - if ($theform.length==0) //if form with specified ID doesn't exist, try name attribute instead - $theform=$('form[name='+setting.formid+']') - if (setting.manualfieldsets && setting.manualfieldsets.length>0) - thiswizard.createfieldsets($theform, setting.manualfieldsets) - var $stepsguide=$('<div class="stepsguide" />') //create Steps Container to house the "steps" text - var $sections=$theform.find('fieldset.sectionwrap').hide() //find all fieldset elements within form and hide them initially - if (setting.revealfx[0]=="slide"){ //create outer DIV that will house all the fieldset.sectionwrap elements - $sectionswrapper=$('<div style="position:relative;overflow:hidden;"></div>').insertBefore($sections.eq(0)) //add DIV above the first fieldset.sectionwrap element - $sectionswrapper_inner=$('<div style="position:absolute;left:0;top:0;"></div>') //create inner DIV of $sectionswrapper that will scroll to reveal a fieldset element - } - var maxfieldsetwidth=$sections.eq(0).outerWidth() //variable to get width of widest fieldset.sectionwrap - $sections.slice(1).each(function(i){ //loop through $sections (starting from 2nd one) - maxfieldsetwidth=Math.max($(this).outerWidth(), maxfieldsetwidth) - }) - maxfieldsetwidth+=2 //add 2px to final width to reveal fieldset border (if not removed via CSS) - thiswizard.maxfieldsetwidth=maxfieldsetwidth - $sections.each(function(i){ //loop through $sections again - var $section=$(this) - if (setting.revealfx[0]=="slide"){ - $section.data('page', i).css({position:'absolute', top:0, left:maxfieldsetwidth*i}).appendTo($sectionswrapper_inner) //set fieldset position to "absolute" and move it to inside sectionswrapper_inner DIV - } - $section.data('elements', []) //empty array to contain elements within this section that should be validated for data (applicable only if validate option is defined) - //create each "step" DIV and add it to main Steps Container: - var $thestep=$('<div class="step disabledstep" />').data('section', i).html('Step '+(i+1)+'<div class="smalltext">'+$section.find('legend:eq(0)').text()+'<p></p></div>').appendTo($stepsguide) - $thestep.click(function(){ //assign behavior to each step div - thiswizard.loadsection($(this).data('section')) - }) - }) - if (setting.revealfx[0]=="slide"){ - $sectionswrapper.width(maxfieldsetwidth) //set fieldset wrapper to width of widest fieldset - $sectionswrapper.append($sectionswrapper_inner) //add $sectionswrapper_inner as a child of $sectionswrapper - } - $theform.prepend($stepsguide) //add $thesteps div to the beginning of the form - //$stepsguide.insertBefore($sectionswrapper) //add Steps Container before sectionswrapper container - var $thesteps=$stepsguide.find('div.step') - //create pagination DIV and add it to end of form: - var $paginatediv=$('<div class="formpaginate" style="overflow:hidden;"><span class="prev" style="float:left">Prev</span> <span class="status">Step 1 of </span> <span class="next" style="float:right">Next</span></div>') - $theform.append($paginatediv) - thiswizard.$theform=$theform - if (setting.revealfx[0]=="slide"){ - thiswizard.sections={$outerwrapper:$sectionswrapper, $innerwrapper:$sectionswrapper_inner, $sections:$sections, count:$sections.length} //remember various parts of section container - thiswizard.sections.$sections.show() - } - else{ - thiswizard.sections={$sections:$sections, count:$sections.length} //remember various parts of section container - } - thiswizard.$thesteps=$thesteps //remember this ref - thiswizard.paginatediv={$main:$paginatediv, $navlinks:$paginatediv.find('span.prev, span.next'), $status:$paginatediv.find('span.status')} //remember various parts of pagination DIV - thiswizard.paginatediv.$main.click(function(e){ //assign behavior to pagination buttons - if (/(prev)|(next)/.test(e.target.className)) - thiswizard.loadsection(e.target.className) - }) - var i=(setting.persistsection)? formtowizard.routines.getCookie(setting.formid+"_persist") : 0 - thiswizard.loadsection(i||0, true) //show the first section - thiswizard.setting.oninit($, i, $sections.eq(i)) //call oninit event handler - if (setting.validate){ //if validate array defined - thiswizard.addvalidatefields() //seek out and cache form elements that should be validated - thiswizard.$theform.submit(function(){ - var returnval=true - for (var i=0; i<thiswizard.sections.count; i++){ - if (!thiswizard.validate(i)){ - thiswizard.loadsection(i, true) - returnval=false - break - } - } - return returnval //allow or disallow form submission - }) - } - }) - } -} - -formtowizard.routines={ - - getCookie:function(Name){ - var re=new RegExp(Name+"=[^;]+", "i"); //construct RE to search for target name/value pair - if (document.cookie.match(re)) //if cookie found - return document.cookie.match(re)[0].split("=")[1] //return its value - return null - }, - - setCookie:function(name, value){ - document.cookie = name+"=" + value + ";path=/" - } -} \ No newline at end of file diff --git a/gui/slick/js/lib/bootbox.min.js b/gui/slick/js/lib/bootbox.min.js new file mode 100644 index 0000000000000000000000000000000000000000..0dc0cbd5f42ee1df3ab6568b77f0f6366329b2e6 Binary files /dev/null and b/gui/slick/js/lib/bootbox.min.js differ diff --git a/gui/slick/js/lib/formwizard.js b/gui/slick/js/lib/formwizard.js new file mode 100644 index 0000000000000000000000000000000000000000..53abf6e0565ce3f791270b8d4de8b5f16c7b9219 --- /dev/null +++ b/gui/slick/js/lib/formwizard.js @@ -0,0 +1,202 @@ +/*jQuery Form to Form Wizard (Initial: Oct 1st, 2010) +* This notice must stay intact for usage +* Author: Dynamic Drive at http://www.dynamicdrive.com/ +* Visit http://www.dynamicdrive.com/ for full source code +*/ + +//Oct 21st, 2010: Script updated to v1.1, which adds basic form validation functionality, triggered each time the user goes from one page to the next, or tries to submit the form. + +//jQuery.noConflict() + + +function formtowizard(options){ + this.setting=jQuery.extend({persistsection:false, revealfx:['slide', 500], oninit:function(){}, onpagechangestart:function(){}}, options); + this.currentsection=-1; + this.init(this.setting); +} + +formtowizard.prototype={ + + createfieldsets:function($theform, arr){ //reserved function for future version (dynamically wraps form elements with a fieldset element) + $theform.find('fieldset.sectionwrap').removeClass('sectionwrap'); //make sure no fieldsets carry 'sectionwrap' before proceeding + var $startelement=$theform.find(':first-child'); //reference first element inside form + for (var i=0; i<arr.length; i++){ //loop thru "break" elements + var $fieldsetelements=$startelement.nextUntil('#'+arr[i].breakafter+', *[name='+arr[i].breakafter+']').andSelf(); //reference all elements from start element to break element (nextUntil() is jQuery 1.4 function) + $fieldsetelements.add($fieldsetelements.next()).wrapAll('<fieldset class="sectionwrap" />'); //wrap these elements with fieldset element + $startelement=$theform.find('fieldset.sectionwrap').eq(i).prepend('<legend class="legendStep">'+arr[i].legend+'</legend>').next(); //increment startelement to begin at the end of the just inserted fieldset element + } + }, + + loadsection:function(rawi, bypasshooks){ + var thiswizard=this; + //doload Boolean checks to see whether to load next section (true if bypasshooks param is true or onpagechangestart() event handler doesn't return false) + var doload=bypasshooks || this.setting.onpagechangestart(jQuery, this.currentsection, this.sections.$sections.eq(this.currentsection)); + doload=(doload===false)? false : true; //unless doload is explicitly false, set to true + if (!bypasshooks && this.setting.validate){ + var outcome=this.validate(this.currentsection); + if (outcome===false) doload=false; + } + var i=(rawi=="prev")? this.currentsection-1 : (rawi=="next")? this.currentsection+1 : parseInt(rawi); //get index of next section to show + i=(i<0)? this.sections.count-1 : (i>this.sections.count-1)? 0 : i; //make sure i doesn't exceed min/max limit + if (i<this.sections.count && doload){ //if next section to show isn't the same as the current section shown + this.$thesteps.eq(this.currentsection).addClass('disabledstep').end().eq(i).removeClass('disabledstep'); //dull current "step" text then highlight next "step" text + if (this.setting.revealfx[0]=="slide"){ + this.sections.$sections.css("visibility", "visible"); + this.sections.$outerwrapper.stop().animate({height: this.sections.$sections.eq(i).outerHeight()}, this.setting.revealfx[1]); //animate fieldset wrapper's height to accomodate next section's height + this.sections.$innerwrapper.stop().animate({left:-i*this.maxfieldsetwidth}, this.setting.revealfx[1], function(){ //slide next section into view + thiswizard.sections.$sections.each(function(thissec){ + if (thissec!=i) thiswizard.sections.$sections.eq(thissec).css("visibility", "hidden"); //hide fieldset sections currently not in veiw, so tabbing doesn't go to elements within them (and mess up layout) + }); + }); + } else if (this.setting.revealfx[0]=="fade"){ //if fx is "fade" + this.sections.$sections.eq(this.currentsection).hide().end().eq(i).fadeIn(this.setting.revealfx[1], function(){ + if (document.all && this.style && this.style.removeAttribute) this.style.removeAttribute('filter'); //fix IE clearType problem + }); + } else { + this.sections.$sections.eq(this.currentsection).hide().end().eq(i).show(); + } + this.paginatediv.$status.text("Page "+(i+1)+" of "+this.sections.count); //update current page status text + this.paginatediv.$navlinks.css('visibility', 'visible'); + if (i===0) { //hide "prev" link + this.paginatediv.$navlinks.eq(0).css('visibility', 'hidden'); + } else if (i==this.sections.count-1){ //hide "next" link + this.paginatediv.$navlinks.eq(1).css('visibility', 'hidden'); + } + if (this.setting.persistsection) formtowizard.routines.setCookie(this.setting.formid+"_persist", i); //enable persistence? + this.currentsection=i; + if(i === 0) setTimeout(function() { $('#nameToSearch').focus(); }, 250); + } + }, + + addvalidatefields:function(){ + var $=jQuery, setting=this.setting, theform=this.$theform.get(0), validatefields=[]; + validatefields=setting.validate; //array of form element ids to validate + for (var i=0; i<validatefields.length; i++){ + var el=theform.elements[validatefields[i]]; //reference form element + if (el){ //if element is defined + var $section=$(el).parents('fieldset.sectionwrap:eq(0)'); //find fieldset.sectionwrap this form element belongs to + if ($section.length==1){ //if element is within a fieldset.sectionwrap element + $section.data('elements').push(el); //cache this element inside corresponding section + } + } + } + }, + + validate:function(section){ + var elements=this.sections.$sections.eq(section).data('elements'); //reference elements within this section that should be validated + var validated=true, invalidtext=["Please fill out the following fields:\n"]; + function invalidate(el){ + validated=false; + invalidtext.push("- "+ (el.id || el.name)); + } + for (var i=0; i<elements.length; i++){ + if (/(text)/.test(elements[i].type) && elements[i].value===""){ //text and textarea elements + invalidate(elements[i]); + } + else if (/(select)/.test(elements[i].type) && (elements[i].selectedIndex==-1 || elements[i].options[elements[i].selectedIndex].text==="")){ //select elements + invalidate(elements[i]); + } + else if (elements[i].type===undefined && elements[i].length>0){ //radio and checkbox elements + var onechecked=false; + for (var r=0; r<elements[i].length; r++){ + if (elements[i][r].checked===true){ + onechecked=true; + break; + } + } + if (!onechecked){ + invalidate(elements[i][0]); + } + } + } + if (!validated) + alert(invalidtext.join('\n')); + return validated; + }, + + + init:function(setting){ + var thiswizard=this; + jQuery(function($){ //on document.ready + var $theform=$('#'+setting.formid); + if ($theform.length===0) $theform=$('form[name='+setting.formid+']'); //if form with specified ID doesn't exist, try name attribute instead + if (setting.manualfieldsets && setting.manualfieldsets.length>0) thiswizard.createfieldsets($theform, setting.manualfieldsets); + var $stepsguide=$('<div class="stepsguide" />'); //create Steps Container to house the "steps" text + var $sections=$theform.find('fieldset.sectionwrap').hide(); //find all fieldset elements within form and hide them initially + if (setting.revealfx[0]=="slide"){ //create outer DIV that will house all the fieldset.sectionwrap elements + $sectionswrapper=$('<div style="position:relative;overflow:hidden;"></div>').insertBefore($sections.eq(0)); //add DIV above the first fieldset.sectionwrap element + $sectionswrapper_inner=$('<div style="position:absolute;left:0;top:0;"></div>'); //create inner DIV of $sectionswrapper that will scroll to reveal a fieldset element + } + var maxfieldsetwidth=$sections.eq(0).outerWidth(); //variable to get width of widest fieldset.sectionwrap + $sections.slice(1).each(function(i){ //loop through $sections (starting from 2nd one) + maxfieldsetwidth=Math.max($(this).outerWidth(), maxfieldsetwidth); + }); + maxfieldsetwidth+=2; //add 2px to final width to reveal fieldset border (if not removed via CSS) + thiswizard.maxfieldsetwidth=maxfieldsetwidth; + $sections.each(function(i){ //loop through $sections again + var $section=$(this); + if (setting.revealfx[0]=="slide"){ + $section.data('page', i).css({position:'absolute', top:0, left:maxfieldsetwidth*i}).appendTo($sectionswrapper_inner); //set fieldset position to "absolute" and move it to inside sectionswrapper_inner DIV + } + $section.data('elements', []); //empty array to contain elements within this section that should be validated for data (applicable only if validate option is defined) + //create each "step" DIV and add it to main Steps Container: + var $thestep=$('<div class="step disabledstep" />').data('section', i).html('Step '+(i+1)+'<div class="smalltext">'+$section.find('legend:eq(0)').text()+'<p></p></div>').appendTo($stepsguide); + $thestep.click(function(){ //assign behavior to each step div + thiswizard.loadsection($(this).data('section')); + }); + }); + if (setting.revealfx[0]=="slide"){ + $sectionswrapper.width(maxfieldsetwidth); //set fieldset wrapper to width of widest fieldset + $sectionswrapper.append($sectionswrapper_inner); //add $sectionswrapper_inner as a child of $sectionswrapper + } + $theform.prepend($stepsguide); //add $thesteps div to the beginning of the form + //$stepsguide.insertBefore($sectionswrapper) //add Steps Container before sectionswrapper container + var $thesteps=$stepsguide.find('div.step'); + //create pagination DIV and add it to end of form: + var $paginatediv=$('<div class="formpaginate" style="overflow:hidden;"><span class="prev" style="float:left">Prev</span> <span class="status">Step 1 of </span> <span class="next" style="float:right">Next</span></div>'); + $theform.append($paginatediv); + thiswizard.$theform=$theform; + if (setting.revealfx[0]=="slide"){ + thiswizard.sections={$outerwrapper:$sectionswrapper, $innerwrapper:$sectionswrapper_inner, $sections:$sections, count:$sections.length}; //remember various parts of section container + thiswizard.sections.$sections.show(); + } else{ + thiswizard.sections={$sections:$sections, count:$sections.length}; //remember various parts of section container + } + thiswizard.$thesteps=$thesteps; //remember this ref + thiswizard.paginatediv={$main:$paginatediv, $navlinks:$paginatediv.find('span.prev, span.next'), $status:$paginatediv.find('span.status')}; //remember various parts of pagination DIV + thiswizard.paginatediv.$main.click(function(e){ //assign behavior to pagination buttons + if (/(prev)|(next)/.test(e.target.className)) thiswizard.loadsection(e.target.className); + }); + var i=(setting.persistsection)? formtowizard.routines.getCookie(setting.formid+"_persist") : 0; + thiswizard.loadsection(i||0, true); //show the first section + thiswizard.setting.oninit($, i, $sections.eq(i)); //call oninit event handler + if (setting.validate){ //if validate array defined + thiswizard.addvalidatefields(); //seek out and cache form elements that should be validated + thiswizard.$theform.submit(function(){ + var returnval=true; + for (var i=0; i<thiswizard.sections.count; i++){ + if (!thiswizard.validate(i)){ + thiswizard.loadsection(i, true); + returnval=false; + break; + } + } + return returnval; //allow or disallow form submission + }); + } + }); + } +}; + +formtowizard.routines={ + + getCookie:function(Name){ + var re=new RegExp(Name+"=[^;]+", "i"); //construct RE to search for target name/value pair + if (document.cookie.match(re)) return document.cookie.match(re)[0].split("=")[1]; //if cookie found return it's value + return null; + }, + + setCookie:function(name, value){ + document.cookie = name+"=" + value + ";path=/"; + } +}; diff --git a/gui/slick/js/lib/jquery-1.11.2.min.js b/gui/slick/js/lib/jquery-1.11.2.min.js deleted file mode 100644 index e6a051d0d1d32752ae08d9cf30fe5952da22a9b0..0000000000000000000000000000000000000000 Binary files a/gui/slick/js/lib/jquery-1.11.2.min.js and /dev/null differ diff --git a/gui/slick/js/lib/jquery-2.1.4.min.js b/gui/slick/js/lib/jquery-2.1.4.min.js new file mode 100644 index 0000000000000000000000000000000000000000..49990d6e14503798f142dcb0d5b23cb0c8f80244 Binary files /dev/null and b/gui/slick/js/lib/jquery-2.1.4.min.js differ diff --git a/gui/slick/js/massUpdate.js b/gui/slick/js/massUpdate.js index 7ec531d6213ae7a7339e0ce322867c83c068ec35..3d390c9cc1502b795b784e2ae20c840d98cb5d0f 100644 --- a/gui/slick/js/massUpdate.js +++ b/gui/slick/js/massUpdate.js @@ -49,7 +49,7 @@ $(document).ready(function(){ }); if(deleteCount >= 1) { - bootbox.confirm("You have selected to delete " + deleteCount + " show(s). Are you sure you wish to cntinue? All files will be removed from your system.", function(result) { + bootbox.confirm("You have selected to delete " + deleteCount + " show(s). Are you sure you wish to continue? All files will be removed from your system.", function(result) { if(result) { $('.deleteCheck').each(function() { if(this.checked === true) { diff --git a/gui/slick/js/moment/moment.min.js b/gui/slick/js/moment/moment.min.js deleted file mode 100644 index 3fe82adf13246e96fb251da403363752f3a20e40..0000000000000000000000000000000000000000 Binary files a/gui/slick/js/moment/moment.min.js and /dev/null differ diff --git a/gui/slick/js/new/comingEpisodes.js b/gui/slick/js/new/comingEpisodes.js index 62ba8e4305099bcd10e10ceb66f02377134e524e..c6de5a697996f4f61cb9a67b4e746b294f533c2e 100644 --- a/gui/slick/js/new/comingEpisodes.js +++ b/gui/slick/js/new/comingEpisodes.js @@ -1,7 +1,7 @@ $(document).ready(function(){ - if($('meta[data-var="sickbeard.COMING_EPS_LAYOUT"]').data('content') == 'list'){ + if(isMeta('sickbeard.COMING_EPS_LAYOUT', ['list'])){ var sortCodes = {'date': 0, 'show': 1, 'network': 4}; - var sort = $('meta[data-var="sickbeard.COMING_EPS_SORT"]').data('content'); + var sort = getMeta('sickbeard.COMING_EPS_SORT'); var sortList = (sort in sortCodes) ? [[sortCodes[sort], 0]] : [[0, 0]]; $('#showListTable:has(tbody tr)').tablesorter({ @@ -26,7 +26,8 @@ $(document).ready(function(){ $('#srRoot').ajaxEpSearch(); } - if($('meta[data-var="sickbeard.COMING_EPS_LAYOUT"]').data('content') == 'banner' || $('meta[data-var="sickbeard.COMING_EPS_LAYOUT"]').data('content') == 'poster'){ + + if(isMeta('sickbeard.COMING_EPS_LAYOUT', ['banner', 'poster'])){ $('#srRoot').ajaxEpSearch({'size': 16, 'loadingImage': 'loading16' + themeSpinner + '.gif'}); $('.ep_summary').hide(); $('.ep_summaryTrigger').click(function() { @@ -38,8 +39,3 @@ $(document).ready(function(){ }); } }); - -setTimeout(function () { - "use strict"; - location.reload(true); -}, 60000); diff --git a/gui/slick/js/new/config_backuprestore.js b/gui/slick/js/new/config_backuprestore.js index 143464c6165e53740b51b7875fa9510a5ba5590f..b721fac147cc1fea041a1b08c7a84f4e3b948618 100644 --- a/gui/slick/js/new/config_backuprestore.js +++ b/gui/slick/js/new/config_backuprestore.js @@ -2,7 +2,7 @@ $(document).ready(function(){ $('#backupDir').fileBrowser({ title: 'Select backup folder to save to', key: 'backupPath' }); $('#backupFile').fileBrowser({ title: 'Select backup files to restore', key: 'backupFile', includeFiles: 1 }); $('#config-components').tabs(); - + $(".enabler").each(function(){ if (!$(this).prop('checked')) $('#content_'+$(this).attr('id')).hide(); }); @@ -80,7 +80,7 @@ $(document).ready(function(){ $('#branchCheckout').click(function() { var url = srRoot+'/home/branchCheckout?branch='+$("#branchVersion").val(); - var checkDBversion = srRoot + "/home/getDBcompare"; + var checkDBversion = srRoot + "/home/getDBcompare"; $.getJSON(checkDBversion, function(data){ if (data.status == "success") { if (data.message == "equal") { diff --git a/gui/slick/js/new/config_subtitles.js b/gui/slick/js/new/config_subtitles.js index f970bf657070a5fcf85c6c918b205ed1c07fbca4..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/gui/slick/js/new/config_subtitles.js +++ b/gui/slick/js/new/config_subtitles.js @@ -1,10 +0,0 @@ -$(document).ready(function() { - $("#subtitles_languages").tokenInput([$('meta[data-var="subtitles.subtitleLanguageFilter"]').data('content')], { - method: "POST", - hintText: "Write to search a language and select it", - preventDuplicates: true, - prePopulate: [$('meta[data-var="prePopulate"]').data('content')] - }); -}); -$('#config-components').tabs(); -$('#subtitles_dir').fileBrowser({ title: 'Select Subtitles Download Directory' }); diff --git a/gui/slick/js/new/editShow.js b/gui/slick/js/new/editShow.js index 4742e1631810440b6259ee9fc1465711707aba30..3b566547940e47aa57064ba8666a27356bde7c91 100644 --- a/gui/slick/js/new/editShow.js +++ b/gui/slick/js/new/editShow.js @@ -11,7 +11,7 @@ $('#submit').click(function(){ $("#exceptions_list").val(all_exceptions); - if($('meta[data-var="show.is_anime"]').data('content') === 'True') generate_bwlist(); + if(metaToBool('show.is_anime')) generate_bwlist(); }); $('#addSceneName').click(function() { var scene_ex = $('#SceneName').val(); diff --git a/gui/slick/js/new/errorlogs.js b/gui/slick/js/new/errorlogs.js index 377fe7ae9063b4aba963505c174721256284b057..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/gui/slick/js/new/errorlogs.js +++ b/gui/slick/js/new/errorlogs.js @@ -1,4 +0,0 @@ -setTimeout(function () { - "use strict"; - location.reload(true); -}, 60000); diff --git a/gui/slick/js/new/history.js b/gui/slick/js/new/history.js index 6897dc21ac9ae9187f86569e9ff4f65fb9c92ed4..be5e503b09ad1ad79eed98d97cb02a54bf3fd2e0 100644 --- a/gui/slick/js/new/history.js +++ b/gui/slick/js/new/history.js @@ -3,7 +3,7 @@ $(document).ready(function(){ widgets: ['zebra', 'filter'], sortList: [[0,1]], textExtraction: (function(){ - if($('meta[data-var="layout"]').data('content') == 'detailed'){ + if(isMeta('sickbeard.HOME_LAYOUT', ['detailed'])){ return { 0: function(node) { return $(node).find('time').attr('datetime'); }, 4: function(node) { return $(node).find("span").text().toLowerCase(); } @@ -18,7 +18,7 @@ $(document).ready(function(){ } }()), headers: (function(){ - if($('meta[data-var="layout"]').data('content') == 'detailed'){ + if(isMeta('sickbeard.HOME_LAYOUT', ['detailed'])){ return { 0: { sorter: 'realISODate' }, 4: { sorter: 'quality' } diff --git a/gui/slick/js/new/home.js b/gui/slick/js/new/home.js index c2f342c60dc4715122de4435129c16eb926873ba..eca9c7196ffafefdc8dff8a073b3b2226b090db3 100644 --- a/gui/slick/js/new/home.js +++ b/gui/slick/js/new/home.js @@ -1,60 +1,3 @@ -$.tablesorter.addParser({ - id: 'loadingNames', - is: function(s) { - return false; - }, - format: function(s) { - if (s.indexOf('Loading...') === 0) - return s.replace('Loading...','000'); - else - return ($('meta[data-var="sickbeard.SORT_ARTICLE"]').data('content') == 'True' ? (s || '') : (s || '').replace(/^(The|A|An)\s/i,'')); - }, - type: 'text' -}); - -$.tablesorter.addParser({ - id: 'quality', - is: function(s) { - return false; - }, - 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' -}); - -$.tablesorter.addParser({ - id: 'eps', - is: function(s) { - return false; - }, - format: function(s) { - match = s.match(/^(.*)/); - - if (match === null || match[1] == "?") return -10; - - var nums = match[1].split(" / "); - if (nums[0].indexOf("+") != -1) { - var num_parts = nums[0].split("+"); - nums[0] = num_parts[0]; - } - - nums[0] = parseInt(nums[0]); - nums[1] = parseInt(nums[1]); - - if (nums[0] === 0) - return nums[1]; - - var finalNum = parseInt(($('meta[data-var="max_download_count"]').data('content'))*nums[0]/nums[1]); - var pct = Math.round((nums[0]/nums[1])*100) / 1000; - if (finalNum > 0) - finalNum += nums[0]; - - return finalNum + pct; - }, - type: 'numeric' -}); - $(document).ready(function(){ // Resets the tables sorting, needed as we only use a single call for both tables in tablesorter $('.resetsorting').on('click', function(){ @@ -88,7 +31,7 @@ $(document).ready(function(){ }, widgets: ['saveSort', 'zebra', 'stickyHeaders', 'filter', 'columnSelector'], headers: (function(){ - if($('meta[data-var="sickbeard.FILTER_ROW"]').data('content') == 'True'){ + if(metaToBool('sickbeard.FILTER_ROW')){ return { 0: { sorter: 'isoDate' }, 1: { columnSelector: false }, @@ -108,7 +51,7 @@ $(document).ready(function(){ } }()), widgetOptions: (function(){ - if($('meta[data-var="sickbeard.FILTER_ROW"]').data('content') == 'True'){ + if(metaToBool('sickbeard.FILTER_ROW')){ return { filter_columnFilters: true, filter_hideFilters : true, @@ -184,7 +127,7 @@ $(document).ready(function(){ $.tablesorter.filter.bindSearch( "#showListTableShows", $('.search') ); } - if(['True', 1].indexOf($('meta[data-var="sickbeard.ANIME_SPLIT_HOME"]').data('content')) >= 0){ + if(metaToBool('sickbeard.ANIME_SPLIT_HOME')){ if($("#showListTableAnime").find("tbody").find("tr").size() > 0){ $.tablesorter.filter.bindSearch( "#showListTableAnime", $('.search') ); } @@ -192,46 +135,46 @@ $(document).ready(function(){ var $container = [$('#container'), $('#container-anime')]; - $.each($container, function (j) { + $.each($container, function (j){ this.isotope({ itemSelector: '.show', - sortBy : $('meta[data-var="sickbeard.POSTER_SORTBY"]').data('content'), - sortAscending: $('meta[data-var="sickbeard.POSTER_SORTDIR"]').data('content'), + sortBy : getMeta('sickbeard.POSTER_SORTBY'), + sortAscending: getMeta('sickbeard.POSTER_SORTDIR'), layoutMode: 'masonry', masonry: { columnWidth: 13, isFitWidth: true }, getSortData: { - name: function( itemElem ) { - var name = $( itemElem ).attr('data-name'); - return ($('meta[data-var="sickbeard.SORT_ARTICLE"]').data('content') == 'True' ? (name || '') : (name || '').replace(/^(The|A|An)\s/i,'')); + name: function(itemElem){ + var name = $(itemElem).attr('data-name'); + return (metaToBool('sickbeard.SORT_ARTICLE') ? (name || '') : (name || '').replace(/^(The|A|An)\s/i,'')); }, network: '[data-network]', - date: function( itemElem ) { - var date = $( itemElem ).attr('data-date'); - return date.length && parseInt( date, 10 ) || Number.POSITIVE_INFINITY; + date: function(itemElem){ + var date = $(itemElem).attr('data-date'); + return date.length && parseInt(date, 10) || Number.POSITIVE_INFINITY; }, - progress: function( itemElem ) { - var progress = $( itemElem ).attr('data-progress'); - return progress.length && parseInt( progress, 10 ) || Number.NEGATIVE_INFINITY; + progress: function(itemElem){ + var progress = $(itemElem).attr('data-progress'); + return progress.length && parseInt(progress, 10) || Number.NEGATIVE_INFINITY; } } }); }); - $('#postersort').on( 'change', function() { + $('#postersort').on('change', function(){ var sortValue = this.value; - $('#container').isotope({ sortBy: sortValue }); - $('#container-anime').isotope({ sortBy: sortValue }); + $('#container').isotope({sortBy: sortValue}); + $('#container-anime').isotope({sortBy: sortValue}); $.get(this.options[this.selectedIndex].getAttribute('data-sort')); }); - $('#postersortdirection').on( 'change', function() { + $('#postersortdirection').on('change', function(){ var sortDirection = this.value; sortDirection = sortDirection == 'true'; - $('#container').isotope({ sortAscending: sortDirection }); - $('#container-anime').isotope({ sortAscending: sortDirection }); + $('#container').isotope({sortAscending: sortDirection}); + $('#container-anime').isotope({sortAscending: sortDirection}); $.get(this.options[this.selectedIndex].getAttribute('data-sort')); }); @@ -242,7 +185,7 @@ $(document).ready(function(){ }).on('shown.bs.popover', function () { // bootstrap popover event triggered when the popover opens // call this function to copy the column selection code into the popover $.tablesorter.columnSelector.attachTo( $('#showListTableShows'), '#popover-target'); - if(['True', 1].indexOf($('meta[data-var="sickbeard.ANIME_SPLIT_HOME"]').data('content')) >= 0){ + if(metaToBool('sickbeard.ANIME_SPLIT_HOME')){ $.tablesorter.columnSelector.attachTo( $('#showListTableAnime'), '#popover-target'); } diff --git a/gui/slick/js/new/home_addExistingShow.js b/gui/slick/js/new/home_addExistingShow.js index 744d4877dd8dafc6140a16da7552779e1ca3982f..3e3e8dc37f7dfb8c94b377dbae7a7cf56e473d71 100644 --- a/gui/slick/js/new/home_addExistingShow.js +++ b/gui/slick/js/new/home_addExistingShow.js @@ -1,6 +1,6 @@ $(document).ready(function(){ $( "#tabs" ).tabs({ collapsible: true, - selected: ($('meta[data-var="sickbeard.SORT_ARTICLE"]').data('content') == 'True' ? -1 : 0) + selected: (metaToBool('sickbeard.SORT_ARTICLE') ? -1 : 0) }); }); diff --git a/gui/slick/js/new/home_recommendedShows.js b/gui/slick/js/new/home_recommendedShows.js index 4e292d5854ff0918dc4a1f38c0bec27afa41dc1b..31d9535234cca1094d32ef460cc1a5e283250b79 100644 --- a/gui/slick/js/new/home_recommendedShows.js +++ b/gui/slick/js/new/home_recommendedShows.js @@ -1,7 +1,7 @@ $(document).ready(function(){ $( "#tabs" ).tabs({ collapsible: true, - selected: ($('meta[data-var="sickbeard.SORT_ARTICLE"]').data('content') == 'True' ? -1 : 0) + selected: (metaToBool('sickbeard.SORT_ARTICLE') ? -1 : 0) }); // initialise combos for dirty page refreshes @@ -17,7 +17,7 @@ $(document).ready(function(){ getSortData: { name: function( itemElem ) { var name = $( itemElem ).attr('data-name'); - return ($('meta[data-var="sickbeard.SORT_ARTICLE"]').data('content') == 'True' ? (name || '') : (name || '').replace(/^(The|A|An)\s/i,'')); + return (metaToBool('sickbeard.SORT_ARTICLE') ? (name || '') : (name || '').replace(/^(The|A|An)\s/i,'')); }, rating: '[data-rating] parseInt', votes: '[data-votes] parseInt', @@ -55,8 +55,3 @@ $(document).ready(function(){ $('#container').isotope({sortAscending: ('asc' == this.value)}); }); }); - -setTimeout(function () { - "use strict"; - location.reload(true); -}, 60000); diff --git a/gui/slick/js/new/home_trendingShows.js b/gui/slick/js/new/home_trendingShows.js index b96203a3ce019dc4e0f1fec3848f1dddf9aa2c5b..51e1e49b11cfc7808e4b570e99701e5d8136e566 100644 --- a/gui/slick/js/new/home_trendingShows.js +++ b/gui/slick/js/new/home_trendingShows.js @@ -1,5 +1,5 @@ $(document).ready(function(){ - $( "#tabs" ).tabs({ + $("#tabs").tabs({ collapsible: true, // selected: ${('0', '-1')[bool(sickbeard.ROOT_DIRS)]} }); @@ -15,7 +15,7 @@ $(document).ready(function(){ getSortData: { name: function( itemElem ) { var name = $(itemElem).attr('data-name') || ''; - return ($('meta[data-var="sickbeard.SORT_ARTICLE"]').data('content') == 'False' ? name.replace(/^(The|A|An)\s/i, '') : name).toLowerCase(); + return (metaToBool('sickbeard.SORT_ARTICLE') ? name : name.replace(/^(The|A|An)\s/i, '')).toLowerCase(); }, rating: '[data-rating] parseInt', votes: '[data-votes] parseInt', @@ -52,4 +52,3 @@ $(document).ready(function(){ $('#container').isotope({sortAscending: ('asc' == this.value)}); }); }); -window.setInterval('location.reload(true)', 600000); // Refresh every 10 minutes diff --git a/gui/slick/js/new/manage.js b/gui/slick/js/new/manage.js index 6a6754dd7f5c81187d6d4231161e2165b1d643e6..a601c7b5e39c5568204587b188d0166c47e0417f 100644 --- a/gui/slick/js/new/manage.js +++ b/gui/slick/js/new/manage.js @@ -1,24 +1,3 @@ -$.tablesorter.addParser({ - id: 'showNames', - is: function(s) { - return false; - }, - format: function(s) { - return ($('meta[data-var="sickbeard.SORT_ARTICLE"]').data('content') == 'True' ? (s || '') : (s || '').replace(/^(The|A|An)\s/i,'')); - }, - type: 'text' -}); -$.tablesorter.addParser({ - id: 'quality', - is: function(s) { - return false; - }, - format: function(s) { - return s.replace('hd1080p',5).replace('hd720p',4).replace('hd',3).replace('sd',2).replace('any',1).replace('best',0).replace('custom',7); - }, - type: 'numeric' -}); - $(document).ready(function(){ $("#massUpdateTable:has(tbody tr)").tablesorter({ sortList: [[1,0]], @@ -30,6 +9,7 @@ $(document).ready(function(){ 6: function(node) { return $(node).find("img").attr("alt"); }, 7: function(node) { return $(node).find("img").attr("alt"); }, 8: function(node) { return $(node).find("img").attr("alt"); }, + 9: function(node) { return $(node).find("img").attr("alt"); }, }, widgets: ['zebra'], headers: { @@ -40,11 +20,11 @@ $(document).ready(function(){ 4: { sorter: 'scene'}, 5: { sorter: 'anime'}, 6: { sorter: 'flatfold'}, - 7: { sorter: 'paused'}, - 8: { sorter: 'subtitle'}, - 9: { sorter: 'default_ep_status'}, - 10: { sorter: 'status'}, - 11: { sorter: false}, + 7: { sorter: 'archive_firstmatch'}, + 8: { sorter: 'paused'}, + 9: { sorter: 'subtitle'}, + 10: { sorter: 'default_ep_status'}, + 11: { sorter: 'status'}, 12: { sorter: false}, 13: { sorter: false}, 14: { sorter: false}, diff --git a/gui/slick/js/new/meta.js b/gui/slick/js/new/meta.js new file mode 100644 index 0000000000000000000000000000000000000000..65056db8123a09d3fb35c48fb6eab47e16f52110 --- /dev/null +++ b/gui/slick/js/new/meta.js @@ -0,0 +1,14 @@ +function metaToBool(pyVar){ + var meta = $('meta[data-var="' + pyVar + '"]').data('content'); + meta = (isNaN(meta) ? meta.toLowerCase() : meta.toString()); + return !(meta === 'false' || meta === 'none' || meta === '0'); +} + +function getMeta(pyVar){ + return $('meta[data-var="' + pyVar + '"]').data('content'); +} + +function isMeta(pyVar, result){ + var reg = new RegExp(result.length > 1 ? result.join('|') : result); + return (reg).test($('meta[data-var="' + pyVar + '"]').data('content')); +} diff --git a/gui/slick/js/new/parsers.js b/gui/slick/js/new/parsers.js index a4d0bba30e2b6a423acfc793e6b483d8ecbbc784..5c46465712677c1473ea8facce7d1b579fc6a56c 100644 --- a/gui/slick/js/new/parsers.js +++ b/gui/slick/js/new/parsers.js @@ -7,7 +7,7 @@ $.tablesorter.addParser({ if (0 === s.indexOf('Loading...')){ return s.replace('Loading...', '000'); } else { - return ($('meta[data-var="sickbeard.SORT_ARTICLE"]').data('content') == 'False' ? (s || '') : (s || '').replace(/^(The|A|An)\s/i,'')); + return (metaToBool('sickbeard.SORT_ARTICLE') ? (s || '') : (s || '').replace(/^(The|A|An)\s/i,'')); } }, type: 'text' @@ -43,3 +43,31 @@ $.tablesorter.addParser({ }, type: 'numeric' }); +$.tablesorter.addParser({ + id: 'eps', + is: function(s) { + return false; + }, + format: function(s) { + match = s.match(/^(.*)/); + + if (match === null || match[1] == "?") return -10; + + var nums = match[1].split(" / "); + if (nums[0].indexOf("+") != -1) { + var num_parts = nums[0].split("+"); + nums[0] = num_parts[0]; + } + + nums[0] = parseInt(nums[0]); + nums[1] = parseInt(nums[1]); + + if (nums[0] === 0) return nums[1]; + var finalNum = parseInt((getMeta('max_download_count'))*nums[0]/nums[1]); + var pct = Math.round((nums[0]/nums[1])*100) / 1000; + if (finalNum > 0) finalNum += nums[0]; + + return finalNum + pct; + }, + type: 'numeric' +}); diff --git a/gui/slick/js/new/trendingShows.js b/gui/slick/js/new/trendingShows.js index 9b50dfc2da1c3eaa7c52d77059e43760dfb1baa8..b65df539d17e4b370036a55bc452a4f6ac3f976c 100644 --- a/gui/slick/js/new/trendingShows.js +++ b/gui/slick/js/new/trendingShows.js @@ -12,7 +12,7 @@ $(document).ready(function(){ getSortData: { name: function(itemElem) { var name = $(itemElem).attr('data-name') || ''; - return ($('meta[data-var="sickbeard.SORT_ARTICLE"]').data('content') == 'False' ? name.replace(/^(The|A|An)\s/i, '') : name).toLowerCase(); + return (metaToBool('sickbeard.SORT_ARTICLE') ? name : name.replace(/^(The|A|An)\s/i, '')).toLowerCase(); }, rating: '[data-rating] parseInt', votes: '[data-votes] parseInt', @@ -50,8 +50,3 @@ $(document).ready(function(){ $('#container').isotope({sortAscending: ('asc' == this.value)}); }); }); - -setTimeout(function () { - "use strict"; - location.reload(true); -}, 60000); diff --git a/gui/slick/js/new/viewlogs.js b/gui/slick/js/new/viewlogs.js index 09423b3213773e5e63d867383fd4e141ef9301c8..351f23444359e5e42451f46d635e0468373c3921 100644 --- a/gui/slick/js/new/viewlogs.js +++ b/gui/slick/js/new/viewlogs.js @@ -8,7 +8,7 @@ $(document).ready(function(){ $('#minLevel').prop('disabled', true); $('#logFilter').prop('disabled', true); $('#logSearch').prop('disabled', true); - document.body.style.cursor='wait' + document.body.style.cursor='wait'; url = srRoot + '/errorlogs/viewlog/?minLevel='+$('select[name=minLevel]').val()+'&logFilter='+$('select[name=logFilter]').val()+'&logSearch='+$('#logSearch').val(); $.get(url, function(data){ history.pushState('data', '', url); @@ -16,6 +16,7 @@ $(document).ready(function(){ $('#minLevel').removeProp('disabled'); $('#logFilter').removeProp('disabled'); $('#logSearch').removeProp('disabled'); + document.body.style.cursor='default'; }); }); @@ -53,8 +54,3 @@ $(document).ready(function(){ } }); }); - -setTimeout(function () { - "use strict"; - location.reload(true); -}, 60000); diff --git a/gui/slick/js/script.js b/gui/slick/js/script.js index 63ccea508dd32364b498f9792ad2b5334b34cb74..d3733a5d9976cef0b8e3d8b42c59f61e56aeaf25 100644 --- a/gui/slick/js/script.js +++ b/gui/slick/js/script.js @@ -1,3 +1,8 @@ +var srRoot = getMeta('srRoot'), + themeSpinner = getMeta('themeSpinner'), + anonURL = getMeta('anonURL'), + top_image_html = '<img src="' + srRoot + '/images/top.gif" width="31" height="11" alt="Jump to top" />'; + function initHeader() { //settings var header = $("#header"); @@ -59,27 +64,6 @@ function resetFilters(text) { } } -function initFancybox() { - if ($("a[rel=dialog]").length > 0) { - $.getScript(srRoot + '/js/fancybox/jquery.fancybox.pack.js', function () { - $("head").append("<link rel='stylesheet' href='" + srRoot + "/js/fancybox/jquery.fancybox.css'>"); - $("a[rel=dialog]").fancybox({ - type: "image", - padding: 0, - helpers : { - title : null, - overlay : { - locked: false, - css : { - 'background' : 'rgba(0, 0, 0, 0.4)' - } - } - } - }); - }); - } -} - function initTabs() { $("#config-components").tabs({ activate: function (event, ui) { @@ -125,7 +109,6 @@ function initTabs() { function init() { initHeader(); - initFancybox(); initTabs(); } @@ -133,7 +116,7 @@ $(document).ready(function () { init(); $(document).ready(function() { $('.dropdown-toggle').dropdownHover(); - if(['True', 1].indexOf($('meta[data-var="sickbeard.FUZZY_DATING"]').data('content')) >= 0){ + if(metaToBool('sickbeard.FUZZY_DATING')){ $.timeago.settings.allowFuture = true; $.timeago.settings.strings = { prefixAgo: null, @@ -143,13 +126,13 @@ $(document).ready(function () { seconds: "less than a minute", minute: "about a minute", minutes: "%d minutes", - hour: "about an hour", - hours: "about %d hours", + hour: "an hour", + hours: "%d hours", day: "a day", days: "%d days", - month: "about a month", + month: "a month", months: "%d months", - year: "about a year", + year: "a year", years: "%d years", wordSeparator: " ", numbers: [] diff --git a/gui/slick/views/comingEpisodes.mako b/gui/slick/views/comingEpisodes.mako index 75740dbbc377376e7e3717ccf2f9407177203ccf..345a653e31f911f1817b0353292cef36ad4167cb 100644 --- a/gui/slick/views/comingEpisodes.mako +++ b/gui/slick/views/comingEpisodes.mako @@ -7,10 +7,6 @@ import time import re %> -<%block name="metas"> -<meta data-var="sickbeard.COMING_EPS_SORT" data-content="${sickbeard.COMING_EPS_SORT}"> -<meta data-var="sickbeard.COMING_EPS_LAYOUT" data-content="${sickbeard.COMING_EPS_LAYOUT}"> -</%block> <%block name="scripts"> <script type="text/javascript" src="${srRoot}/js/ajaxEpSearch.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/plotTooltip.js?${sbPID}"></script> @@ -58,9 +54,9 @@ % if 'calendar' != layout: <b>Key:</b> <span class="listing-key listing-overdue">Missed</span> - <span class="listing-key listing-current">Current</span> - <span class="listing-key listing-default">Future</span> - <span class="listing-key listing-toofar">Distant</span> + <span class="listing-key listing-current">Today</span> + <span class="listing-key listing-default">Soon</span> + <span class="listing-key listing-toofar">Later</span> % endif <a class="btn btn-inline forceBacklog" href="webcal://${sbHost}:${sbHttpPort}/calendar"> <i class="icon-calendar icon-white"></i>Subscribe</a> @@ -133,7 +129,7 @@ <td> % if cur_result['description']: - <img alt='' src='${srRoot}/images/info32.png' height='16' width='16' class='plotInfo' id="plot_info_${'%s_%s_%s' % (str(cur_result['showid']), str(cur_result['season']), str(cur_result['episode']))}" /> + <img alt="" src="${srRoot}/images/info32.png" height="16" width="16" class="plotInfo" id="plot_info_${'%s_%s_%s' % (str(cur_result['showid']), str(cur_result['season']), str(cur_result['episode']))}" /> % else: <img alt="" src="${srRoot}/images/info32.png" width="16" height="16" class="plotInfoNone" /> % endif @@ -152,11 +148,15 @@ % if cur_result['imdb_id']: <a href="${anon_url('http://www.imdb.com/title/', cur_result['imdb_id'])}" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="http://www.imdb.com/title/${cur_result['imdb_id']}"><img alt="[imdb]" height="16" width="16" src="${srRoot}/images/imdb.png" /> % endif - <a href="${anon_url(sickbeard.indexerApi(cur_indexer).config['show_url'], cur_result['showid'])}" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="${sickbeard.indexerApi(cur_indexer).config['show_url']}${cur_result['showid']}"><img alt="${sickbeard.indexerApi(cur_indexer).name}" height="16" width="16" src="${srRoot}/images/${sickbeard.indexerApi(cur_indexer).config['icon']}" /></a> + <a href="${anon_url(sickbeard.indexerApi(cur_indexer).config['show_url'], cur_result['showid'])}" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="${sickbeard.indexerApi(cur_indexer).config['show_url']}${cur_result['showid']}"> + <img alt="${sickbeard.indexerApi(cur_indexer).name}" height="16" width="16" src="${srRoot}/images/${sickbeard.indexerApi(cur_indexer).config['icon']}" /> + </a> </td> <td align="center"> - <a href="${srRoot}/home/searchEpisode?show=${cur_result['showid']}&season=${cur_result['season']}&episode=${cur_result['episode']}" title="Manual Search" id="forceUpdate-${cur_result['showid']}x${cur_result['season']}x${cur_result['episode']}" class="forceUpdate epSearch"><img alt="[search]" height="16" width="16" src="${srRoot}/images/search16.png" id="forceUpdateImage-${cur_result['showid']}" /></a> + <a href="${srRoot}/home/searchEpisode?show=${cur_result['showid']}&season=${cur_result['season']}&episode=${cur_result['episode']}" title="Manual Search" id="forceUpdate-${cur_result['showid']}x${cur_result['season']}x${cur_result['episode']}" class="forceUpdate epSearch"> + <img alt="[search]" height="16" width="16" src="${srRoot}/images/search16.png" id="forceUpdateImage-${cur_result['showid']}" /> + </a> </td> </tr> % endfor @@ -285,7 +285,9 @@ <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr> <th ${('class="nobg"', 'rowspan="2"')[banner == layout]} valign="top"> - <a href="${srRoot}/home/displayShow?show=${cur_result['showid']}"><img alt="" class="${('posterThumb', 'bannerThumb')[layout == 'banner']}" src="${srRoot}/showPoster/?show=${cur_result['showid']}&which=${(layout, 'poster_thumb')[layout == 'poster']}" /></a> + <a href="${srRoot}/home/displayShow?show=${cur_result['showid']}"> + <img alt="" class="${('posterThumb', 'bannerThumb')[layout == 'banner']}" src="${srRoot}/showPoster/?show=${cur_result['showid']}&which=${(layout, 'poster_thumb')[layout == 'poster']}" /> + </a> </th> % if 'banner' == layout: </tr> @@ -295,10 +297,9 @@ <div class="clearfix"> <span class="tvshowTitle"> <a href="${srRoot}/home/displayShow?show=${cur_result['showid']}">${cur_result['show_name']} - % if int(cur_result['paused']): - <span class="pause">[paused]</span> - % endif - </a></span> + ${('', '<span class="pause">[paused]</span>')[int(cur_result['paused'])]} + </a> + </span> <span class="tvshowTitleIcons"> % if cur_result['imdb_id']: @@ -312,7 +313,6 @@ <span class="title">Next Episode:</span> <span>${'S%02iE%02i' % (int(cur_result['season']), int(cur_result['episode']))} - ${cur_result['name']}</span> <div class="clearfix"> - <span class="title">Airs: </span><span class="airdate">${sbdatetime.sbdatetime.sbfdatetime(cur_result['localtime']).decode(sickbeard.SYS_ENCODING)}</span>${('', '<span> on %s</span>' % str(cur_result['network']))[bool(cur_result['network'])]} </div> @@ -333,7 +333,7 @@ <img class="ep_summaryTriggerNone" src="${srRoot}/images/plus.png" height="16" width="16" alt="" /> % endif </div> - </td> + </td> </tr> </table> </div> @@ -346,8 +346,6 @@ % endif % if 'calendar' == layout: - -## <% today = datetime.date.today() %> <% dates = [today.date() + datetime.timedelta(days = i) for i in range(7)] %> <% tbl_day = 0 %> <br> diff --git a/gui/slick/views/config_general.mako b/gui/slick/views/config_general.mako index 22ae8d9ff2a4d14cc2ddeaa48054a02f7c43a4a0..1590a78cb4dd8f212adc2b911241b41565f1e4c1 100644 --- a/gui/slick/views/config_general.mako +++ b/gui/slick/views/config_general.mako @@ -611,14 +611,27 @@ </span> </label> </div> + + <div class="field-pair"> + <label for="skip_removed_files"> + <span class="component-title">Skip Remove Detection</span> + <span class="component-desc"> + <input type="checkbox" name="skip_removed_files" id="skip_removed_files" ${('', 'checked="checked"')[bool(sickbeard.SKIP_REMOVED_FILES)]}/> + <p>Skip detection of removed files. If disable it will set default deleted status</p> + </span> + <div class="clear-left"> + <span class="component-desc"><b>NOTE:</b> This may mean SickRage misses renames as well</span> + </div> + </div> + <div class="field-pair"> <label for="ep_default_deleted_status"> <span class="component-title">Default deleted episode status:</span> <span class="component-desc"> % if not sickbeard.SKIP_REMOVED_FILES: <select name="ep_default_deleted_status" id="ep_default_deleted_status" class="form-control input-sm"> - % for defStatus in [SKIPPED, IGNORED]: - <option value="${defStatus}" ${('', 'selected="selected"')[sickbeard.EP_DEFAULT_DELETED_STATUS == defStatus]}>${statusStrings[defStatus]}</option> + % for defStatus in [SKIPPED, IGNORED, ARCHIVED]: + <option value="${defStatus}" ${('', 'selected="selected"')[int(sickbeard.EP_DEFAULT_DELETED_STATUS) == defStatus]}>${statusStrings[defStatus]}</option> % endfor </select> % else: @@ -630,6 +643,10 @@ <input type="hidden" name="ep_default_deleted_status" value="${sickbeard.EP_DEFAULT_DELETED_STATUS}" /> % endif <span>Define the status to be set for media file that has been deleted.</span> + <div class="clear-left"> + <p> <b>NOTE:</b> Archived option will keep previous downloaded quality</p> + <p>Example: Downloaded (1080p WEB-DL) ==> Archived (1080p WEB-DL)</p> + </div> </span> </label> </div> diff --git a/gui/slick/views/config_postProcessing.mako b/gui/slick/views/config_postProcessing.mako index a9084a4fe896eca58f2ba98c6bf5c5713d831c87..0eb190463ecdcee03c2ccb72a802f375fceb39c7 100644 --- a/gui/slick/views/config_postProcessing.mako +++ b/gui/slick/views/config_postProcessing.mako @@ -103,17 +103,6 @@ <span class="component-desc">Delete content of RAR files, even if Process Method not set to move?</span> </label> </div> - <div class="field-pair"> - <input type="checkbox" name="skip_removed_files" id="skip_removed_files" ${('', 'checked="checked"')[bool(sickbeard.SKIP_REMOVED_FILES)]}/> - <label for="skip_removed_files"> - <span class="component-title">Skip Remove Detection</span> - <span class="component-desc">Skip detection of removed files, so they don't get set to ignored/archived?</span> - </label> - <label class="nocheck"> - <span class="component-title"> </span> - <span class="component-desc"><b>NOTE:</b> This may mean SickRage misses renames as well</span> - </label> - </div> <div class="field-pair"> <label class="nocheck"> <span class="component-title">Extra Scripts</span> diff --git a/gui/slick/views/config_subtitles.mako b/gui/slick/views/config_subtitles.mako index 3adac686d3b262e37a0799629cbcdfc7f69c0a23..98d9bb97ce0bc576a566fe22232b460f1232d55a 100644 --- a/gui/slick/views/config_subtitles.mako +++ b/gui/slick/views/config_subtitles.mako @@ -4,15 +4,10 @@ import sickbeard from sickbeard.helpers import anon_url %> -<%block name="metas"> -## <meta data-var="subtitles.subtitleLanguageFilter" data-content="${','.join("{id: " + lang.opensubtitles + ", name: " + lang.name + "}" for lang in subtitles.subtitleLanguageFilter())}"> -## <meta data-var="prePopulate" data-content="${','.join("{id: " + subtitles.fromietf(lang).opensubtitles + ", name: " + subtitles.fromietf(lang).name + "}" for lang in subtitles.wantedLanguages()) if subtitles.wantedLanguages() else ''}"> -</%block> <%block name="scripts"> <script type="text/javascript" src="${srRoot}/js/configSubtitles.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/config.js"></script> <script type="text/javascript" src="${srRoot}/js/lib/jquery.tokeninput.js"></script> -## <script type="text/javascript" src="${srRoot}/js/new/config_subtitles.js"></script> <script> $(document).ready(function() { $("#subtitles_languages").tokenInput([${','.join("{\"id\": \"" + lang.opensubtitles + "\", name: \"" + lang.name + "\"}" for lang in subtitles.subtitleLanguageFilter())}], { @@ -56,7 +51,7 @@ $('#subtitles_dir').fileBrowser({ title: 'Select Subtitles Download Directory' } <label for="use_subtitles" class="clearfix"> <span class="component-title">Search Subtitles</span> <span class="component-desc"> - <input type="checkbox" class="enabler" ${("", " checked=\"checked\"")[bool(sickbeard.USE_SUBTITLES)]} id="use_subtitles" name="use_subtitles"> + <input type="checkbox" class="enabler" ${('', ' checked="checked"')[bool(sickbeard.USE_SUBTITLES)]} id="use_subtitles" name="use_subtitles"> </span> </label> </div> diff --git a/gui/slick/views/displayShow.mako b/gui/slick/views/displayShow.mako index 1461b4c312db02434d56d2c30e9555cb77bc9544..5476568f6051a7205c64de9cb79d25bc9111f2c4 100644 --- a/gui/slick/views/displayShow.mako +++ b/gui/slick/views/displayShow.mako @@ -260,7 +260,7 @@ <label for="snatched"><span class="snatched"><input type="checkbox" id="snatched"checked="checked" /> Snatched: <b>${epCounts[Overview.SNATCHED]}</b></span></label> </div> - <button id="popover" type="button" class="btn btn-xs">Select Columns</button> + <button id="popover" type="button" class="btn btn-xs">Select Columns <b class="caret"></b></button> <div class="pull-right" > <button class="btn btn-xs seriesCheck">Select Filtered Episodes</button> <button class="btn btn-xs clearAll">Clear All</button> @@ -311,6 +311,8 @@ dfltEpNumbering = True epLoc = epResult["location"] + if epLoc and show._location and epLoc.lower().startswith(show._location.lower()): + epLoc = epLoc[len(show._location)+1:] %> % if int(epResult["season"]) != curSeason: % if curSeason == -1: @@ -420,7 +422,6 @@ % endif <% curSeason = int(epResult["season"]) %> % endif - <% epLoc = epResult["location"] %> <tr class="${Overview.overviewStrings[epCats[epStr]]} season-${curSeason} seasonstyle"> <td class="col-checkbox"> % if int(epResult["status"]) != UNAIRED: @@ -431,13 +432,9 @@ <td align="center"><img src="${srRoot}/images/${("tbn-no.gif", "tbn.gif")[epResult["hastbn"]]}" alt="${("N", "Y")[epResult["hastbn"]]}" width="23" height="11" /></td> <td align="center"> <% - if epLoc and show._location and epLoc.lower().startswith(show._location.lower()): - epLoc = epLoc[len(show._location)+1:] - + text = str(epResult['episode']) if epLoc != '' and epLoc != None: - text = '<span title="' + epLoc + '" class="addQTip">' + str(epResult['episode']) + "</span>" - else: - text = str(epResult['episode']) + text = '<span title="' + epLoc + '" class="addQTip">' + text + "</span>" %> ${text} </td> @@ -474,16 +471,19 @@ % endif ${epResult["name"]} </td> - <td class="col-name]"> - ${ntpath.basename((epResult['location'] or '').replace('\\','\\\\'))} - </td> + <td class="col-name">${epLoc}</td> <td class="col-ep"> % if epResult["file_size"]: <% file_size = sickbeard.helpers.pretty_filesize(epResult["file_size"]) %> ${file_size} % endif </td> - <% date = sbdatetime.sbdatetime.convert_to_setting(network_timezones.parse_date_time(epResult['airdate'], show.airs, show.network)) %> + % if epResult['airdate'] > int(datetime.datetime.now().toordinal()) * 100: + <% tempDate = datetime.datetime.utcfromtimestamp(0) + datetime.timedelta(seconds=epResult['airdate']) %> + % else: + <% tempDate = epResult['airdate'] %> + % endif + <% date = sbdatetime.sbdatetime.convert_to_setting(network_timezones.parse_date_time(tempDate, show.airs, show.network)) %> <td class="col-airdate"> % if int(epResult['airdate']) != 1: <time datetime="${date.isoformat('T')}" class="date">${sbdatetime.sbdatetime.sbfdate(date)}</time> @@ -491,7 +491,6 @@ Never % endif <span class="sort_data">${date.isoformat('T')}</span> - </td> <td> % if sickbeard.DOWNLOAD_URL and epResult['location']: diff --git a/gui/slick/views/history.mako b/gui/slick/views/history.mako index 3092a237eb903ffda1fafd432389ab3368bbea1e..a3a758ef3df176bb20934009f8a1d7b2b5474098 100644 --- a/gui/slick/views/history.mako +++ b/gui/slick/views/history.mako @@ -23,10 +23,6 @@ .sort_data {display:none;} </style> </%block> -<%block name="metas"> -<meta data-var="sickbeard.FUZZY_DATING" data-content="${sickbeard.FUZZY_DATING}"> -<meta data-var="layout" data-content="${layout}"> -</%block> <%block name="scripts"> <script type="text/javascript" src="${srRoot}/js/new/history.js"></script> </%block> diff --git a/gui/slick/views/home.mako b/gui/slick/views/home.mako index 726cf77eace291acaf9a71ed07b5db75a0ff7191..4c6c5d43f33b663f6cfc756d1219710915822032 100644 --- a/gui/slick/views/home.mako +++ b/gui/slick/views/home.mako @@ -40,17 +40,7 @@ max_download_count = max_download_count * 100 %> <%block name="metas"> -<meta data-var="sickbeard.SORT_ARTICLE" data-content="${sickbeard.SORT_ARTICLE}"> -<meta data-var="sickbeard.FILTER_ROW" data-content="${sickbeard.FILTER_ROW}"> -<meta data-var="sickbeard.ANIME_SPLIT_HOME" data-content="${sickbeard.ANIME_SPLIT_HOME}"> -<meta data-var="sickbeard.POSTER_SORTBY" data-content="${sickbeard.POSTER_SORTBY}"> -<meta data-var="sickbeard.POSTER_SORTDIR" data-content="${sickbeard.POSTER_SORTDIR}"> -<meta data-var="sickbeard.FUZZY_DATING" data-content="${sickbeard.FUZZY_DATING}"> -<meta data-var="sickbeard.DATE_PRESET" data-content="${sickbeard.DATE_PRESET}"> -<meta data-var="sickbeard.TIME_PRESET" data-content="${sickbeard.TIME_PRESET}"> -<meta data-var="sickbeard.TRIM_ZERO" data-content="${sickbeard.TRIM_ZERO}"> <meta data-var="max_download_count" data-content="${max_download_count}"> -<meta data-var="layout" data-content="${layout}"> </%block> <%block name="scripts"> <script type="text/javascript" src="${srRoot}/js/new/home.js"></script> @@ -65,7 +55,7 @@ <div id="HomeLayout" class="pull-right hidden-print" style="margin-top: -40px;"> % if layout != 'poster': - <button id="popover" type="button" class="btn btn-inline">Select Column <b class="caret"></b></button> + <button id="popover" type="button" class="btn btn-inline">Select Columns <b class="caret"></b></button> % endif <span> Layout: <select name="layout" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;"> @@ -396,7 +386,7 @@ % if layout == 'small': <td class="tvShow"> <div class="imgsmallposter ${layout}"> - <a href="${srRoot}/showPoster/?show=${curShow.indexerid}&which=${layout}" rel="dialog" title="${curShow.name}"> + <a href="${srRoot}/home/displayShow?show=${curShow.indexerid}" title="${curShow.name}"> <img src="${srRoot}/showPoster/?show=${curShow.indexerid}&which=poster_thumb" class="${layout}" alt="${curShow.indexerid}"/> </a> <a href="${srRoot}/home/displayShow?show=${curShow.indexerid}" style="vertical-align: middle;">${curShow.name}</a> diff --git a/gui/slick/views/home_addExistingShow.mako b/gui/slick/views/home_addExistingShow.mako index 2733d59359cd001346ea859ba215f89e3b23b948..3e029e48659fdf575bd963712fc2c4a0b528b295 100644 --- a/gui/slick/views/home_addExistingShow.mako +++ b/gui/slick/views/home_addExistingShow.mako @@ -2,9 +2,6 @@ <%! import sickbeard %> -<%block name="metas"> -<meta data-var="sickbeard.ROOT_DIRS" data-content="${sickbeard.ROOT_DIRS}"> -</%block> <%block name="scripts"> <script type="text/javascript" src="${srRoot}/js/qualityChooser.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/addExistingShow.js?${sbPID}"></script> diff --git a/gui/slick/views/home_newShow.mako b/gui/slick/views/home_newShow.mako index 4b982f2f590c16d012380db0dfd3c22991772049..0a13df2591ecbc1da377a737920e03ae6bebdcbb 100644 --- a/gui/slick/views/home_newShow.mako +++ b/gui/slick/views/home_newShow.mako @@ -4,7 +4,6 @@ from sickbeard.helpers import anon_url %> <%block name="scripts"> -<script type="text/javascript" src="${srRoot}/js/formwizard.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/qualityChooser.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/newShow.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/addShowOptions.js?${sbPID}"></script> diff --git a/gui/slick/views/home_recommendedShows.mako b/gui/slick/views/home_recommendedShows.mako index a7f6c97517c2c789dda6974db02699b4644bd9de..4405682a5838f912154bc9d57acfd4a15f925519 100644 --- a/gui/slick/views/home_recommendedShows.mako +++ b/gui/slick/views/home_recommendedShows.mako @@ -2,9 +2,6 @@ <%! import sickbeard %> -<%block name="metas"> -<meta data-var="sickbeard.SORT_ARTICLE" data-content="${sickbeard.SORT_ARTICLE}"> -</%block> <%block name="scripts"> <script type="text/javascript" src="${srRoot}/js/recommendedShows.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/rootDirs.js?${sbPID}"></script> diff --git a/gui/slick/views/home_trendingShows.mako b/gui/slick/views/home_trendingShows.mako index 55c8dd0d253e2ba1d5291d8c14c9b6b8ea8c2f1d..8c2739b68e66916323741d1141d6c7bd1da331cf 100644 --- a/gui/slick/views/home_trendingShows.mako +++ b/gui/slick/views/home_trendingShows.mako @@ -8,9 +8,6 @@ from sickbeard import sbdatetime from sickbeard.helpers import anon_url %> -<%block name="metas"> -<meta data-var="sickbeard.SORT_ARTICLE" data-content="${sickbeard.SORT_ARTICLE}"> -</%block> <%block name="scripts"> <script type="text/javascript" src="${srRoot}/js/addTrendingShow.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/rootDirs.js?${sbPID}"></script> diff --git a/gui/slick/views/layouts/main.mako b/gui/slick/views/layouts/main.mako index 4b2ee1e66b42489a2820581012f728c110f52b38..acf81e75a52786bb698bc5238cfa4f0dadc6564a 100644 --- a/gui/slick/views/layouts/main.mako +++ b/gui/slick/views/layouts/main.mako @@ -43,7 +43,25 @@ <meta name="msapplication-TileImage" content="${srRoot}/images/ico/favicon-144.png"> <meta name="msapplication-config" content="${srRoot}/css/browserconfig.xml"> + + <meta data-var="srRoot" data-content="${srRoot}"> + <meta data-var="themeSpinner" data-content="${('', '-dark')[sickbeard.THEME_NAME == 'dark']}"> + <meta data-var="anonURL" data-content="${sickbeard.ANON_REDIRECT}"> + + <meta data-var="sickbeard.ANIME_SPLIT_HOME" data-content="${sickbeard.ANIME_SPLIT_HOME}"> + <meta data-var="sickbeard.COMING_EPS_LAYOUT" data-content="${sickbeard.COMING_EPS_LAYOUT}"> + <meta data-var="sickbeard.COMING_EPS_SORT" data-content="${sickbeard.COMING_EPS_SORT}"> + <meta data-var="sickbeard.DATE_PRESET" data-content="${sickbeard.DATE_PRESET}"> + <meta data-var="sickbeard.FILTER_ROW" data-content="${sickbeard.FILTER_ROW}"> <meta data-var="sickbeard.FUZZY_DATING" data-content="${sickbeard.FUZZY_DATING}"> + <meta data-var="sickbeard.HOME_LAYOUT" data-content="${sickbeard.HOME_LAYOUT}"> + <meta data-var="sickbeard.POSTER_SORTBY" data-content="${sickbeard.POSTER_SORTBY}"> + <meta data-var="sickbeard.POSTER_SORTDIR" data-content="${sickbeard.POSTER_SORTDIR}"> + <meta data-var="sickbeard.ROOT_DIRS" data-content="${sickbeard.ROOT_DIRS}"> + <meta data-var="sickbeard.SORT_ARTICLE" data-content="${sickbeard.SORT_ARTICLE}"> + <meta data-var="sickbeard.SORT_ARTICLE" data-content="${sickbeard.SORT_ARTICLE}"> + <meta data-var="sickbeard.TIME_PRESET" data-content="${sickbeard.TIME_PRESET}"> + <meta data-var="sickbeard.TRIM_ZERO" data-content="${sickbeard.TRIM_ZERO}"> <%block name="metas" /> <link rel="shortcut icon" href="${srRoot}/images/ico/favicon.ico"> @@ -92,26 +110,35 @@ % if sbLogin: <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav navbar-right"> - <li id="NAVnews" ${('', 'class="active"')[topmenu == 'news']}> + <li id="NAVnews"${('', ' class="active"')[topmenu == 'news']}> <a href="${srRoot}/news/">News</a> </li> - <li id="NAVirc" ${('', 'class="active"')[topmenu == 'irc']}> + <li id="NAVirc"${('', ' class="active"')[topmenu == 'irc']}> <a href="${srRoot}/IRC/">IRC</a> </li> - <li id="NAVhome" ${('', 'class="active"')[topmenu == 'home']}> - <a href="${srRoot}/home/">Shows</a> + + <li id="NAVhome" class="navbar-split dropdown${('', ' active')[topmenu == 'home']}"> + <a href="${srRoot}/home/" class="dropdown-toggle">Shows</a> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"><b class="caret"></b></a> + <ul class="dropdown-menu"> + <li><a href="${srRoot}/home/"><i class="menu-icon-home"></i> Show List</a></li> + <li><a href="${srRoot}/home/addShows/"><i class="menu-icon-addshow"></i> Add Shows</a></li> + <li><a href="${srRoot}/home/postprocess/"><i class="menu-icon-postprocess"></i> Manual Post-Processing</a></li> + </ul> + <div style="clear:both;"></div> </li> - <li id="NAVcomingEpisodes" ${('', 'class="active"')[topmenu == 'comingEpisodes']}> + <li id="NAVcomingEpisodes"${('', ' class="active"')[topmenu == 'comingEpisodes']}> <a href="${srRoot}/comingEpisodes/">Coming Episodes</a> </li> - <li id="NAVhistory" ${('', 'class="active"')[topmenu == 'history']}> + <li id="NAVhistory"${('', ' class="active"')[topmenu == 'history']}> <a href="${srRoot}/history/">History</a> </li> - <li id="NAVmanage" class="dropdown ${('', 'active')[topmenu == 'manage']}"> - <a href="${srRoot}/manage/" class="dropdown-toggle" data-toggle="dropdown">Manage <b class="caret"></b></a> + <li id="NAVmanage" class="navbar-split dropdown${('', ' active')[topmenu == 'manage']}"> + <a href="${srRoot}/manage/episodeStatuses/" class="dropdown-toggle">Manage</a> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"><b class="caret"></b></a> <ul class="dropdown-menu"> <li><a href="${srRoot}/manage/"><i class="menu-icon-manage"></i> Mass Update</a></li> <li><a href="${srRoot}/manage/backlogOverview/"><i class="menu-icon-backlog-view"></i> Backlog Overview</a></li> @@ -136,18 +163,22 @@ <li><a href="${srRoot}/manage/subtitleMissed/"><i class="menu-icon-backlog"></i> Missed Subtitle Management</a></li> % endif </ul> + <div style="clear:both;"></div> </li> - <li id="NAVerrorlogs" class="dropdown" ${('', 'class="active"')[topmenu == 'errorlogs']}> - <a href="${srRoot}/errorlogs/" class="dropdown-toggle" data-toggle="dropdown">${logPageTitle} <b class="caret"></b></a> + <li id="NAVerrorlogs" class="navbar-split dropdown${('', ' active')[topmenu == 'errorlogs']}"> + <a href="${srRoot}/errorlogs/" class="dropdown-toggle">${logPageTitle}</a> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"><b class="caret"></b></a> <ul class="dropdown-menu"> <li><a href="${srRoot}/errorlogs/"><i class="menu-icon-viewlog-errors"></i> View Log (Errors)</a></li> <li><a href="${srRoot}/errorlogs/viewlog/"><i class="menu-icon-viewlog"></i> View Log</a></li> </ul> + <div style="clear:both;"></div> </li> - <li id="NAVconfig" class="dropdown" ${('', 'class="active"')[topmenu == 'config']}> - <a href="${srRoot}/config/" class="dropdown-toggle" data-toggle="dropdown"><img src="${srRoot}/images/menu/system18.png" class="navbaricon hidden-xs" /><b class="caret hidden-xs"></b><span class="visible-xs">Config <b class="caret"></b></span></a> + <li id="NAVconfig" class="navbar-split dropdown${('', ' active')[topmenu == 'config']}"> + <a href="${srRoot}/config/" class="dropdown-toggle"><span class="visible-xs">Config</span><img src="${srRoot}/images/menu/system18.png" class="navbaricon hidden-xs" /></a> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"><b class="caret"></b></a> <ul class="dropdown-menu"> <li><a href="${srRoot}/config/"><i class="menu-icon-help"></i> Help & Info</a></li> <li><a href="${srRoot}/config/general/"><i class="menu-icon-config"></i> General</a></li> @@ -159,10 +190,12 @@ <li><a href="${srRoot}/config/notifications/"><i class="menu-icon-config"></i> Notifications</a></li> <li><a href="${srRoot}/config/anime/"><i class="menu-icon-config"></i> Anime</a></li> </ul> + <div style="clear:both;"></div> </li> - <li class="dropdown"> - <a href="#" class="dropdown-toggle" data-toggle="dropdown"><img src="${srRoot}/images/menu/system18-2.png" class="navbaricon hidden-xs" /><b class="caret hidden-xs"></b><span class="visible-xs">System <b class="caret"></b></span></a> + <li id="NAVsystem" class="navbar-split dropdown${('', ' active')[topmenu == 'system']}"> + <a href="${srRoot}/home/status/" class="dropdown-toggle"><span class="visible-xs">Tools</span><img src="${srRoot}/images/menu/system18-2.png" class="navbaricon hidden-xs" /></a> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"><b class="caret"></b></a> <ul class="dropdown-menu"> <li><a href="${srRoot}/home/updateCheck?pid=${sbPID}"><i class="menu-icon-update"></i> Check For Updates</a></li> <li><a href="${srRoot}/changes"><i class="menu-icon-help"></i> Changelog</a></li> @@ -171,6 +204,7 @@ <li><a href="${srRoot}/logout" class="confirm logout"><i class="menu-icon-shutdown"></i> Logout</a></li> <li><a href="${srRoot}/home/status/"><i class="menu-icon-help"></i> Server Status</a></li> </ul> + <div style="clear:both;"></div> </li> <li id="donate"><a href="https://github.com/SiCKRAGETV/SickRage/wiki/Donations" rel="noreferrer" onclick="window.open('${sickbeard.ANON_REDIRECT}' + this.href); return false;"><img src="${srRoot}/images/donate.jpg" alt="[donate]" class="navbaricon hidden-xs" /></a></li> </ul> @@ -285,7 +319,7 @@ </div> </div> </footer> - <script type="text/javascript" src="${srRoot}/js/lib/jquery-1.11.2.min.js?${sbPID}"></script> + <script type="text/javascript" src="${srRoot}/js/lib/jquery-2.1.4.min.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/lib/bootstrap.min.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/lib/bootstrap-hover-dropdown.min.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/lib/jquery-ui-1.10.4.custom.min.js?${sbPID}"></script> @@ -303,15 +337,10 @@ <script type="text/javascript" src="${srRoot}/js/lib/isotope.pkgd.min.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/lib/jquery.confirm.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/lib/jquery.timeago.js?${sbPID}"></script> + <script type="text/javascript" src="${srRoot}/js/lib/formwizard.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/new/parsers.js?${sbPID}"></script> + <script type="text/javascript" src="${srRoot}/js/new/meta.js?${sbPID}"></script> <script type="text/javascript" src="${srRoot}/js/script.js?${sbPID}"></script> - <script type="text/javascript"> - srRoot = '${srRoot}'; // needed for browser.js & ajaxNotifications.js - //HTML for scrolltopcontrol, which is auto wrapped in DIV w/ ID="topcontrol" - top_image_html = '<img src="${srRoot}/images/top.gif" width="31" height="11" alt="Jump to top" />'; - themeSpinner = '${('', '-dark')[sickbeard.THEME_NAME == 'dark']}'; - anonURL = '${sickbeard.ANON_REDIRECT}'; - </script> <script type="text/javascript" src="${srRoot}/js/lib/jquery.scrolltopcontrol-1.1.js"></script> <script type="text/javascript" src="${srRoot}/js/browser.js"></script> <script type="text/javascript" src="${srRoot}/js/ajaxNotifications.js"></script> diff --git a/gui/slick/views/manage.mako b/gui/slick/views/manage.mako index 9aab23d0ad7d4e3284e6dbf40701319fdf7f8a04..9f001a3d6bed6859328daf996482a4f8caab6bcf 100644 --- a/gui/slick/views/manage.mako +++ b/gui/slick/views/manage.mako @@ -28,6 +28,7 @@ <th class="col-legend">Scene</th> <th class="col-legend">Anime</th> <th class="col-legend">Flat Folders</th> + <th class="col-legend">Archive first match</th> <th class="col-legend">Paused</th> <th class="col-legend">Subtitle</th> <th class="col-legend">Default Ep<br>Status</th> @@ -47,7 +48,7 @@ <tfoot> <tr> <td rowspan="1" colspan="2" class="align-center alt"><input class="btn pull-left" type="button" value="Edit Selected" id="submitMassEdit" /></td> - <td rowspan="1" colspan="${(14, 15)[bool(sickbeard.USE_SUBTITLES)]}" class="align-right alt"><input class="btn pull-right" type="button" value="Submit" id="submitMassUpdate" /></td> + <td rowspan="1" colspan="${(15, 16)[bool(sickbeard.USE_SUBTITLES)]}" class="align-right alt"><input class="btn pull-right" type="button" value="Submit" id="submitMassUpdate" /></td> </tr> </tfoot> @@ -107,6 +108,7 @@ <td align="center"><img src="${srRoot}/images/${('no16.png" alt="N"', 'yes16.png" alt="Y"')[int(curShow.is_scene) == 1]} width="16" height="16" /></td> <td align="center"><img src="${srRoot}/images/${('no16.png" alt="N"', 'yes16.png" alt="Y"')[int(curShow.is_anime) == 1]} width="16" height="16" /></td> <td align="center"><img src="${srRoot}/images/${('no16.png" alt="N"', 'yes16.png" alt="Y"')[int(curShow.flatten_folders) == 1]} width="16" height="16" /></td> + <td align="center"><img src="${srRoot}/images/${('no16.png" alt="N"', 'yes16.png" alt="Y"')[int(curShow.archive_firstmatch) == 1]} width="16" height="16" /></td> <td align="center"><img src="${srRoot}/images/${('no16.png" alt="N"', 'yes16.png" alt="Y"')[int(curShow.paused) == 1]} width="16" height="16" /></td> <td align="center"><img src="${srRoot}/images/${('no16.png" alt="N"', 'yes16.png" alt="Y"')[int(curShow.subtitles) == 1]} width="16" height="16" /></td> <td align="center">${statusStrings[curShow.default_ep_status]}</td> diff --git a/gui/slick/views/manage_episodeStatuses.mako b/gui/slick/views/manage_episodeStatuses.mako index 1b4ffec630943ef4e413f81a6a9b0cdf8d6d6a90..e26bfdbe841c5fa88c8d1d19bf6a4e09e4229981 100644 --- a/gui/slick/views/manage_episodeStatuses.mako +++ b/gui/slick/views/manage_episodeStatuses.mako @@ -25,8 +25,10 @@ <form action="${srRoot}/manage/episodeStatuses" method="get"> Manage episodes with status <select name="whichStatus" class="form-control form-control-inline input-sm"> -% for curStatus in [common.SKIPPED, common.SNATCHED, common.WANTED, common.IGNORED] + common.Quality.ARCHIVED: -<option value="${curStatus}">${common.statusStrings[curStatus]}</option> +% for curStatus in [common.SKIPPED, common.SNATCHED, common.WANTED, common.IGNORED] + common.Quality.DOWNLOADED + common.Quality.ARCHIVED: + %if surStatus not in [common.ARCHIVED, common.DOWNLOADED]: + <option value="${curStatus}">${common.statusStrings[curStatus]}</option> + %endif % endfor </select> <input class="btn btn-inline" type="submit" value="Manage" /> @@ -42,7 +44,7 @@ Manage episodes with status <select name="whichStatus" class="form-control form- <br /> <% - if int(whichStatus) in [common.IGNORED, common.SNATCHED] + common.Quality.ARCHIVED: + if int(whichStatus) in [common.IGNORED, common.SNATCHED] + common.Quality.DOWNLOADED + common.Quality.ARCHIVED: row_class = "good" else: row_class = common.Overview.overviewStrings[int(whichStatus)] @@ -52,7 +54,10 @@ Manage episodes with status <select name="whichStatus" class="form-control form- Set checked shows/episodes to <select name="newStatus" class="form-control form-control-inline input-sm"> <% - statusList = [common.SKIPPED, common.WANTED, common.IGNORED] + common.Quality.ARCHIVED + statusList = [common.SKIPPED, common.WANTED, common.IGNORED] + common.Quality.DOWNLOADED + common.Quality.ARCHIVED + # Do not allow setting to bare downloaded or archived! + statusList.remove(common.DOWNLOADED) + statusList.remove(common.ARCHIVED) if int(whichStatus) in statusList: statusList.remove(int(whichStatus)) @@ -77,10 +82,11 @@ Set checked shows/episodes to <select name="newStatus" class="form-control form- <table class="sickbeardTable manageTable" cellspacing="1" border="0" cellpadding="0"> % for cur_indexer_id in sorted_show_ids: <tr id="${cur_indexer_id}"> - <th><input type="checkbox" class="allCheck" id="allCheck-${cur_indexer_id}" name="${cur_indexer_id}-all"checked="checked" /></th> + <th><input type="checkbox" class="allCheck" id="allCheck-${cur_indexer_id}" name="${cur_indexer_id}-all" checked="checked" /></th> <th colspan="2" style="width: 100%; text-align: left;"><a class="whitelink" href="${srRoot}/home/displayShow?show=${cur_indexer_id}">${show_names[cur_indexer_id]}</a> (${ep_counts[cur_indexer_id]}) <input type="button" class="pull-right get_more_eps btn" id="${cur_indexer_id}" value="Expand" /></th> </tr> % endfor + <tr><td style="padding:0;"></td><td style="padding:0;"></td><td style="padding:0;"></td></tr> </table> </form> diff --git a/lib/six.py b/lib/six.py index 7ec7f1bec10246b93a3776a16305c3fbc0be28d1..ffa3fe166ad0357732556eee9640c87ba47cf909 100644 --- a/lib/six.py +++ b/lib/six.py @@ -1,6 +1,6 @@ """Utilities for writing code that runs on Python 2 and 3""" -# Copyright (c) 2010-2014 Benjamin Peterson +# Copyright (c) 2010-2015 Benjamin Peterson # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -20,12 +20,16 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import absolute_import + +import functools +import itertools import operator import sys import types __author__ = "Benjamin Peterson <benjamin@python.org>" -__version__ = "1.5.2" +__version__ = "1.9.0" # Useful for very coarse version differentiation. @@ -85,8 +89,12 @@ class _LazyDescr(object): def __get__(self, obj, tp): result = self._resolve() setattr(obj, self.name, result) # Invokes __set__. - # This is a bit ugly, but it avoids running this again. - delattr(obj.__class__, self.name) + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass return result @@ -105,14 +113,6 @@ class MovedModule(_LazyDescr): return _import_module(self.mod) def __getattr__(self, attr): - # Hack around the Django autoreloader. The reloader tries to get - # __file__ or __name__ of every module in sys.modules. This doesn't work - # well if this MovedModule is for an module that is unavailable on this - # machine (like winreg on Unix systems). Thus, we pretend __file__ and - # __name__ don't exist if the module hasn't been loaded yet. See issues - # #51 and #53. - if attr in ("__file__", "__name__") and self.mod not in sys.modules: - raise AttributeError _module = self._resolve() value = getattr(_module, attr) setattr(self, attr, value) @@ -159,9 +159,72 @@ class MovedAttribute(_LazyDescr): return getattr(module, self.attr) +class _SixMetaPathImporter(object): + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + class _MovedItems(_LazyModule): """Lazy loading of moved objects""" + __path__ = [] # mark as package _moved_attributes = [ @@ -169,11 +232,15 @@ _moved_attributes = [ MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), MovedAttribute("map", "itertools", "builtins", "imap", "map"), MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), MovedAttribute("reload_module", "__builtin__", "imp", "reload"), MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), MovedAttribute("UserString", "UserString", "collections"), MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), @@ -183,12 +250,14 @@ _moved_attributes = [ MovedModule("configparser", "ConfigParser"), MovedModule("copyreg", "copy_reg"), MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), MovedModule("http_cookies", "Cookie", "http.cookies"), MovedModule("html_entities", "htmlentitydefs", "html.entities"), MovedModule("html_parser", "HTMLParser", "html.parser"), MovedModule("http_client", "httplib", "http.client"), MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), @@ -222,17 +291,19 @@ _moved_attributes = [ MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), MovedModule("winreg", "_winreg"), ] for attr in _moved_attributes: setattr(_MovedItems, attr.name, attr) if isinstance(attr, MovedModule): - sys.modules[__name__ + ".moves." + attr.name] = attr + _importer._add_module(attr, "moves." + attr.name) del attr _MovedItems._moved_attributes = _moved_attributes -moves = sys.modules[__name__ + ".moves"] = _MovedItems(__name__ + ".moves") +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") class Module_six_moves_urllib_parse(_LazyModule): @@ -241,6 +312,7 @@ class Module_six_moves_urllib_parse(_LazyModule): _urllib_parse_moved_attributes = [ MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), MovedAttribute("parse_qs", "urlparse", "urllib.parse"), MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), MovedAttribute("urldefrag", "urlparse", "urllib.parse"), @@ -254,6 +326,14 @@ _urllib_parse_moved_attributes = [ MovedAttribute("unquote", "urllib", "urllib.parse"), MovedAttribute("unquote_plus", "urllib", "urllib.parse"), MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), ] for attr in _urllib_parse_moved_attributes: setattr(Module_six_moves_urllib_parse, attr.name, attr) @@ -261,7 +341,8 @@ del attr Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes -sys.modules[__name__ + ".moves.urllib_parse"] = sys.modules[__name__ + ".moves.urllib.parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse") +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") class Module_six_moves_urllib_error(_LazyModule): @@ -279,7 +360,8 @@ del attr Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes -sys.modules[__name__ + ".moves.urllib_error"] = sys.modules[__name__ + ".moves.urllib.error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib.error") +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") class Module_six_moves_urllib_request(_LazyModule): @@ -327,7 +409,8 @@ del attr Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes -sys.modules[__name__ + ".moves.urllib_request"] = sys.modules[__name__ + ".moves.urllib.request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib.request") +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") class Module_six_moves_urllib_response(_LazyModule): @@ -346,7 +429,8 @@ del attr Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes -sys.modules[__name__ + ".moves.urllib_response"] = sys.modules[__name__ + ".moves.urllib.response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib.response") +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") class Module_six_moves_urllib_robotparser(_LazyModule): @@ -362,22 +446,24 @@ del attr Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes -sys.modules[__name__ + ".moves.urllib_robotparser"] = sys.modules[__name__ + ".moves.urllib.robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser") +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") class Module_six_moves_urllib(types.ModuleType): """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" - parse = sys.modules[__name__ + ".moves.urllib_parse"] - error = sys.modules[__name__ + ".moves.urllib_error"] - request = sys.modules[__name__ + ".moves.urllib_request"] - response = sys.modules[__name__ + ".moves.urllib_response"] - robotparser = sys.modules[__name__ + ".moves.urllib_robotparser"] + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") def __dir__(self): return ['parse', 'error', 'request', 'response', 'robotparser'] - -sys.modules[__name__ + ".moves.urllib"] = Module_six_moves_urllib(__name__ + ".moves.urllib") +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") def add_move(move): @@ -404,11 +490,6 @@ if PY3: _func_code = "__code__" _func_defaults = "__defaults__" _func_globals = "__globals__" - - _iterkeys = "keys" - _itervalues = "values" - _iteritems = "items" - _iterlists = "lists" else: _meth_func = "im_func" _meth_self = "im_self" @@ -418,11 +499,6 @@ else: _func_defaults = "func_defaults" _func_globals = "func_globals" - _iterkeys = "iterkeys" - _itervalues = "itervalues" - _iteritems = "iteritems" - _iterlists = "iterlists" - try: advance_iterator = next @@ -471,21 +547,49 @@ get_function_defaults = operator.attrgetter(_func_defaults) get_function_globals = operator.attrgetter(_func_globals) -def iterkeys(d, **kw): - """Return an iterator over the keys of a dictionary.""" - return iter(getattr(d, _iterkeys)(**kw)) +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") -def itervalues(d, **kw): - """Return an iterator over the values of a dictionary.""" - return iter(getattr(d, _itervalues)(**kw)) + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return iter(d.iterkeys(**kw)) + + def itervalues(d, **kw): + return iter(d.itervalues(**kw)) + + def iteritems(d, **kw): + return iter(d.iteritems(**kw)) + + def iterlists(d, **kw): + return iter(d.iterlists(**kw)) -def iteritems(d, **kw): - """Return an iterator over the (key, value) pairs of a dictionary.""" - return iter(getattr(d, _iteritems)(**kw)) + viewkeys = operator.methodcaller("viewkeys") -def iterlists(d, **kw): - """Return an iterator over the (key, [values]) pairs of a dictionary.""" - return iter(getattr(d, _iterlists)(**kw)) + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") if PY3: @@ -506,6 +610,9 @@ if PY3: import io StringIO = io.StringIO BytesIO = io.BytesIO + _assertCountEqual = "assertCountEqual" + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" else: def b(s): return s @@ -518,19 +625,35 @@ else: return ord(bs[0]) def indexbytes(buf, i): return ord(buf[i]) - def iterbytes(buf): - return (ord(byte) for byte in buf) + iterbytes = functools.partial(itertools.imap, ord) import StringIO StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" _add_doc(b, """Byte literal""") _add_doc(u, """Text literal""") +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + if PY3: exec_ = getattr(moves.builtins, "exec") def reraise(tp, value, tb=None): + if value is None: + value = tp() if value.__traceback__ is not tb: raise value.with_traceback(tb) raise value @@ -554,6 +677,21 @@ else: """) +if sys.version_info[:2] == (3, 2): + exec_("""def raise_from(value, from_value): + if from_value is None: + raise value + raise value from from_value +""") +elif sys.version_info[:2] > (3, 2): + exec_("""def raise_from(value, from_value): + raise value from from_value +""") +else: + def raise_from(value, from_value): + raise value + + print_ = getattr(moves.builtins, "print", None) if print_ is None: def print_(*args, **kwargs): @@ -608,25 +746,93 @@ if print_ is None: write(sep) write(arg) write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() _add_doc(reraise, """Reraise an exception.""") +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + def wrapper(f): + f = functools.wraps(wrapped, assigned, updated)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps def with_metaclass(meta, *bases): """Create a base class with a metaclass.""" - return meta("NewBase", bases, {}) + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) + def add_metaclass(metaclass): """Class decorator for creating a class with a metaclass.""" def wrapper(cls): orig_vars = cls.__dict__.copy() - orig_vars.pop('__dict__', None) - orig_vars.pop('__weakref__', None) slots = orig_vars.get('__slots__') if slots is not None: if isinstance(slots, str): slots = [slots] for slots_var in slots: orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) return metaclass(cls.__name__, cls.__bases__, orig_vars) return wrapper + + +def python_2_unicode_compatible(klass): + """ + A decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/lib/unrar2/.hgtags b/lib/unrar2/.hgtags deleted file mode 100644 index e94a771c9e406499616777ceb76ac5958c53dedd..0000000000000000000000000000000000000000 --- a/lib/unrar2/.hgtags +++ /dev/null @@ -1,7 +0,0 @@ -f2570b5f7205f1433661a9508f464f691cf63389 0.97 -d3595b2c9a1aec510f8ae1dcfef1eb8562a77fc0 0.99.1 -d23822f936c663784c5edda09cd5a6effe1e882d 0.99.2 -855a137f51581bd6d7a79264856020aa52fd0b66 0.99.3 -160655e623388d65c35ac4c8e271b58566e8a489 0.99.4 -8225eb999c02735d0aead538870c91270d41df0c 0.99.5 -734f8f605597616bc102b60ca1e959d3a0ace5b6 0.99.6 diff --git a/lib/unrar2/rar_exceptions.py b/lib/unrar2/rar_exceptions.py index 4ed3ac237b26aec25e4e29bb3b3d3749d6298536..d90d1c8dbd9b4c465cbd4bb5d457d19b9094c44b 100644 --- a/lib/unrar2/rar_exceptions.py +++ b/lib/unrar2/rar_exceptions.py @@ -28,7 +28,3 @@ class InvalidRARArchive(Exception): pass class FileOpenError(Exception): pass class IncorrectRARPassword(Exception): pass class InvalidRARArchiveUsage(Exception): pass -class FatalRARError(Exception): pass -class CRCRARError(Exception): pass -class NoFileToExtract(Exception): pass -class GenericRARError(Exception): pass diff --git a/lib/unrar2/test_UnRAR2.py b/lib/unrar2/test_UnRAR2.py index b7b8232993edfedce57c275228e07de37d20dbbf..a76f56528f2a83905ef923acaef71dfc7e42e4fe 100644 --- a/lib/unrar2/test_UnRAR2.py +++ b/lib/unrar2/test_UnRAR2.py @@ -1,10 +1,7 @@ -import os,sys,inspect -currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) -parentdir = os.path.dirname(currentdir) -sys.path.insert(0,parentdir) +import os, sys -import unrar2 as UnRAR2 -from unrar2.rar_exceptions import * +import UnRAR2 +from UnRAR2.rar_exceptions import * def cleanup(dir='test'): diff --git a/lib/unrar2/unix.py b/lib/unrar2/unix.py index cb6d79ee0528f7c53872f139d252680d53af42ac..eab79bfe02eaf281c2e26519da9b89a97b37414e 100644 --- a/lib/unrar2/unix.py +++ b/lib/unrar2/unix.py @@ -48,7 +48,7 @@ def call_unrar(params): pass if rar_executable_cached is None: raise UnpackerNotInstalled("No suitable RAR unpacker installed") - + assert type(params) == list, "params must be list" args = [rar_executable_cached] + params try: @@ -62,18 +62,15 @@ class RarFileImplementation(object): def init(self, password=None): global rar_executable_version self.password = password - - proc = self.call('v', []) - stdoutdata, stderrdata = proc.communicate() - - # Use unrar return code if available - self._check_returncode(proc.returncode) + + + stdoutdata, stderrdata = self.call('v', []).communicate() for line in stderrdata.splitlines(): if line.strip().startswith("Cannot open"): raise FileOpenError if line.find("CRC failed")>=0: - raise IncorrectRARPassword + raise IncorrectRARPassword accum = [] source = iter(stdoutdata.splitlines()) line = '' @@ -110,40 +107,36 @@ class RarFileImplementation(object): else: self.comment = None else: - raise UnpackerNotInstalled("Unsupported RAR version, expected 4.x or 5.x, found: " + raise UnpackerNotInstalled("Unsupported RAR version, expected 4.x or 5.x, found: " + signature.split(" ")[1]) - - + + def escaped_password(self): return '-' if self.password == None else self.password - - + + def call(self, cmd, options=[], files=[]): options2 = options + ['p'+self.escaped_password()] soptions = ['-'+x for x in options2] return call_unrar([cmd]+soptions+['--',self.archiveName]+files) def infoiter(self): - + command = "v" if rar_executable_version == 4 else "l" - proc = self.call(command, ['c-']) - stdoutdata, stderrdata = proc.communicate() - - # Use unrar return code if available - self._check_returncode(proc.returncode) - + stdoutdata, stderrdata = self.call(command, ['c-']).communicate() + for line in stderrdata.splitlines(): if line.strip().startswith("Cannot open"): raise FileOpenError - + accum = [] source = iter(stdoutdata.splitlines()) line = '' while not line.startswith('-----------'): if line.strip().endswith('is not RAR archive'): raise InvalidRARArchive - if line.startswith("CRC failed") or line.startswith("Checksum error") or line.startswith("checksum error"): - raise IncorrectRARPassword + if line.startswith("CRC failed") or line.startswith("Checksum error"): + raise IncorrectRARPassword line = source.next() line = source.next() i = 0 @@ -160,7 +153,11 @@ class RarFileImplementation(object): data['size'] = int(fields[0]) attr = fields[5] data['isdir'] = 'd' in attr.lower() - data['datetime'] = time.strptime(fields[3]+" "+fields[4], '%d-%m-%y %H:%M') + try: + data['datetime'] = time.strptime(fields[3]+" "+fields[4], '%d-%m-%y %H:%M') + except ValueError: + data['datetime'] = time.strptime(fields[3]+" "+fields[4], '%y-%m-%d %H:%M') + data['comment'] = None data['volume'] = None yield data @@ -182,7 +179,7 @@ class RarFileImplementation(object): yield data i += 1 line = source.next() - + def read_files(self, checker): res = [] @@ -191,9 +188,9 @@ class RarFileImplementation(object): if checkres==True and not info.isdir: pipe = self.call('p', ['inul'], [info.filename]).stdout res.append((info, pipe.read())) - return res + return res + - def extract(self, checker, path, withSubpath, overwrite): res = [] command = 'x' @@ -217,65 +214,28 @@ class RarFileImplementation(object): names.append(path) proc = self.call(command, options, names) stdoutdata, stderrdata = proc.communicate() - - # Use unrar return code if available - self._check_returncode(proc.returncode) - - if stderrdata.find("CRC failed")>=0 or stderrdata.find("Checksum error")>=0 or stderrdata.find("checksum error")>=0: - raise CRCRARError - if stderrdata.find("No files to extract")>=0: - raise NoFileToExtract - if stderrdata.find("Bad archive")>=0: - raise FatalRARError - + if stderrdata.find("CRC failed")>=0 or stderrdata.find("Checksum error")>=0: + raise IncorrectRARPassword return res - - def _check_returncode(self, returncode): - # RAR exit code from unrarsrc-5.2.1.tar.gz/errhnd.hpp - RARX_SUCCESS = 0 - RARX_WARNING = 1 - RARX_FATAL = 2 - RARX_CRC = 3 - RARX_LOCK = 4 - RARX_WRITE = 5 - RARX_OPEN = 6 - RARX_USERERROR = 7 - RARX_MEMORY = 8 - RARX_CREATE = 9 - RARX_NOFILES = 10 - RARX_BADPWD = 11 - RARX_USERBREAK = 255 - - if returncode != RARX_SUCCESS: - if returncode == RARX_FATAL: - raise FatalRARError - elif returncode == RARX_CRC: - raise CRCRARError - elif returncode == RARX_BADPWD: - raise IncorrectRARPassword - elif returncode == RARX_NOFILES: - raise NoFileToExtract - else: - raise GenericRARError - + def destruct(self): pass - + def get_volume(self): command = "v" if rar_executable_version == 4 else "l" stdoutdata, stderrdata = self.call(command, ['c-']).communicate() - + for line in stderrdata.splitlines(): if line.strip().startswith("Cannot open"): raise FileOpenError - + source = iter(stdoutdata.splitlines()) line = '' while not line.startswith('-----------'): if line.strip().endswith('is not RAR archive'): raise InvalidRARArchive if line.startswith("CRC failed") or line.startswith("Checksum error"): - raise IncorrectRARPassword + raise IncorrectRARPassword line = source.next() line = source.next() if rar_executable_version == 4: @@ -287,7 +247,7 @@ class RarFileImplementation(object): return int(items[5]) - 1 else: return None - + elif rar_executable_version == 5: while not line.startswith('-----------'): line = source.next() @@ -297,5 +257,3 @@ class RarFileImplementation(object): return int(items[2]) - 1 else: return None - - diff --git a/lib/xmltodict.py b/lib/xmltodict.py index 4fdbb16a2ae639cf2ac45648a402e44edef82cb6..746a4bcd7cf5abdc80b19ffdeac3645b463cc83f 100644 --- a/lib/xmltodict.py +++ b/lib/xmltodict.py @@ -29,7 +29,7 @@ except NameError: # pragma no cover _unicode = str __author__ = 'Martin Blech' -__version__ = '0.9.0' +__version__ = '0.9.2' __license__ = 'MIT' @@ -94,7 +94,7 @@ class _DictSAXHandler(object): self.stack.append((self.item, self.data)) if self.xml_attribs: attrs = self.dict_constructor( - (self.attr_prefix+key, value) + (self.attr_prefix+self._build_name(key), value) for (key, value) in attrs.items()) else: attrs = None @@ -256,17 +256,20 @@ def _emit(key, value, content_handler, preprocessor=None, pretty=False, newl='\n', - indent='\t'): + indent='\t', + full_document=True): if preprocessor is not None: result = preprocessor(key, value) if result is None: return key, value = result - if not isinstance(value, (list, tuple)): + if (not hasattr(value, '__iter__') + or isinstance(value, _basestring) + or isinstance(value, dict)): value = [value] - if depth == 0 and len(value) > 1: - raise ValueError('document with multiple roots') - for v in value: + for index, v in enumerate(value): + if full_document and depth == 0 and index > 0: + raise ValueError('document with multiple roots') if v is None: v = OrderedDict() elif not isinstance(v, dict): @@ -318,7 +321,8 @@ def unparse(input_dict, output=None, encoding='utf-8', full_document=True, can be customized with the `newl` and `indent` parameters. """ - ((key, value),) = input_dict.items() + if full_document and len(input_dict) != 1: + raise ValueError('Document must have exactly one root.') must_return = False if output is None: output = StringIO() @@ -326,7 +330,9 @@ def unparse(input_dict, output=None, encoding='utf-8', full_document=True, content_handler = XMLGenerator(output, encoding) if full_document: content_handler.startDocument() - _emit(key, value, content_handler, **kwargs) + for key, value in input_dict.items(): + _emit(key, value, content_handler, full_document=full_document, + **kwargs) if full_document: content_handler.endDocument() if must_return: diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 52ac11ecfc209ad6431e5b6c526c6816c125f0a4..6121d816b242f36d92ccacab968bf3a876a4e644 100644 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -726,6 +726,7 @@ def initialize(consoleLogging=True): if os.path.exists(os.path.join(DATA_DIR, 'restore')): try: shutil.rmtree(os.path.join(DATA_DIR, 'restore')) + shutil.rmtree(os.path.join(CACHE_DIR, 'mako')) except Exception as e: logger.log(u"Restore: Unable to remove the restore directory: {0}".format(str(e)), logger.ERROR) diff --git a/sickbeard/common.py b/sickbeard/common.py index 74f1616f8334b32ce1599c427bf370aedfa5edf8..f7214d28d32f62f6c3887f268bf2e8c585511b5a 100644 --- a/sickbeard/common.py +++ b/sickbeard/common.py @@ -265,10 +265,10 @@ class Quality: return ret - if checkName([r"(pdtv|hd.?tv|dsr|tvrip).(xvid|x26[45]|h.?26[45])"], all) and not checkName([r"(720|1080)[pi]"], all) and\ + if checkName([r"(pdtv|hd.?tv|dsr|tv(rip|mux)).(xvid|x26[45]|h.?26[45])"], all) and not checkName([r"(720|1080)[pi]"], all) and\ not checkName([r"hr.ws.pdtv.x26[45]"], any): ret = Quality.SDTV - elif checkName([r"web.?dl|webrip", r"xvid|x26[45]|h.?26[45]"], all) and not checkName([r"(720|1080)[pi]"], all): + elif checkName([r"web.?dl|web(rip|mux)", r"xvid|x26[45]|h.?26[45]"], all) and not checkName([r"(720|1080)[pi]"], all): ret = Quality.SDTV elif checkName([r"(dvd(rip|mux)|b[rd](rip|mux)|blue?-?ray)(.ws)?.(xvid|divx|x26[45])"], any) and not checkName([r"(720|1080)[pi]"], all): ret = Quality.SDDVD @@ -279,13 +279,13 @@ class Quality: ret = Quality.RAWHDTV elif checkName([r"1080p", r"hd.?tv", r"x26[45]"], all): ret = Quality.FULLHDTV - elif checkName([r"720p", r"web.?dl|webrip"], all) or checkName([r"720p", r"itunes", r"h.?26[45]"], all): + elif checkName([r"720p", r"web.?dl|web(rip|mux)"], all) or checkName([r"720p", r"itunes", r"h.?26[45]"], all): ret = Quality.HDWEBDL - elif checkName([r"1080p", r"web.?dl|webrip"], all) or checkName([r"1080p", r"itunes", r"h.?26[45]"], all): + elif checkName([r"1080p", r"web.?dl|web(rip|mux)"], all) or checkName([r"1080p", r"itunes", r"h.?26[45]"], all): ret = Quality.FULLHDWEBDL - elif checkName([r"720p", r"blue?-?ray|hddvd|b[rd]rip", r"x26[45]"], all): + elif checkName([r"720p", r"blue?-?ray|hddvd|b[rd](rip|mux)", r"x26[45]"], all): ret = Quality.HDBLURAY - elif checkName([r"1080p", r"blue?-?ray|hddvd|b[rd]rip", r"x26[45]"], all): + elif checkName([r"1080p", r"blue?-?ray|hddvd|b[rd](rip|mux)", r"x26[45]"], all): ret = Quality.FULLHDBLURAY return ret @@ -422,15 +422,12 @@ Quality.FAILED = [Quality.compositeStatus(FAILED, x) for x in Quality.qualityStr Quality.SNATCHED_BEST = [Quality.compositeStatus(SNATCHED_BEST, x) for x in Quality.qualityStrings.keys()] Quality.ARCHIVED = [Quality.compositeStatus(ARCHIVED, x) for x in Quality.qualityStrings.keys()] -SD = Quality.combineQualities([Quality.SDTV, Quality.SDDVD], []) -HD = Quality.combineQualities( - [Quality.HDTV, Quality.FULLHDTV, Quality.HDWEBDL, Quality.FULLHDWEBDL, Quality.HDBLURAY, Quality.FULLHDBLURAY], - []) # HD720p + HD1080p HD720p = Quality.combineQualities([Quality.HDTV, Quality.HDWEBDL, Quality.HDBLURAY], []) HD1080p = Quality.combineQualities([Quality.FULLHDTV, Quality.FULLHDWEBDL, Quality.FULLHDBLURAY], []) -ANY = Quality.combineQualities( - [Quality.SDTV, Quality.SDDVD, Quality.HDTV, Quality.FULLHDTV, Quality.HDWEBDL, Quality.FULLHDWEBDL, - Quality.HDBLURAY, Quality.FULLHDBLURAY, Quality.UNKNOWN], []) # SD + HD + +SD = Quality.combineQualities([Quality.SDTV, Quality.SDDVD], []) +HD = Quality.combineQualities([HD720p, HD1080p], []) +ANY = Quality.combineQualities([SD, HD], []) # legacy template, cant remove due to reference in mainDB upgrade? BEST = Quality.combineQualities([Quality.SDTV, Quality.HDTV, Quality.HDWEBDL], [Quality.HDTV]) diff --git a/sickbeard/databases/mainDB.py b/sickbeard/databases/mainDB.py index cbe45a0bf599a6a09589e251debd60a2d767ce7d..d405d30ce625d82498c5523b0e6eee0865d58656 100644 --- a/sickbeard/databases/mainDB.py +++ b/sickbeard/databases/mainDB.py @@ -46,9 +46,35 @@ class MainSanityCheck(db.DBSanityCheck): self.fix_subtitles_codes() self.fix_show_nfo_lang() self.convert_tvrage_to_tvdb() + self.convert_archived_to_compund() + + + def convert_archived_to_compund(self): + logger.log(u'Checking for archived episodes not qualified', logger.DEBUG) + + query = "SELECT episode_id, showid, status, location, season, episode " + \ + "FROM tv_episodes WHERE status = %s" % common.ARCHIVED + + sqlResults = self.connection.select(query) + if sqlResults: + logger.log(u"Found %i shows with bare archived status, attempting automatic conversion..." % len(sqlResults), logger.WARNING) + + for archivedEp in sqlResults: + fixedStatus = common.Quality.compositeStatus(common.ARCHIVED, common.Quality.UNKNOWN) + existing = archivedEp['location'] and ek(os.path.exists, archivedEp['location']) + if existing: + quality = common.Quality.assumeQuality(archivedEp['location']) + fixedStatus = common.Quality.compositeStatus(common.ARCHIVED, quality) + + logger.log(u'Changing status from %s to %s for %s: S%02dE%02d at %s (File %s)' % + (common.statusStrings[common.ARCHIVED], common.statusStrings[fixedStatus], + archivedEp['showid'], archivedEp['season'], archivedEp['episode'], + archivedEp['location'] if archivedEp['location'] else 'unknown location', ('NOT FOUND', 'EXISTS')[bool(existing)])) + + self.connection.action("UPDATE tv_episodes SET status = %i WHERE episode_id = %i" % (fixedStatus, archivedEp['episode_id'])) def convert_tvrage_to_tvdb(self): - logger.log(u"Checking for shows with tvrage id's, since tvrage is gone") + logger.log(u"Checking for shows with tvrage id's, since tvrage is gone", logger.DEBUG) from sickbeard.indexers.indexer_config import INDEXER_TVRAGE from sickbeard.indexers.indexer_config import INDEXER_TVDB diff --git a/sickbeard/helpers.py b/sickbeard/helpers.py index 8e1738be846f2933440235f64fbaae4ad91546b2..b60ddf5486bcfa39629119a3b91ca106eba219b8 100644 --- a/sickbeard/helpers.py +++ b/sickbeard/helpers.py @@ -221,7 +221,7 @@ def isSyncFile(filename): extension = filename.rpartition(".")[2].lower() #if extension == '!sync' or extension == 'lftp-pget-status' or extension == 'part' or extension == 'bts': syncfiles = sickbeard.SYNC_FILES - if extension in syncfiles.split(","): + if extension in syncfiles.split(",") or filename.startswith('.syncthing'): return True else: return False diff --git a/sickbeard/providers/extratorrent.py b/sickbeard/providers/extratorrent.py index 2149c20cc9814ef0c8ad00e2145e0825188bb5a7..c06a334bc48ddd2504e90cf83792633c740f4f49 100644 --- a/sickbeard/providers/extratorrent.py +++ b/sickbeard/providers/extratorrent.py @@ -31,6 +31,7 @@ from sickbeard import classes from sickbeard import helpers from sickbeard import show_name_helpers from sickbeard.helpers import sanitizeSceneName +from sickbeard.common import USER_AGENT class ExtraTorrentProvider(generic.TorrentProvider): @@ -52,7 +53,7 @@ class ExtraTorrentProvider(generic.TorrentProvider): self.minleech = None self.cache = ExtraTorrentCache(self) - + self.headers.update({'User-Agent': USER_AGENT}) self.search_params = {'cid': 8} def isEnabled(self): @@ -130,23 +131,35 @@ class ExtraTorrentProvider(generic.TorrentProvider): for item in entries: title = item['title'] info_hash = item['info_hash'] - url = item['enclosure']['@url'] - size = int(item['enclosure']['@length'] or item['size']) + size = int(item['size']) seeders = helpers.tryInt(item['seeders'],0) leechers = helpers.tryInt(item['leechers'],0) + url = item['enclosure']['@url'] if 'enclosure' in item else self._magnet_from_details(item['link']) - if not seeders or seeders < self.minseed or leechers < self.minleech: + if not all([title, url, seeders, seeders >= self.minseed, leechers >= self.minleech, size]): continue items[mode].append((title, url, seeders, leechers, size, info_hash)) - except Exception: + except (AttributeError, TypeError, KeyError, ValueError): logger.log(u"Failed parsing " + self.name + " Traceback: " + traceback.format_exc(), logger.ERROR) results += items[mode] return results + + def _magnet_from_details(self, link): + details = self.getURL(link) + if not details: + return '' + + match = re.search(r'href="(magnet.*?)"', details) + if not match: + return '' + + return match.group(1) + def _get_title_and_url(self, item): #pylint: disable=W0612 title, url, seeders, leechers, size, info_hash = item @@ -157,6 +170,7 @@ class ExtraTorrentProvider(generic.TorrentProvider): if url: url = url.replace('&', '&') + return (title, url) diff --git a/sickbeard/providers/tntvillage.py b/sickbeard/providers/tntvillage.py index ebaf4ef2ed335b7170958cf9968551c056c1145f..ffdb9f84bac8241f55b6097ea1e41d46807dd4e5 100644 --- a/sickbeard/providers/tntvillage.py +++ b/sickbeard/providers/tntvillage.py @@ -404,7 +404,7 @@ class TNTVillageProvider(generic.TorrentProvider): continue if mode != 'RSS' and (seeders < self.minseed or leechers < self.minleech): - logger.log(u"Discarding torrent because it doesn't meet the minimum seeders or leechers: {0} (S:{1} L:{2})".format(name, seeders, leechers), logger.DEBUG) + logger.log(u"Discarding torrent because it doesn't meet the minimum seeders or leechers: {0} (S:{1} L:{2})".format(title, seeders, leechers), logger.DEBUG) continue if not title or not download_url: diff --git a/sickbeard/providers/torrentbytes.py b/sickbeard/providers/torrentbytes.py index c0fac96dd69bb46e6124e84a94e52898308930f7..3170ed9ea7f28300b43de40fd6525460c85a4763 100644 --- a/sickbeard/providers/torrentbytes.py +++ b/sickbeard/providers/torrentbytes.py @@ -195,7 +195,7 @@ class TorrentBytesProvider(generic.TorrentProvider): #Filter unseeded torrent if mode != 'RSS' and (seeders < self.minseed or leechers < self.minleech): - logger.log(u"Discarding torrent because it doesn't meet the minimum seeders or leechers: {0} (S:{1} L:{2})".format(name, seeders, leechers), logger.DEBUG) + logger.log(u"Discarding torrent because it doesn't meet the minimum seeders or leechers: {0} (S:{1} L:{2})".format(title, seeders, leechers), logger.DEBUG) continue if not title or not download_url: diff --git a/sickbeard/providers/torrentleech.py b/sickbeard/providers/torrentleech.py index 2446e18499dfd6fb14d8dd1c393f74c42f71695b..777a7470b7e35c31edfef51a62f35dfcec441a6c 100644 --- a/sickbeard/providers/torrentleech.py +++ b/sickbeard/providers/torrentleech.py @@ -194,7 +194,7 @@ class TorrentLeechProvider(generic.TorrentProvider): #Filter unseeded torrent if mode != 'RSS' and (seeders < self.minseed or leechers < self.minleech): - logger.log(u"Discarding torrent because it doesn't meet the minimum seeders or leechers: {0} (S:{1} L:{2})".format(name, seeders, leechers), logger.DEBUG) + logger.log(u"Discarding torrent because it doesn't meet the minimum seeders or leechers: {0} (S:{1} L:{2})".format(title, seeders, leechers), logger.DEBUG) continue if not title or not download_url: diff --git a/sickbeard/providers/transmitthenet.py b/sickbeard/providers/transmitthenet.py index e1deb3fee7c67a2bdb126fee2ab7a0434702a6ba..0779e5207ab8a297f071406d423df71ad4690c7b 100644 --- a/sickbeard/providers/transmitthenet.py +++ b/sickbeard/providers/transmitthenet.py @@ -34,12 +34,13 @@ from urllib import urlencode class TransmitTheNetProvider(generic.TorrentProvider): def __init__(self): + generic.TorrentProvider.__init__(self, "TransmitTheNet") self.urls = { 'base_url': 'https://transmithe.net/', 'index': 'https://transmithe.net/index.php', - } + } self.url = self.urls['base_url'] @@ -55,7 +56,9 @@ class TransmitTheNetProvider(generic.TorrentProvider): self.cache = TransmitTheNetCache(self) self.search_params = { - 'page': 'torrents', "category": 1, "active": 1 + "page": 'torrents', + "category": 0, + "active": 1 } def isEnabled(self): @@ -70,6 +73,7 @@ class TransmitTheNetProvider(generic.TorrentProvider): return quality def _checkAuth(self): + if not self.username or not self.password: raise AuthException("Your authentication credentials for " + self.name + " are missing, check your config.") @@ -78,11 +82,11 @@ class TransmitTheNetProvider(generic.TorrentProvider): def _doLogin(self): login_params = { - 'uid': self.username, - 'pwd': self.password, - 'remember_me': 'on', - 'login': 'submit' - } + 'uid': self.username, + 'pwd': self.password, + 'remember_me': 'on', + 'login': 'submit' + } response = self.getURL(self.urls['index'], params={'page': 'login'}, post_data=login_params, timeout=30) if not response: @@ -106,7 +110,7 @@ class TransmitTheNetProvider(generic.TorrentProvider): elif ep_obj.show.anime: ep_string = show_name + ' ' + "%d" % ep_obj.scene_absolute_number else: - ep_string = show_name + ' S%02d' % int(ep_obj.scene_season) #1) showName SXX + ep_string = show_name + ' S%02d' % int(ep_obj.scene_season) # 1) showName SXX search_string['Season'].append(ep_string.strip()) @@ -141,7 +145,7 @@ class TransmitTheNetProvider(generic.TorrentProvider): sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.scene_season, 'episodenumber': ep_obj.scene_episode} + ' %s' % add_string - search_string['Episode'].append(re.sub('\s+', ' ', ep_string)) + search_string['Episode'].append(re.sub('\s+', ' ', ep_string.replace('.', ' ').strip())) return [search_string] @@ -156,17 +160,17 @@ class TransmitTheNetProvider(generic.TorrentProvider): for mode in search_strings.keys(): for search_string in search_strings[mode]: - self.search_params['search'] = search_string.strip() + self.search_params['search'] = search_string logger.log(u"Search string: " + self.search_params['search'] + " for " + self.name, logger.DEBUG) data = self.getURL(self.urls['index'], params=self.search_params) url_searched = self.urls['index'] + "?" + urlencode(self.search_params) if not data: - logger.log(u"The response from (" + url_searched + ") is empty.",logger.DEBUG) + logger.log(u"The response from (" + url_searched + ") is empty.", logger.DEBUG) continue - logger.log(u"Search query from (" + url_searched + ") returned data.",logger.DEBUG) + logger.log(u"Search query from (" + url_searched + ") returned data.", logger.DEBUG) try: with BS4Parser(data) as html: @@ -180,22 +184,25 @@ class TransmitTheNetProvider(generic.TorrentProvider): if torr_row: torrent_rows.append(torr_row) - #Continue only if one Release is found + # Continue only if one Release is found if len(torrent_rows) < 1: - logger.log(u"The Data returned from " + self.name + " did not contain any torrent", logger.DEBUG) - continue + logger.log(u"The Data returned from " + self.name + " did not contain any torrent", + logger.DEBUG) + continue for torrent_row in torrent_rows: - title = torrent_row.find('a',{"data-src": True})['data-src'].rsplit('.', 1)[0] + title = torrent_row.find('a', {"data-src": True})['data-src'].rsplit('.', 1)[0] download_href = torrent_row.find('img', {"alt": 'Download Torrent'}).findParent()['href'] - id = torrent_row.find('a',{"data-src": True})['href'].split("&id=", 1)[1] + id = torrent_row.find('a', {"data-src": True})['href'].split("&id=", 1)[1] seeders = int(torrent_row.findAll('a', {'title': 'Click here to view peers details'})[0].text.strip()) leechers = int(torrent_row.findAll('a', {'title': 'Click here to view peers details'})[1].text.strip()) - #Filter unseeded torrent + # Filter unseeded torrent if seeders < self.minseed: - logger.log(u"Discarding torrent because it doesn't meet the minimum seeders: {0} (S:{1})".format(name, seeders), logger.DEBUG) + logger.log( + u"Discarding torrent because it doesn't meet the minimum seeders: {0} (S:{1})".format( + title, seeders), logger.DEBUG) continue if not title or not download_href: @@ -204,14 +211,15 @@ class TransmitTheNetProvider(generic.TorrentProvider): download_url = self.urls['base_url'] + download_href item = title, download_url, id, seeders, leechers - logger.log(u"Found result: " + title.replace(' ','.') + " (" + download_url + ")", logger.DEBUG) + logger.log(u"Found result: " + title.replace(' ', '.') + " (" + download_url + ")", + logger.DEBUG) items[mode].append(item) except: logger.log(u"Failed parsing " + self.name + " Traceback: " + traceback.format_exc(), logger.ERROR) - #For each search mode sort all the items by seeders + # For each search mode sort all the items by seeders items[mode].sort(key=lambda tup: tup[3], reverse=True) results += items[mode] @@ -262,10 +270,9 @@ class TransmitTheNetProvider(generic.TorrentProvider): class TransmitTheNetCache(tvcache.TVCache): def __init__(self, provider): - tvcache.TVCache.__init__(self, provider) - # only poll TorrentBytes every 20 minutes max + # Only poll TransmitTheNet every 20 minutes max self.minTime = 20 def _getRSSData(self): @@ -273,4 +280,4 @@ class TransmitTheNetCache(tvcache.TVCache): return {'entries': self.provider._doSearch(search_strings)} -provider = TransmitTheNetProvider() \ No newline at end of file +provider = TransmitTheNetProvider() diff --git a/sickbeard/providers/tvchaosuk.py b/sickbeard/providers/tvchaosuk.py index 6c14551887e7026d450fc49f07aaeb8d570060be..d0fa2cb2a514b73b7190383ee5fc88cee1224aeb 100644 --- a/sickbeard/providers/tvchaosuk.py +++ b/sickbeard/providers/tvchaosuk.py @@ -171,7 +171,7 @@ class TVChaosUKProvider(generic.TorrentProvider): #Filter unseeded torrent if not seeders or seeders < self.minseed or leechers < self.minleech: - logger.log(u"Discarding torrent because it doesn't meet the minimum seeders or leechers: {0} (S:{1} L:{2})".format(name, seeders, leechers), logger.DEBUG) + logger.log(u"Discarding torrent because it doesn't meet the minimum seeders or leechers: {0} (S:{1} L:{2})".format(title, seeders, leechers), logger.DEBUG) continue if not title or not url: diff --git a/sickbeard/show_queue.py b/sickbeard/show_queue.py index 3f47a55b617af14444efe58b50f393ed6d255fa5..755ab871d09fdeaa339f7208073046fd215a5ab8 100644 --- a/sickbeard/show_queue.py +++ b/sickbeard/show_queue.py @@ -496,8 +496,8 @@ class QueueItemRefresh(ShowQueueItem): self.show.refreshDir() self.show.writeMetadata() - #if self.force: - # self.show.updateMetadata() + if self.force: + self.show.updateMetadata() self.show.populateCache() # Load XEM data to DB for show diff --git a/sickbeard/subtitles.py b/sickbeard/subtitles.py index 42dfddb4b60dd11bd4d8966fff7426eee4ecba8d..57a6edec1d1f36d5d15f5bc37621ccc7f742ad8c 100644 --- a/sickbeard/subtitles.py +++ b/sickbeard/subtitles.py @@ -24,7 +24,7 @@ from sickbeard import db from sickrage.helper.common import dateTimeFormat from sickrage.helper.encoding import ek from sickrage.helper.exceptions import ex -from enzyme import MKV +from enzyme import MKV, MalformedMKVError from babelfish import Error as BabelfishError, Language, language_converters import subliminal import subprocess @@ -98,8 +98,9 @@ def subtitlesLanguages(video_path): # Serch for embedded subtitles if not sickbeard.EMBEDDED_SUBTITLES_ALL: if video_path.endswith('mkv'): - with open(video_path, 'rb') as f: - mkv = MKV(f) + try: + with open(video_path.encode(sickbeard.SYS_ENCODING), 'rb') as f: + mkv = MKV(f) if mkv.subtitle_tracks: for st in mkv.subtitle_tracks: if st.language: @@ -118,6 +119,8 @@ def subtitlesLanguages(video_path): embedded_subtitle_languages.add(Language('und')) else: logger.log('MKV has no subtitle track', logger.DEBUG) + except MalformedMKVError: + logger.log('MKV seems to be malformed, ignoring embedded subtitles', logger.WARNING) # Search subtitles in the absolute path if sickbeard.SUBTITLES_DIR and ek(os.path.exists, sickbeard.SUBTITLES_DIR): diff --git a/sickbeard/tv.py b/sickbeard/tv.py index 2b96aa233aa310e30010cb8c1780c6cb0082d54a..0a48d4d52350b61ae113461735140e354bd48c3e 100644 --- a/sickbeard/tv.py +++ b/sickbeard/tv.py @@ -1100,9 +1100,16 @@ class TVShow(object): with curEp.lock: # if it used to have a file associated with it and it doesn't anymore then set it to sickbeard.EP_DEFAULT_DELETED_STATUS if curEp.location and curEp.status in Quality.DOWNLOADED: + + if sickbeard.EP_DEFAULT_DELETED_STATUS == ARCHIVED: + oldStatus, oldQuality = Quality.splitCompositeStatus(curEp.status) + new_status = Quality.compositeStatus(ARCHIVED, oldQuality) + else: + new_status = sickbeard.EP_DEFAULT_DELETED_STATUS + logger.log(u"%s: Location for S%02dE%02d doesn't exist, removing it and changing our status to %s" % - (self.indexerid, season, episode, statusStrings[sickbeard.EP_DEFAULT_DELETED_STATUS]) ,logger.DEBUG) - curEp.status = sickbeard.EP_DEFAULT_DELETED_STATUS + (self.indexerid, season, episode, statusStrings[new_status]) ,logger.DEBUG) + curEp.status = new_status curEp.subtitles = list() curEp.subtitles_searchcount = 0 curEp.subtitles_lastsearch = str(datetime.datetime.min) @@ -1478,7 +1485,7 @@ class TVEpisode(object): video = None try: # Never look for subtitles in the same path, as we specify the path later on - video = subliminal.scan_video(vname, subtitles=False, embedded_subtitles=False) + video = subliminal.scan_video(vname.encode(sickbeard.SYS_ENCODING), subtitles=False, embedded_subtitles=False) except Exception: logger.log(u'%s: Exception caught in subliminal.scan_video for S%02dE%02d' % (self.show.indexerid, self.season, self.episode), logger.DEBUG) diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 1963e0b8e7ac4a9104c76255eb25c9975ada9932..aa274ccc9decab08de46a72f88ffd5f2e19eed50 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -641,21 +641,9 @@ class Home(WebRoot): def __init__(self, *args, **kwargs): super(Home, self).__init__(*args, **kwargs) - def HomeMenu(self): - menu = [ - {'title': 'Add Shows', 'path': 'home/addShows/', 'icon': 'ui-icon ui-icon-video'}, - {'title': 'Manual Post-Processing', 'path': 'home/postprocess/', 'icon': 'ui-icon ui-icon-folder-open'}, - {'title': 'Update KODI', 'path': 'home/updateKODI/', 'requires': self.haveKODI(), 'icon': 'submenu-icon-kodi'}, - {'title': 'Update Plex', 'path': 'home/updatePLEX/', 'requires': self.havePLEX(), 'icon': 'ui-icon ui-icon-refresh'}, - {'title': 'Update Emby', 'path': 'home/updateEMBY/', 'requires': self.haveEMBY(), 'icon': 'ui-icon ui-icon-refresh'}, - {'title': 'Manage Torrents', 'path': 'manage/manageTorrents/', 'requires': self.haveTORRENT(), 'icon': 'submenu-icon-bittorrent'}, - ] - - return menu - def _genericMessage(self, subject, message): t = PageTemplate(rh=self, file="genericMessage.mako") - return t.render(message=message, subject=subject, submenu=self.HomeMenu(), topmenu="home", title="") + return t.render(message=message, subject=subject, topmenu="home", title="") def _getEpisode(self, show, season=None, episode=None, absolute=None): if show is None: @@ -692,7 +680,7 @@ class Home(WebRoot): else: showlists = [["Shows", sickbeard.showList]] - return t.render(title="Home", header="Show List", topmenu="home", showlists=showlists, submenu=self.HomeMenu()) + return t.render(title="Home", header="Show List", topmenu="home", showlists=showlists) def is_alive(self, *args, **kwargs): if 'callback' in kwargs and '_' in kwargs: @@ -1067,7 +1055,7 @@ class Home(WebRoot): rootDir[subject] = helpers.getDiskSpaceUsage(subject) t = PageTemplate(rh=self, file="status.mako") - return t.render(title='Status', header='Status', topmenu='system', submenu=self.HomeMenu(), tvdirFree=tvdirFree, rootDir=rootDir) + return t.render(title='Status', header='Status', topmenu='system', tvdirFree=tvdirFree, rootDir=rootDir) def shutdown(self, pid=None): if not Shutdown.stop(pid): @@ -1084,7 +1072,7 @@ class Home(WebRoot): t = PageTemplate(rh=self, file="restart.mako") - return t.render(title="Home", header="Restarting SickRage", topmenu="system", submenu=self.HomeMenu()) + return t.render(title="Home", header="Restarting SickRage", topmenu="system") def updateCheck(self, pid=None): if str(pid) != str(sickbeard.PID): @@ -1109,7 +1097,7 @@ class Home(WebRoot): sickbeard.events.put(sickbeard.events.SystemEvent.RESTART) t = PageTemplate(rh=self, file="restart.mako") - return t.render(title="Home", header="Restarting SickRage", topmenu="home", submenu=self.HomeMenu()) + return t.render(title="Home", header="Restarting SickRage", topmenu="home") else: return self._genericMessage("Update Failed", "Update wasn't successful, not restarting. Check your log for more information.") @@ -1334,11 +1322,10 @@ class Home(WebRoot): scene_exceptions = sickbeard.scene_exceptions.get_scene_exceptions(showObj.indexerid) if showObj.is_anime: - return t.render(submenu=self.HomeMenu(), show=show, scene_exceptions=scene_exceptions, groups=groups, whitelist=whitelist, + return t.render(show=show, scene_exceptions=scene_exceptions, groups=groups, whitelist=whitelist, blacklist=blacklist, title='Edit Shows', header='Edit Shows') else: - return t.render(submenu=self.HomeMenu(), show=show, scene_exceptions=scene_exceptions, title='Edit Shows', - header='Edit Shows') + return t.render(show=show, scene_exceptions=scene_exceptions, title='Edit Shows', header='Edit Shows') flatten_folders = config.checkbox_to_value(flatten_folders) dvdorder = config.checkbox_to_value(dvdorder) @@ -2093,7 +2080,7 @@ class HomeIRC(Home): def index(self): t = PageTemplate(rh=self, file="IRC.mako") - return t.render(topmenu="irc", header="IRC", title="IRC", submenu=self.HomeMenu()) + return t.render(topmenu="irc", header="IRC", title="IRC") @route('/news(/?.*)') class HomeNews(Home): @@ -2110,7 +2097,7 @@ class HomeNews(Home): t = PageTemplate(rh=self, file="markdown.mako") data = markdown2.markdown(news if news else "The was a problem connecting to github, please refresh and try again", extras=['header-ids']) - return t.render(title="News", header="News", topmenu="news", data=data, submenu=self.HomeMenu()) + return t.render(title="News", header="News", topmenu="news", data=data) @route('/changes(/?.*)') @@ -2128,7 +2115,7 @@ class HomeChangeLog(Home): t = PageTemplate(rh=self, file="markdown.mako") data = markdown2.markdown(changes if changes else "The was a problem connecting to github, please refresh and try again", extras=['header-ids']) - return t.render(title="Changelog", header="Changelog", topmenu="system", data=data, submenu=self.HomeMenu()) + return t.render(title="Changelog", header="Changelog", topmenu="system", data=data) @route('/home/postprocess(/?.*)') @@ -2138,7 +2125,7 @@ class HomePostProcess(Home): def index(self): t = PageTemplate(rh=self, file="home_postprocess.mako") - return t.render(submenu=self.HomeMenu(), title='Post Processing', header='Post Processing') + return t.render(title='Post Processing', header='Post Processing', topmenu='home') def processEpisode(self, dir=None, nzbName=None, jobName=None, quiet=None, process_method=None, force=None, is_priority=None, delete_on="0", failed="0", type="auto", *args, **kwargs): @@ -2182,7 +2169,7 @@ class HomeAddShows(Home): def index(self): t = PageTemplate(rh=self, file="home_addShows.mako") - return t.render(submenu=self.HomeMenu(), title='Add Shows', header='Add Shows') + return t.render(title='Add Shows', header='Add Shows', topmenu='home') def getIndexerLanguages(self): result = sickbeard.indexerApi().config['valid_languages'] @@ -2306,7 +2293,7 @@ class HomeAddShows(Home): cur_dir['added_already'] = True - return t.render(submenu=self.HomeMenu(), dirList=dir_list) + return t.render(dirList=dir_list) def newShow(self, show_to_add=None, other_shows=None, search_string=None): @@ -2347,11 +2334,11 @@ class HomeAddShows(Home): provided_indexer = int(indexer or sickbeard.INDEXER_DEFAULT) - return t.render(submenu=self.HomeMenu(), enable_anime_options=True, + return t.render(enable_anime_options=True, use_provided_info=use_provided_info, default_show_name=default_show_name, other_shows=other_shows, provided_show_dir=show_dir, provided_indexer_id=provided_indexer_id, provided_indexer_name=provided_indexer_name, provided_indexer=provided_indexer, indexers=sickbeard.indexerApi().indexers, whitelist=[], blacklist=[], groups=[], - title='New Show', header='New Show' + title='New Show', header='New Show', topmenu='home' ) def recommendedShows(self): @@ -2360,7 +2347,7 @@ class HomeAddShows(Home): posts them to addNewShow """ t = PageTemplate(rh=self, file="home_recommendedShows.mako") - return t.render(title="Recommended Shows", header="Recommended Shows", submenu=self.HomeMenu(), enable_anime_options=False) + return t.render(title="Recommended Shows", header="Recommended Shows", enable_anime_options=False) def getRecommendedShows(self): t = PageTemplate(rh=self, file="trendingShows.mako") @@ -2403,7 +2390,7 @@ class HomeAddShows(Home): except traktException as e: logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) - return t.render(title="Trending Shows", header="Trending Shows", trending_shows=trending_shows, blacklist=blacklist, submenu=self.HomeMenu()) + return t.render(title="Trending Shows", header="Trending Shows", trending_shows=trending_shows, blacklist=blacklist) def trendingShows(self): """ @@ -2411,7 +2398,7 @@ class HomeAddShows(Home): posts them to addNewShow """ t = PageTemplate(rh=self, file="home_trendingShows.mako") - return t.render(title="Trending Shows", header="Trending Shows", submenu=self.HomeMenu(), enable_anime_options=False) + return t.render(title="Trending Shows", header="Trending Shows", enable_anime_options=False) def getTrendingShows(self): """ @@ -2457,7 +2444,7 @@ class HomeAddShows(Home): except traktException as e: logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) - return t.render(submenu = self.HomeMenu(), blacklist=blacklist, trending_shows=trending_shows) + return t.render(blacklist=blacklist, trending_shows=trending_shows) def popularShows(self): @@ -2472,7 +2459,7 @@ class HomeAddShows(Home): except Exception as e: popular_shows = None - return t.render(title="Popular Shows", header="Popular Shows", submenu = self.HomeMenu(), popular_shows=popular_shows, imdb_exception=e) + return t.render(title="Popular Shows", header="Popular Shows", popular_shows=popular_shows, imdb_exception=e, topmenu="home") def addShowToBlacklist(self, indexer_id): @@ -2499,7 +2486,7 @@ class HomeAddShows(Home): Prints out the page to add existing shows from a root dir """ t = PageTemplate(rh=self, file="home_addExistingShow.mako") - return t.render(submenu=self.HomeMenu(), enable_anime_options=False, title='Existing Show', header='Existing Show', topmenu="home") + return t.render(enable_anime_options=False, title='Existing Show', header='Existing Show', topmenu="home") def addTraktShow(self, indexer_id, showName): if helpers.findCertainShow(sickbeard.showList, int(indexer_id)): @@ -3642,7 +3629,7 @@ class ConfigGeneral(Config): sickbeard.save_config() def saveGeneral(self, log_dir=None, log_nr = 5, log_size = 1048576, web_port=None, web_log=None, encryption_version=None, web_ipv6=None, - trash_remove_show=None, trash_rotate_logs=None, update_frequency=None, + trash_remove_show=None, trash_rotate_logs=None, update_frequency=None, skip_removed_files=None, indexerDefaultLang='en', ep_default_deleted_status=None, launch_browser=None, showupdate_hour=3, web_username=None, api_key=None, indexer_default=None, timezone_display=None, cpu_preset='NORMAL', web_password=None, version_notify=None, enable_https=None, https_cert=None, https_key=None, @@ -3659,6 +3646,7 @@ class ConfigGeneral(Config): sickbeard.DOWNLOAD_URL = download_url sickbeard.INDEXER_DEFAULT_LANGUAGE = indexerDefaultLang sickbeard.EP_DEFAULT_DELETED_STATUS = ep_default_deleted_status + sickbeard.SKIP_REMOVED_FILES = config.checkbox_to_value(skip_removed_files) sickbeard.LAUNCH_BROWSER = config.checkbox_to_value(launch_browser) config.change_SHOWUPDATE_HOUR(showupdate_hour) config.change_VERSION_NOTIFY(config.checkbox_to_value(version_notify)) @@ -3933,7 +3921,7 @@ class ConfigPostProcessing(Config): tv_download_dir=None, naming_custom_abd=None, naming_anime=None,create_missing_show_dirs=None,add_shows_wo_dir=None, naming_abd_pattern=None, naming_strip_year=None, use_failed_downloads=None, - delete_failed=None, extra_scripts=None, skip_removed_files=None, + delete_failed=None, extra_scripts=None, naming_custom_sports=None, naming_sports_pattern=None, naming_custom_anime=None, naming_anime_pattern=None, naming_anime_multi_ep=None, autopostprocesser_frequency=None): @@ -3972,7 +3960,6 @@ class ConfigPostProcessing(Config): sickbeard.NAMING_STRIP_YEAR = config.checkbox_to_value(naming_strip_year) sickbeard.USE_FAILED_DOWNLOADS = config.checkbox_to_value(use_failed_downloads) sickbeard.DELETE_FAILED = config.checkbox_to_value(delete_failed) - sickbeard.SKIP_REMOVED_FILES = config.checkbox_to_value(skip_removed_files) sickbeard.NFO_RENAME = config.checkbox_to_value(nfo_rename) sickbeard.METADATA_KODI = kodi_data