ComicReader X – Parte 4. Entendendo o ComicReaderX.Manager

No assembly ComicReaderX.Manager encontramos a classe Manager responsável por muitas coisas (eu sei que deveria fazer um refactoring aqui e distribuir melhor as responsabilidades, mas como disse anteriormente, nesse momento eu não procurava pelo melhor design, apenas queria ver o projeto funcionando). Nela encontramos os métodos responsáveis por abrir o arquivo, descompactá-lo, gerar os thumbnails e posteriormente fechar o arquivo liberando assim recursos.

Antes de explorar cada uma dessas funcionalidades quero explicar como é o funcionamento geral. Ao iniciar a aplicação o sistema cria uma pasta temporária que será utilizada durante sua execução. Por padrão essa pasta está definida em C:\ProgramData\ComicReaderX. Então ao abrir um arquivo e antes de extraí-lo o sistema cria uma subpasta no local padrão, essa pasta é um Guid gerado automaticamente, isso para permitir que mais de uma instância do sistema possa ser utilizada e até mesmo que o mesmo arquivo possa ser aberto ao mesmo tempo.

Com essa pasta criada o sistema então extrai o conteúdo do arquivo, filtrando as imagens e a cada imagem encontrada seu thumb é criado, uma instância de Page é criada e adicionada ao objeto Comic corrente.

Abrindo um arquivo .CBR

O ComicReaderX permite que um arquivo .CBR seja aberto de duas maneiras, clicando diretamente sobre o arquivo ou depois que o programa já foi aberto, através de um botão “Open”. Vamos ver primeiro como um arquivo é aberto através do botão.

public void ExtractFile(string filepath)
        {
            _rarFile = filepath;
            _listPaginas.Clear();
            _listThumb.Clear(); 
            string destinationFolder = _tempFolder + '\\' + System.IO.Path.GetFileName(filepath);
             
            if  (!System.IO.Directory.Exists(destinationFolder))
                System.IO.Directory.CreateDirectory(destinationFolder);
            try
            {
                if (_unrar == null) _unrar = new Unrar();
 
                _unrar.DestinationPath = destinationFolder;
                _unrar.Open(filepath, Unrar.OpenMode.List);
                TotalPages = _unrar.ListFiles().Length;
                _unrar.Close();
                _unrar.Open(filepath,Unrar.OpenMode.Extract);
                Currentpage = 0;
                while (_unrar.ReadHeader())
                {
                    _unrar.Extract();
                    if ((!_unrar.CurrentFile.IsDirectory) && (_unrar.CurrentFile.FileName.EndsWith(".jpg",StringComparison.InvariantCultureIgnoreCase)))
                    {
                        Currentpage += 1;
                        _listPaginas.Add(destinationFolder + "\\"+_unrar.CurrentFile.FileName);
                        _listThumb.Add(getThumbnaiImage(80, destinationFolder + "\\" + _unrar.CurrentFile.FileName));
                        if (bw != null)
                            bw.ReportProgress(Currentpage);
                    }
                        
                }
            }
            catch (Exception ex)
            {
                throw (ex);
            }
 
            finally
            {
                if (_unrar != null)
                {
                    _unrar.Close();
                    _unrar.Dispose();
                }
                    
            }
        }

No método acima estamos descompactando o arquivo que foi passado como parâmetro. Veja que estamos utilizando o Unrar, que foi definido no assembly ComicReaderX.Reader. Novamente acho que deveria ter um refactoring aqui para separar um pouco essas classes, criando uma interface que abstraia essa funcionalidade e que sua implementação seja delegada a outra classe.

Veja que para referência na criação das pastas estamos utilizando um campo privado chamado _tempFolder, abaixo vemos como ele é gerado.

 

public Manager()
        {
            _tempFolder = System.Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
            _tempFolder = System.IO.Path.Combine(_tempFolder, "ComicReaderX");
            _tempFolder = System.IO.Path.Combine(_tempFolder, unique.ToString());
        }

Da forma como é criada, a pasta não causará violações de permissão no Windows Vista. Durante a extração dos arquivos seu thumbnail também criado. Isso vemos no método abaixo

private string getThumbnaiImage(int height, String original)
        {
            Image img = Image.FromFile(original);
            float porcentagem = ((height*100)/img.Height);
            int width = Convert.ToInt32((porcentagem * img.Width)/100);
 
            Image thumb = new Bitmap(width, height);
            Image.GetThumbnailImageAbort myCallback = new Image.GetThumbnailImageAbort(ThumbnailCallback);
            Image tmp = img.GetThumbnailImage(width, height, myCallback, IntPtr.Zero);
 
            using (Graphics g = Graphics.FromImage(thumb))
            {
                g.DrawImage(tmp, 0, 0, tmp.Width, tmp.Height);
            }
 
 
            if (tmp != null) tmp.Dispose();
            thumb.Save(original + ".thumb.jpg");
            thumb.Dispose();
           
            return original + ".thumb.jpg";
        }
 
        public bool ThumbnailCallback()
        {
            return true;
        }

Durante a extração veja que armazenamos em duas variáveis o caminho onde foi extraído a imagem e seu nome e também qual o nome do thumb gerado e o local pra onde foi gerado. Essas informações serão posteriormente utilizadas pelo método OpenComicFile, conforme é visto abaixo:

public ComicBook OpenComicFile()
        {
            comic = new ComicBook();
            comic.Filename = System.IO.Path.GetFileName(_rarFile);
            string destinationFolder = _tempFolder + '\\' + System.IO.Path.GetFileName(_rarFile);
            comic.ReadingFolder = destinationFolder;
 
            _listThumb.Sort();
            _listPaginas.Sort();
            for (int i=0; i <= _listPaginas.Count-1; i++)
            {
                Page page = new Page();
                page.FileName = _listPaginas[i] ;
                page.Number = i + 1;
                page.Thumb = _listThumb[i];
                comic.Pages.Add(page);
            }
 
            if (comic.Pages.Count > 0)
                comic.Cover = comic.Pages[0].FileName;
            return comic;
        }
 

O método OpenComicFile é responsável por criar os objetos que são acessados pela UI. Veja que estamos dando um Sort nas listas _listThumb e _listPaginas, isto para que as páginas possam ser acessadas na sua ordem correta.

Por fim, para o momento, temos o método CloseComicFile, que é chamado quando o usuário encerra a leitura do arquivo do arquivo para excluir os arquivos anteriormente criados.

 

public void CloseComicFile(ComicBook cb)
        {
            Directory.Delete(cb.ReadingFolder,true);
        }

No próximo post vamos começar a ver o WPF mesmo, como que esses assemblies até agora apresentados, foram utilizados, como criei a UI, etc… Até lá.

Esse post foi publicado em ComicReader X. Bookmark o link permanente.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s