Say hello to the new ComicBook generator for okular.

Information about this format and testfiles can be found at
  http://en.wikipedia.org/wiki/CDisplay_RAR_Archived_Comic_Book_File


svn path=/trunk/playground/graphics/okular/; revision=624702
This commit is contained in:
Tobias Koenig 2007-01-17 18:49:05 +00:00
parent 169b752433
commit deabbae3bf
12 changed files with 547 additions and 0 deletions

View file

@ -29,3 +29,5 @@ add_subdirectory(xps)
add_subdirectory(ooo)
add_subdirectory(fictionbook)
add_subdirectory(comicbook)

View file

@ -0,0 +1,26 @@
include_directories(
${CMAKE_SOURCE_DIR}/okular
)
########### next target ###############
set( okularGenerator_comicbook_PART_SRCS
document.cpp
generator_comicbook.cpp
unrar.cpp
)
kde4_automoc(${okularGenerator_comicbook_PART_SRCS})
kde4_add_plugin(okularGenerator_comicbook WITH_PREFIX ${okularGenerator_comicbook_PART_SRCS})
target_link_libraries(okularGenerator_comicbook okularcore ${KDE4_KDEUI_LIBS} )
install(TARGETS okularGenerator_comicbook DESTINATION ${PLUGIN_INSTALL_DIR})
########### install files ###############
install( FILES libokularGenerator_comicbook.desktop okularComicbook.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
install( FILES x-cbz.desktop x-cbr.desktop DESTINATION ${MIME_INSTALL_DIR}/application )

View file

@ -0,0 +1,127 @@
/***************************************************************************
* Copyright (C) 2007 by Tobias Koenig <tokoe@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#include <QtGui/QImage>
#include <kzip.h>
#include "document.h"
#include "unrar.h"
using namespace ComicBook;
Document::Document()
: mUnrar( 0 ), mZip( 0 )
{
}
Document::~Document()
{
delete mUnrar;
delete mZip;
}
bool Document::open( const QString &fileName )
{
delete mZip;
delete mUnrar;
/**
* We have a zip archive
*/
if ( fileName.toLower().endsWith( ".cbz" ) ) {
mZip = new KZip( fileName );
if ( !mZip->open( QIODevice::ReadOnly ) ) {
delete mZip;
mZip = 0;
return false;
}
const KArchiveDirectory *directory = mZip->directory();
if ( !directory ) {
delete mZip;
mZip = 0;
return false;
}
mZipDir = const_cast<KArchiveDirectory*>( directory );
QStringList entries = directory->entries();
if ( entries.count() == 1 ) {
// seems to be a nested directory
const KArchiveEntry *entry = directory->entry( entries[ 0 ] );
if ( entry->isDirectory() ) {
entries = static_cast<const KArchiveDirectory*>( entry )->entries();
mZipDir = const_cast<KArchiveDirectory*>( static_cast<const KArchiveDirectory*>( entry ) );
}
}
extractImageFiles( entries );
} else {
/**
* We have a rar archive
*/
mUnrar = new Unrar();
if ( !mUnrar->open( fileName ) ) {
delete mUnrar;
mUnrar = 0;
return false;
}
extractImageFiles( mUnrar->list() );
}
return true;
}
void Document::extractImageFiles( const QStringList &list )
{
QStringList files( list );
qSort( files );
for ( int i = 0; i < files.count(); ++i ) {
const QString lowerFile = files[ i ].toLower();
if ( lowerFile.endsWith( ".gif" ) ||
lowerFile.endsWith( ".jpg" ) ||
lowerFile.endsWith( ".jpeg" ) ||
lowerFile.endsWith( ".png" ) )
mPageMap.append( files[ i ] );
}
}
int Document::pages() const
{
return mPageMap.count();
}
QStringList Document::pageTitles() const
{
return QStringList();
}
QImage Document::pageImage( int page ) const
{
if ( mZip ) {
const KArchiveFile *entry = static_cast<const KArchiveFile*>( mZipDir->entry( mPageMap[ page ] ) );
if ( entry )
return QImage::fromData( entry->data() );
} else {
return QImage::fromData( mUnrar->contentOf( mPageMap[ page ] ) );
}
return QImage();
}

View file

@ -0,0 +1,46 @@
/***************************************************************************
* Copyright (C) 2007 by Tobias Koenig <tokoe@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#ifndef COMICBOOK_DOCUMENT_H
#define COMICBOOK_DOCUMENT_H
#include <QtCore/QStringList>
class KArchiveDirectory;
class KZip;
class QImage;
class Unrar;
namespace ComicBook {
class Document
{
public:
Document();
~Document();
bool open( const QString &fileName );
int pages() const;
QStringList pageTitles() const;
QImage pageImage( int page ) const;
private:
void extractImageFiles( const QStringList& );
QStringList mPageMap;
Unrar *mUnrar;
KZip *mZip;
KArchiveDirectory *mZipDir;
};
}
#endif

View file

@ -0,0 +1,89 @@
/***************************************************************************
* Copyright (C) 2007 by Tobias Koenig <tokoe@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#include <qpainter.h>
#include <kprinter.h>
#include <okular/core/page.h>
#include "generator_comicbook.h"
OKULAR_EXPORT_PLUGIN(ComicBookGenerator)
ComicBookGenerator::ComicBookGenerator()
: Generator()
{
}
ComicBookGenerator::~ComicBookGenerator()
{
}
bool ComicBookGenerator::loadDocument( const QString & fileName, QVector<Okular::Page*> & pagesVector )
{
if ( !mDocument.open( fileName ) )
return false;
int pages = mDocument.pages();
pagesVector.resize( pages );
for ( int i = 0; i < pages; ++i ) {
Okular::Page * page = new Okular::Page( i, 800, 600, Okular::Rotation0 );
pagesVector[i] = page;
}
return true;
}
bool ComicBookGenerator::closeDocument()
{
return true;
}
bool ComicBookGenerator::canGeneratePixmap( bool ) const
{
return true;
}
void ComicBookGenerator::generatePixmap( Okular::PixmapRequest * request )
{
int width = request->width();
int height = request->height();
QImage image = mDocument.pageImage( request->pageNumber() );
image = image.scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
request->page()->setPixmap( request->id(), new QPixmap( QPixmap::fromImage( image ) ) );
// signal that the request has been accomplished
signalRequestDone(request);
}
bool ComicBookGenerator::print( KPrinter& printer )
{
QPainter p( &printer );
for ( int i = 0; i < mDocument.pages(); ++i ) {
const QImage image = mDocument.pageImage( i );
if ( i != 0 )
printer.newPage();
p.drawImage( 0, 0, image );
}
return true;
}
bool ComicBookGenerator::hasFeature( GeneratorFeature ) const
{
return false;
}
#include "generator_comicbook.moc"

View file

@ -0,0 +1,42 @@
/***************************************************************************
* Copyright (C) 2007 by Tobias Koenig <tokoe@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#ifndef GENERATOR_COMICBOOK_H
#define GENERATOR_COMICBOOK_H
#include <okular/core/generator.h>
#include "document.h"
class ComicBookGenerator : public Okular::Generator
{
Q_OBJECT
public:
ComicBookGenerator();
virtual ~ComicBookGenerator();
// [INHERITED] load a document and fill up the pagesVector
bool loadDocument( const QString & fileName, QVector<Okular::Page*> & pagesVector );
bool closeDocument();
// [INHERITED] perform actions on document / pages
bool canGeneratePixmap( bool async ) const;
void generatePixmap( Okular::PixmapRequest * request );
// [INHERITED] print document using already configured kprinter
bool print( KPrinter& printer );
bool hasFeature( GeneratorFeature feature ) const;
private:
ComicBook::Document mDocument;
};
#endif

View file

@ -0,0 +1,11 @@
[Desktop Entry]
Encoding=UTF-8
Type=Service
Name=Comic Book
Comment=Comic book backend for okular
ServiceTypes=okular/Generator
MimeType=application/x-cbz;application/x-cbr;
X-KDE-Library=libokularGenerator_comicbook
X-KDE-Priority=1
X-KDE-okularAPIVersion=1
X-KDE-okularHasInternalSettings=false

View file

@ -0,0 +1,8 @@
[Desktop Entry]
Encoding=UTF-8
Icon=okular
Name=okular
ServiceTypes=KParts/ReadOnlyPart
X-KDE-Library=libokularpart
Type=Service
MimeType=application/x-cbz;application/x-cbr;

View file

@ -0,0 +1,113 @@
/***************************************************************************
* Copyright (C) 2007 by Tobias Koenig <tokoe@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#include <QtCore/QFile>
#include <QtCore/QProcess>
#include <ktempdir.h>
#include "unrar.h"
Unrar::Unrar()
: QObject( 0 ), mTempDir( 0 ), mErrorOccured( false )
{
}
Unrar::~Unrar()
{
delete mTempDir;
}
bool Unrar::open( const QString &fileName )
{
delete mTempDir;
mTempDir = new KTempDir();
mFileName = fileName;
/**
* Extract the archive to a temporary directory
*/
mStdOutData.clear();
mStdErrData.clear();
mProcess = new QProcess( this );
connect( mProcess, SIGNAL( readyReadStandardOutput() ), SLOT( readFromStdout() ) );
connect( mProcess, SIGNAL( readyReadStandardError() ), SLOT( readFromStderr() ) );
connect( mProcess, SIGNAL( finished( int, QProcess::ExitStatus ) ), SLOT( processExited() ) );
connect( mProcess, SIGNAL( error( QProcess::ProcessError ) ), SLOT( processExited() ) );
mProcess->start( "unrar", QStringList() << "e" << mFileName << mTempDir->name(), QIODevice::ReadOnly );
mEventLoop.exec();
delete mProcess;
mProcess = 0;
if ( mErrorOccured ) {
mErrorOccured = false;
return false;
}
return true;
}
QStringList Unrar::list()
{
mStdOutData.clear();
mStdErrData.clear();
mProcess = new QProcess( this );
connect( mProcess, SIGNAL( readyReadStandardOutput() ), SLOT( readFromStdout() ) );
connect( mProcess, SIGNAL( readyReadStandardError() ), SLOT( readFromStderr() ) );
connect( mProcess, SIGNAL( finished( int, QProcess::ExitStatus ) ), SLOT( processExited() ) );
connect( mProcess, SIGNAL( error( QProcess::ProcessError ) ), SLOT( processError() ) );
mProcess->start( "unrar", QStringList() << "lb" << mFileName, QIODevice::ReadOnly );
mEventLoop.exec();
delete mProcess;
mProcess = 0;
return QString::fromLocal8Bit( mStdOutData ).split( "\n", QString::SkipEmptyParts );
}
QByteArray Unrar::contentOf( const QString &fileName ) const
{
QFile file( mTempDir->name() + fileName );
if ( !file.open( QIODevice::ReadOnly ) )
return QByteArray();
return file.readAll();
}
void Unrar::readFromStdout()
{
mStdOutData += mProcess->readAllStandardOutput();
}
void Unrar::readFromStderr()
{
mStdErrData += mProcess->readAllStandardError();
}
void Unrar::processExited()
{
mEventLoop.exit();
}
void Unrar::processError()
{
mErrorOccured = true;
}
#include "unrar.moc"

View file

@ -0,0 +1,67 @@
/***************************************************************************
* Copyright (C) 2007 by Tobias Koenig <tokoe@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#ifndef UNRAR_H
#define UNRAR_H
#include <QtCore/QEventLoop>
#include <QtCore/QObject>
#include <QtCore/QStringList>
class QProcess;
class KTempDir;
class Unrar : public QObject
{
Q_OBJECT
public:
/**
* Creates a new unrar object.
*/
Unrar();
/**
* Destroys the unrar object.
*/
~Unrar();
/**
* Opens given rar archive.
*/
bool open( const QString &fileName );
/**
* Returns the list of files from the archive.
*/
QStringList list();
/**
* Returns the content of the file with the given name.
*/
QByteArray contentOf( const QString &fileName ) const;
private Q_SLOTS:
void processExited();
void processError();
void readFromStdout();
void readFromStderr();
private:
QProcess *mProcess;
QEventLoop mEventLoop;
QString mFileName;
QByteArray mStdOutData;
QByteArray mStdErrData;
KTempDir *mTempDir;
bool mErrorOccured;
};
#endif

View file

@ -0,0 +1,8 @@
[Desktop Entry]
Type=MimeType
Encoding=UTF-8
MimeType=application/x-cbr
Icon=package_toys
Patterns=*.cbr;*.CBR;
Comment=Comic Book
Comment[x-test]=xxComic Bookxx

View file

@ -0,0 +1,8 @@
[Desktop Entry]
Type=MimeType
Encoding=UTF-8
MimeType=application/x-cbz
Icon=package_toys
Patterns=*.cbz;*.CBZ;
Comment=Comic Book
Comment[x-test]=xxComic Bookxx