diff --git a/generators/CMakeLists.txt b/generators/CMakeLists.txt index f30a05e79..9d0e6cbce 100644 --- a/generators/CMakeLists.txt +++ b/generators/CMakeLists.txt @@ -29,3 +29,5 @@ add_subdirectory(xps) add_subdirectory(ooo) add_subdirectory(fictionbook) + +add_subdirectory(comicbook) diff --git a/generators/comicbook/CMakeLists.txt b/generators/comicbook/CMakeLists.txt new file mode 100644 index 000000000..c7b5268f0 --- /dev/null +++ b/generators/comicbook/CMakeLists.txt @@ -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 ) diff --git a/generators/comicbook/document.cpp b/generators/comicbook/document.cpp new file mode 100644 index 000000000..8c594770b --- /dev/null +++ b/generators/comicbook/document.cpp @@ -0,0 +1,127 @@ +/*************************************************************************** + * Copyright (C) 2007 by Tobias Koenig * + * * + * 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 + +#include + +#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( 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( entry )->entries(); + mZipDir = const_cast( static_cast( 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( mZipDir->entry( mPageMap[ page ] ) ); + if ( entry ) + return QImage::fromData( entry->data() ); + + } else { + return QImage::fromData( mUnrar->contentOf( mPageMap[ page ] ) ); + } + + return QImage(); +} diff --git a/generators/comicbook/document.h b/generators/comicbook/document.h new file mode 100644 index 000000000..4e806e5cc --- /dev/null +++ b/generators/comicbook/document.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2007 by Tobias Koenig * + * * + * 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 + +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 diff --git a/generators/comicbook/generator_comicbook.cpp b/generators/comicbook/generator_comicbook.cpp new file mode 100644 index 000000000..a1a2f52b5 --- /dev/null +++ b/generators/comicbook/generator_comicbook.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + * Copyright (C) 2007 by Tobias Koenig * + * * + * 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 +#include + +#include + +#include "generator_comicbook.h" + +OKULAR_EXPORT_PLUGIN(ComicBookGenerator) + +ComicBookGenerator::ComicBookGenerator() + : Generator() +{ +} + +ComicBookGenerator::~ComicBookGenerator() +{ +} + +bool ComicBookGenerator::loadDocument( const QString & fileName, QVector & 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" + diff --git a/generators/comicbook/generator_comicbook.h b/generators/comicbook/generator_comicbook.h new file mode 100644 index 000000000..0e261ddc6 --- /dev/null +++ b/generators/comicbook/generator_comicbook.h @@ -0,0 +1,42 @@ +/*************************************************************************** + * Copyright (C) 2007 by Tobias Koenig * + * * + * 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 + +#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 & 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 diff --git a/generators/comicbook/libokularGenerator_comicbook.desktop b/generators/comicbook/libokularGenerator_comicbook.desktop new file mode 100644 index 000000000..168c2ad36 --- /dev/null +++ b/generators/comicbook/libokularGenerator_comicbook.desktop @@ -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 diff --git a/generators/comicbook/okularComicbook.desktop b/generators/comicbook/okularComicbook.desktop new file mode 100644 index 000000000..ba27da732 --- /dev/null +++ b/generators/comicbook/okularComicbook.desktop @@ -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; diff --git a/generators/comicbook/unrar.cpp b/generators/comicbook/unrar.cpp new file mode 100644 index 000000000..d321df15d --- /dev/null +++ b/generators/comicbook/unrar.cpp @@ -0,0 +1,113 @@ +/*************************************************************************** + * Copyright (C) 2007 by Tobias Koenig * + * * + * 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 +#include + +#include + +#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" diff --git a/generators/comicbook/unrar.h b/generators/comicbook/unrar.h new file mode 100644 index 000000000..600ee966f --- /dev/null +++ b/generators/comicbook/unrar.h @@ -0,0 +1,67 @@ +/*************************************************************************** + * Copyright (C) 2007 by Tobias Koenig * + * * + * 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 +#include +#include + +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 + diff --git a/generators/comicbook/x-cbr.desktop b/generators/comicbook/x-cbr.desktop new file mode 100644 index 000000000..9332afc12 --- /dev/null +++ b/generators/comicbook/x-cbr.desktop @@ -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 diff --git a/generators/comicbook/x-cbz.desktop b/generators/comicbook/x-cbz.desktop new file mode 100644 index 000000000..e091f514e --- /dev/null +++ b/generators/comicbook/x-cbz.desktop @@ -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