diff options
author | Jeroen Walter <jeroen@enormkansloos.nl> | 2013-02-14 23:04:48 +0100 |
---|---|---|
committer | Jeroen Walter <jeroen@enormkansloos.nl> | 2013-02-14 23:04:48 +0100 |
commit | 4e560aa8e84ffdee747b3caef28b7dd1af8cf524 (patch) | |
tree | c79a187352f094195f90d8592fa8bf622113a2ee | |
parent | f726f429d7a103deac8955b76170796ed53482a7 (diff) | |
download | ComicRackWeb-4e560aa8e84ffdee747b3caef28b7dd1af8cf524.zip ComicRackWeb-4e560aa8e84ffdee747b3caef28b7dd1af8cf524.tar.gz ComicRackWeb-4e560aa8e84ffdee747b3caef28b7dd1af8cf524.tar.bz2 |
- version 1.18, updated for CR 0.9.162
- added missing files I forgot to commit
-rw-r--r-- | ComicRackWebViewer/BCRDatabase.cs | 22 | ||||
-rw-r--r-- | ComicRackWebViewer/BCRExtensions.cs | 79 | ||||
-rw-r--r-- | ComicRackWebViewer/ODataExtensions.cs | 247 | ||||
-rw-r--r-- | ComicRackWebViewer/Program.py | 4 | ||||
-rw-r--r-- | ComicRackWebViewer/tablet/build_package.bat | 3 |
5 files changed, 352 insertions, 3 deletions
diff --git a/ComicRackWebViewer/BCRDatabase.cs b/ComicRackWebViewer/BCRDatabase.cs new file mode 100644 index 0000000..cbeacc5 --- /dev/null +++ b/ComicRackWebViewer/BCRDatabase.cs @@ -0,0 +1,22 @@ +/* + * Created by SharpDevelop. + * User: jeroen + * Date: 1/30/2013 + * Time: 9:39 PM + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ +using System; + +namespace ComicRackWebViewer +{ + /// <summary> + /// Description of BCRDatabase. + /// </summary> + public class BCRDatabase + { + public BCRDatabase() + { + } + } +} diff --git a/ComicRackWebViewer/BCRExtensions.cs b/ComicRackWebViewer/BCRExtensions.cs new file mode 100644 index 0000000..ab97349 --- /dev/null +++ b/ComicRackWebViewer/BCRExtensions.cs @@ -0,0 +1,79 @@ +/* + * Created by SharpDevelop. + * User: jeroen + * Date: 1/30/2013 + * Time: 9:47 PM + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using cYo.Common.IO; +using cYo.Projects.ComicRack.Engine; +using cYo.Projects.ComicRack.Engine.IO.Provider; +using cYo.Projects.ComicRack.Viewer; +using Nancy; + +namespace BCR +{ + public static class BCRExtensions + { + public static Response AsError(this IResponseFormatter formatter, HttpStatusCode statusCode, string message, Request request) + { + return new Response + { + StatusCode = statusCode, + ContentType = "text/plain", + Contents = stream => (new StreamWriter(stream) { AutoFlush = true }).Write("Request: " + request.Url + "\nError: " + message) + }; + } + + + public static List<ComicBook> GetFolderBookList(string folder, bool includeSubFolders) + { + List<ComicBook> list = new List<ComicBook>(); + try + { + IEnumerable<string> fileExtensions = Providers.Readers.GetFileExtensions(); + foreach (string file in FileUtility.GetFiles(folder, includeSubFolders ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly, new string[0])) + { + string f = file; + if (Enumerable.Any<string>(fileExtensions, (Func<string, bool>) (ext => f.EndsWith(ext, StringComparison.OrdinalIgnoreCase)))) + { + ComicBook comicBook = Program.BookFactory.Create(file, CreateBookOption.AddToTemporary, list.Count > 100 ? RefreshInfoOptions.DontReadInformation : RefreshInfoOptions.None); + if (comicBook != null) + list.Add(comicBook); + } + } + } + catch + { + } + return list; + } + + public static List<string> GetFolderBookList2(string folder, bool includeSubFolders) + { + List<string> list = new List<string>(); + try + { + IEnumerable<string> fileExtensions = Providers.Readers.GetFileExtensions(); + foreach (string file in FileUtility.GetFiles(folder, includeSubFolders ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly, new string[0])) + { + string f = file; + if (Enumerable.Any<string>(fileExtensions, (Func<string, bool>) (ext => f.EndsWith(ext, StringComparison.OrdinalIgnoreCase)))) + { + list.Add(file); + } + } + } + catch + { + } + return list; + } + } + +} diff --git a/ComicRackWebViewer/ODataExtensions.cs b/ComicRackWebViewer/ODataExtensions.cs new file mode 100644 index 0000000..eb8be97 --- /dev/null +++ b/ComicRackWebViewer/ODataExtensions.cs @@ -0,0 +1,247 @@ +/* + * Created by SharpDevelop. + * User: jeroen + * Date: 1/30/2013 + * Time: 9:45 PM + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Text.RegularExpressions; +using Linq2Rest.Parser; +using Nancy; + +namespace BCR +{ + public class NaturalSortComparer<T> : IComparer<string>, IDisposable + { + private bool isAscending; + + public NaturalSortComparer(bool inAscendingOrder = true) + { + this.isAscending = inAscendingOrder; + } + + #region IComparer<string> Members + + public int Compare(string x, string y) + { + throw new NotImplementedException(); + } + + #endregion + + #region IComparer<string> Members + + int IComparer<string>.Compare(string x, string y) + { + if (x == y) + return 0; + + string[] x1, y1; + + if (!table.TryGetValue(x, out x1)) + { + x1 = Regex.Split(x.Replace(" ", ""), "([0-9]+)"); + table.Add(x, x1); + } + + if (!table.TryGetValue(y, out y1)) + { + y1 = Regex.Split(y.Replace(" ", ""), "([0-9]+)"); + table.Add(y, y1); + } + + int returnVal; + + for (int i = 0; i < x1.Length && i < y1.Length; i++) + { + if (x1[i] != y1[i]) + { + returnVal = PartCompare(x1[i], y1[i]); + return isAscending ? returnVal : -returnVal; + } + } + + if (y1.Length > x1.Length) + { + returnVal = 1; + } + else if (x1.Length > y1.Length) + { + returnVal = -1; + } + else + { + returnVal = 0; + } + + return isAscending ? returnVal : -returnVal; + } + + private static int PartCompare(string left, string right) + { + int x, y; + if (!int.TryParse(left, out x)) + return left.CompareTo(right); + + if (!int.TryParse(right, out y)) + return left.CompareTo(right); + + return x.CompareTo(y); + } + + #endregion + + private Dictionary<string, string[]> table = new Dictionary<string, string[]>(); + + public void Dispose() + { + table.Clear(); + table = null; + } + } + + public static class ODataExtensions + { + private const string ODATA_URI_KEY = "OData_Uri"; + + private static NameValueCollection MyParseUriOptions(NancyContext context) + { + object item; + if (context.Items.TryGetValue(ODATA_URI_KEY, out item)) + { + return item as NameValueCollection; + } + NameValueCollection nv = new NameValueCollection(); + context.Items.Add(ODATA_URI_KEY, nv); + var queryString = context.Request.Url.Query; + if (string.IsNullOrWhiteSpace(queryString)) + { + return nv; + } + if (!queryString.StartsWith("?")) + { + throw new InvalidOperationException("Invalid OData query string " + queryString); + } + var parameters = queryString.Substring(1).Split('&', '='); + if (parameters.Length % 2 != 0) + { + throw new InvalidOperationException("Invalid OData query string " + queryString); + } + for (int i = 0; i < parameters.Length; i += 2) + { + nv.Add(parameters[i], Uri.UnescapeDataString(parameters[i + 1])); + } + return nv; + } + + public static string GetReflectedPropertyValue(this object subject, string field) + { + object reflectedValue = subject.GetType().GetProperty(field).GetValue(subject, null); + return reflectedValue != null ? reflectedValue.ToString() : ""; + } + + public static IEnumerable<object> ApplyODataUriFilter<T>(this NancyContext context, IEnumerable<T> modelItems, ref int totalCount) + { + var nv = MyParseUriOptions(context); + + + // $select is broken somehow....remove it for now + //NameValueCollection selectNV = new NameValueCollection(); + //selectNV.Add("$select", nv.Get("$select")); + nv.Remove("$select"); + + NameValueCollection pagingNV = new NameValueCollection(); + // We want the total count of the query before limiting the result set with $top and $skip + if (null != nv.Get("$skip")) + { + pagingNV.Add("$skip", nv.Get("$skip")); + nv.Remove("$skip"); + } + + if (null != nv.Get("$top")) + { + pagingNV.Add("$top", nv.Get("$top")); + nv.Remove("$top"); + } + + // perform sorting ourselves, because linq2rest doesn't allow custom comparers. + NameValueCollection sortNV = new NameValueCollection(); + if (null != nv.Get("$orderby")) + { + sortNV.Add("$orderby", nv.Get("$orderby")); + nv.Remove("$orderby"); + } + + // Now do a query that returns all records + var parser = new ParameterParser<T>(); + var filter = parser.Parse(nv); + var objects = filter.Filter(modelItems); + totalCount = objects.Count(); + + // Now sort + // Right now, only a single sort term is supported. + if (null != sortNV.Get("$orderby")) + { + char[] delimiterChars = {','}; + string[] orderby = sortNV.Get("$orderby").Split(delimiterChars); + char[] delimiterSpace = {' '}; + string[] terms = orderby[0].Split(delimiterSpace); + bool ascending = true; + if (terms.Count() == 2) + ascending = terms[1] != "desc"; + + if (orderby.Count() == 1) + { + objects = objects.OrderBy(item => item.GetReflectedPropertyValue(terms[0]), new NaturalSortComparer<string>(ascending)); + } + else + if (orderby.Count() > 1) + { + // get the second orderby + string[] terms2 = orderby[1].Split(delimiterSpace); + bool ascending2 = true; + if (terms2.Count() == 2) + ascending2 = terms2[1] != "desc"; + + objects = objects.OrderBy(item => item.GetReflectedPropertyValue(terms[0]), new NaturalSortComparer<string>(ascending)) + .ThenBy(item => item.GetReflectedPropertyValue(terms2[0]), new NaturalSortComparer<string>(ascending2)); + } + + } + + + // Now limit the resultset + var parser2 = new ParameterParser<T>(); + var filter2 = parser2.Parse(pagingNV); + var objects2 = filter2.Filter(objects.Cast<T>()); + return objects2; + } + + public static Response AsOData<T>(this IResponseFormatter formatter, IEnumerable<T> modelItems, HttpStatusCode code = HttpStatusCode.OK) + { + bool isJson = formatter.Context.Request.Headers.Accept.Select(x => x.Item1).Where(x => x.StartsWith("application/json", StringComparison.InvariantCultureIgnoreCase)).Any(); + + var nv = MyParseUriOptions(formatter.Context); + string value = nv.Get("$format"); + if (string.Compare(value, "json", true) == 0) + { + isJson = true; + } + + // BCR only supports json, no need to supply the $format every time.... + isJson = true; + + if (isJson) + { + int totalCount = 0; + return formatter.AsJson(formatter.Context.ApplyODataUriFilter(modelItems, ref totalCount), code); + } + throw new NotImplementedException("Atom feeds not implemented"); + } + } +} diff --git a/ComicRackWebViewer/Program.py b/ComicRackWebViewer/Program.py index 7f10626..de14558 100644 --- a/ComicRackWebViewer/Program.py +++ b/ComicRackWebViewer/Program.py @@ -34,9 +34,9 @@ def ComicRackWebViewerStartup(): def IsVersionOK():
- requiredVersion = Version(0, 9, 161)
+ requiredVersion = Version(0, 9, 162)
if str(ComicRack.App.ProductVersion) != str(requiredVersion):
- MessageBox.Show( ComicRack.MainWindow, "Version check failed!\n\nThe ComicRack Web Viewer Plugin requires an updated version of ComicRack.\nComicRack version required: " + str(requiredVersion) + ".\nExiting...", "Incompatible ComicRack version", MessageBoxButtons.OK, MessageBoxIcon.Warning)
+ MessageBox.Show( ComicRack.MainWindow, "Version check failed!\n\nThe ComicRack Web Viewer Plugin requires a different version of ComicRack.\nComicRack version required: " + str(requiredVersion) + ".\nExiting...", "Incompatible ComicRack version", MessageBoxButtons.OK, MessageBoxIcon.Warning)
return str(ComicRack.App.ProductVersion) == str(requiredVersion)
\ No newline at end of file diff --git a/ComicRackWebViewer/tablet/build_package.bat b/ComicRackWebViewer/tablet/build_package.bat index bfdd53e..fb4c877 100644 --- a/ComicRackWebViewer/tablet/build_package.bat +++ b/ComicRackWebViewer/tablet/build_package.bat @@ -2,7 +2,8 @@ pushd . -call sencha app build package +set SENCHA_SDK_TOOLS_2_0_0_BETA3=D:\bcr\SenchaSDKTools-2.0.0-beta3 +call D:\bcr\SenchaSDKTools-2.0.0-beta3\sencha app build package popd |