Click here to Skip to main content
15,881,709 members
Articles / Desktop Programming / WPF

C.B.R.

Rate me:
Please Sign up or sign in to vote.
4.96/5 (52 votes)
22 Oct 2012GPL329 min read 123.9K   1.8K   132  
Comic and electronic publication reader with library management, extended file conversion, and devices support.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using CBR.Core.Files;
using CBR.Core.Helpers;
using CBR.Core.Models;
using SevenZip;

namespace CBR.Core.Services
{
	public class CatalogService
	{
		#region ----------------SINGLETON----------------
		public static readonly CatalogService Instance = new CatalogService();

		/// <summary>
		/// Private constructor for singleton pattern
		/// </summary>
		private CatalogService()
		{
            string sevenZip = Path.Combine(ApplicationPath, "Dependencies\\7z.dll");
            SevenZipExtractor.SetLibraryPath(sevenZip);
		}

		#endregion

		#region ----------------PROPERTIES----------------

        

		private string applicationPath;
		internal string ApplicationPath
		{
			get
			{
				if (string.IsNullOrEmpty(applicationPath))
					applicationPath = System.IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);

				return applicationPath;
			}
		}

		#endregion

		#region -----------------LOAD-----------------

		public Catalog Open(string path)
		{
			Catalog catlog = null;

			try
			{
				//the file exist, try to load
				if (File.Exists(path))
					catlog = (Catalog)BinaryHelper.Deserialize(path);

				//complete the load by loading the books
				if (catlog != null)
				{
					catlog.CatalogFilePath = path;

                    Thread t = new Thread(new ParameterizedThreadStart(LaunchLoadBookThreads));
                    t.IsBackground = true;
                    t.Priority = ThreadPriority.Lowest;
                    t.Start(catlog);

                    WorkspaceService.Instance.AddRecent(catlog);
				}
			}
			catch (Exception err)
			{
				ExceptionHelper.Manage("CatalogService:Load", err);
			}

			return catlog;
		}

        private static void LaunchLoadBookThreads(object param)
        {
            try
            {
                Catalog catlog = param as Catalog;

                foreach (string filepath in catlog.BookInfoFilePath)
                {
                    // load the book info + cover
                    Thread t = new Thread(new ParameterizedThreadStart(new BookInfoService().LoadBookInfo));
                    t.IsBackground = true;
                    t.Priority = ThreadPriority.Lowest;
                    t.Start(new ThreadExchangeData() { BookPath = filepath, ThreadCatalog = catlog });
                }
            }
            catch (Exception err)
            {
                ExceptionHelper.Manage("CatalogService:LaunchLoadBookThreads", err);
            }
        }

		#endregion

		#region -----------------SAVE-----------------

		public void SaveAs(Catalog catlog, string newFileName)
		{
			try
			{
				catlog.CatalogFilePath = newFileName;
				Save(catlog);
			}
			catch (Exception err)
			{
				ExceptionHelper.Manage("CatalogService:SaveAs", err);
			}
		}

		public void Save(Catalog catlog)
		{
			try
			{
				if (IsDirty(catlog))
				{
					//remove the book without covers
					//RemoveDirtyBooks(CurrentCatalog);

					//save catalog file info
					BinaryHelper.Serialize(catlog.CatalogFilePath, catlog);

					//complete the save by saving the books
					if (catlog.BookInfoFilePath.Count > 0)
					{
						foreach (Book bk in catlog.Books.Where(bkk => bkk.IsDirty))
						{
                            Thread t = new Thread(new ParameterizedThreadStart(new BookInfoService().SaveBookInfo));
							t.IsBackground = true;
							t.Priority = ThreadPriority.BelowNormal;
							t.Start(bk);
						}
					}
				}
			}
			catch (Exception err)
			{
				ExceptionHelper.Manage("CatalogService:SaveCatalog", err);
			}
		}

		#endregion

		#region -----------------DIRECTORY PARSING-----------------

		internal void ParseDirectoryRecursive(object param)
		{
			ThreadExchangeData ted = param as ThreadExchangeData;

			try
			{
				DirectoryInfo directory = new DirectoryInfo((string)ted.BookPath);
				if (!directory.Exists)
				{
					Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate
					{
						MessageBox.Show("Catalog path does not exist! Please check the options box");
					});
					return;
				}
				foreach (FileInfo file in directory.GetFiles("*.*"))
				{
                    if (FileExtensionManager.Instance.FindBookFilterByExt(file.Extension) != null)
					{
						if (!BookExistInCollection(ted.ThreadCatalog, file.FullName))
						{
                            Book bkk = BookServiceFactory.Instance.GetService(file.FullName).CreateBookWithCover(BookFolder, file);

							Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate
							{
								ted.ThreadCatalog.Books.Add(bkk);
							});
							ted.ThreadCatalog.BookInfoFilePath.Add(bkk.BookInfoFilePath);
							ted.ThreadCatalog.IsDirty = true;
						}
					}
				}
				foreach (DirectoryInfo dir in directory.GetDirectories("*", SearchOption.TopDirectoryOnly))
				{
					ted.BookPath = dir.FullName;
					ParseDirectoryRecursive(ted);
				}
			}
			catch (Exception err)
			{
				ExceptionHelper.Manage("CatalogService:ParseDirectoryRecursive", err);
			}
		}

		internal bool BookExistInCollection(Catalog catlog, string filepath)
		{
            return catlog.Books.AsParallel().Count(p => p.FilePath == filepath) == 0 ? false : true;
		}

		#endregion

		#region -----------------REFRESH-----------------

		public void Refresh(Catalog catlog)
		{
			try
			{
				Thread t = new Thread(new ParameterizedThreadStart(RefreshThread));
				t.IsBackground = true;
				t.Priority = ThreadPriority.BelowNormal;
                t.Start(new ThreadExchangeData() { BookPath = catlog.BookFolder, ThreadCatalog = catlog });
			}
			catch (Exception err)
			{
				ExceptionHelper.Manage("CatalogService:Refresh", err);
			}
		}

		internal void RefreshThread(object param)
		{
			ThreadExchangeData ted = param as ThreadExchangeData;
			try
			{
				//first, remove unfounded books
				List<Book> temp = new List<Book>();
				foreach (Book bk in ted.ThreadCatalog.Books)
				{
					if (!File.Exists(bk.FilePath))
						temp.Add(bk);
				}

				foreach (Book bk in temp)
				{
					Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate
					{
                        ted.ThreadCatalog.Books.Remove(bk);
                    });
					ted.ThreadCatalog.IsDirty = true;
				}

				//then add the new ones
				ParseDirectoryRecursive(ted);
			}
			catch (Exception err)
			{
				ExceptionHelper.Manage("CatalogService:RefreshThread", err);
			}
		}
		#endregion

		#region -----------------BOOKS-----------------

		private string _bookFolfer = string.Empty;
		internal string BookFolder
		{
			get
			{ 
				if( string.IsNullOrEmpty(_bookFolfer) )
				{
					_bookFolfer = Path.Combine(ApplicationPath, "BookInfos");
					if (!Directory.Exists(_bookFolfer))
						Directory.CreateDirectory(_bookFolfer);
				}
				return _bookFolfer;
			}
		}

        public void AddBook(Catalog catlog, string bookFile)
        {
            ThreadExchangeData ted = new ThreadExchangeData();

            try
            {
                FileInfo fi = new FileInfo(bookFile);
                if (FileExtensionManager.Instance.FindBookFilterByExt(fi.Extension) != null)
                {
                    if (!BookExistInCollection(catlog, fi.FullName))
                    {
                        Book bkk = BookServiceFactory.Instance.GetService(fi.FullName).CreateBookWithCover(BookFolder, fi);
                        catlog.Books.Add(bkk);
                        catlog.BookInfoFilePath.Add(bkk.BookInfoFilePath);
                        catlog.IsDirty = true;
                    }
                }
            }
            catch (Exception err)
            {
                ExceptionHelper.Manage("CatalogService:AddBook", err);
            }
        }

		//internal void AddBook(ThreadExchangeData ted, FileInfo file)
		//{
		//    string bookDir = Path.Combine(ApplicationPath, "BookInfos");
		//    if (!Directory.Exists(bookDir))
		//        Directory.CreateDirectory(bookDir);

		//    Book bk = new Book(GetBookInfoName(file), file.FullName, true);
		//    bk.Size = file.Length;
		//    ted.ThreadCatalog.Books.Add(bk);

		//    ted.ThreadCatalog.BookInfoFilePath.Add(bk.BookInfoFilePath);
		//    ted.ThreadCatalog.IsDirty = true;
		//}

		//internal string GetBookInfoName(FileInfo file)
		//{
		//    string bookDir = Path.Combine(ApplicationPath, "BookInfos");

		//    return Path.Combine(bookDir, file.DirectoryName.Replace(file.Directory.Root.Name, "").Replace('\\', '.') + "." + file.Name + ".cbb");
		//}

        public void Fill(Catalog cat, string bookPath)
        {
            ThreadExchangeData ted = new ThreadExchangeData();

            try
            {
                cat.BookFolder = bookPath;

                ted.ThreadCatalog = cat;
                ted.BookPath = cat.BookFolder;

                Thread t = new Thread(new ParameterizedThreadStart(ParseDirectoryRecursive));
                t.IsBackground = true;
                t.Priority = ThreadPriority.BelowNormal;
                t.Start(ted);
            }
            catch (Exception err)
            {
                ExceptionHelper.Manage("CatalogService:Create", err);
            }
        }

        public bool IsDirty(Catalog catlog)
        {
            try
            {
                return (catlog.IsDirty || catlog.Books.AsParallel().Count(p => p.IsDirty == true) != 0 );
            }
            catch (Exception err)
            {
                ExceptionHelper.Manage("CatalogService:IsDirty", err);
            }

            return false;
        }

        public bool IsDynamic(Catalog catlog)
        {
            try
            {
                return (catlog.Books.AsParallel().Count(b => b.Pages.AsParallel().Count( p => p.Frames.Count !=0 ) != 0) != 0);
            }
            catch (Exception err)
            {
                ExceptionHelper.Manage("CatalogService:IsDynamic", err);
            }

            return false;
        }

        #endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Architect
France France
WPF and MVVM fan, I practice C # in all its forms from the beginning of the NET Framework without mentioning C ++ / MFC and other software packages such as databases, ASP, WCF, Web & Windows services, Application, and now Core and UWP.
In my wasted hours, I am guilty of having fathered C.B.R. and its cousins C.B.R. for WinRT and UWP on the Windows store.
But apart from that, I am a great handyman ... the house, a rocket stove to heat the jacuzzi and the last one: a wood oven for pizza, bread, and everything that goes inside

https://guillaumewaser.wordpress.com/
https://fouretcompagnie.wordpress.com/

Comments and Discussions