mirror of
https://invent.kde.org/graphics/okular
synced 2024-08-27 03:30:20 +00:00
Mobipocket support for okular, thumbnails and strigi
svn path=/trunk/KDE/kdegraphics/okular/; revision=928589
This commit is contained in:
commit
a48680c1e5
|
@ -72,3 +72,5 @@ endif(JPEG_FOUND AND ZLIB_FOUND)
|
|||
if(EPUB_FOUND)
|
||||
add_subdirectory(epub)
|
||||
endif(EPUB_FOUND)
|
||||
|
||||
add_subdirectory(mobipocket)
|
28
generators/mobipocket/CMakeLists.txt
Normal file
28
generators/mobipocket/CMakeLists.txt
Normal file
|
@ -0,0 +1,28 @@
|
|||
find_package(KDE4 REQUIRED)
|
||||
find_package(Okular REQUIRED)
|
||||
include_directories(${KDE4_INCLUDES} ${QT_INCLUDES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${OKULAR_INCLUDE_DIR}
|
||||
${PROJECT_SOURCE_DIR}/../libs/mobipocket
|
||||
)
|
||||
|
||||
########### next target ###############
|
||||
|
||||
set(okularGenerator_mobi_PART_SRCS
|
||||
${PROJECT_SOURCE_DIR}/../libs/mobipocket/mobipocket.cpp
|
||||
${PROJECT_SOURCE_DIR}/../libs/mobipocket/decompressor.cpp
|
||||
mobidocument.cpp
|
||||
generator_mobi.cpp
|
||||
converter.cpp
|
||||
)
|
||||
|
||||
kde4_add_plugin(okularGenerator_mobi ${okularGenerator_mobi_PART_SRCS})
|
||||
|
||||
target_link_libraries(okularGenerator_mobi ${OKULAR_LIBRARIES} ${mobi_LIBRARIES} ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY})
|
||||
|
||||
install(TARGETS okularGenerator_mobi DESTINATION ${PLUGIN_INSTALL_DIR})
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install( FILES libokularGenerator_mobi.desktop okularMobi.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
|
||||
install( FILES okularApplication_mobi.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} )
|
107
generators/mobipocket/converter.cpp
Normal file
107
generators/mobipocket/converter.cpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Jakub Stachowski <qbast@go2.pl> *
|
||||
* *
|
||||
* 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 "converter.h"
|
||||
|
||||
#include <QtGui/QAbstractTextDocumentLayout>
|
||||
#include <QtGui/QTextDocument>
|
||||
#include <QtGui/QTextBlock>
|
||||
#include <QtGui/QTextFrame>
|
||||
#include <QtGui/QTextDocumentFragment>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QFile>
|
||||
#include "mobipocket.h"
|
||||
|
||||
#include <klocale.h>
|
||||
#include <okular/core/action.h>
|
||||
|
||||
using namespace Mobi;
|
||||
|
||||
Converter::Converter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Converter::~Converter()
|
||||
{
|
||||
}
|
||||
|
||||
void Converter::handleMetadata(const QMap<Mobipocket::Document::MetaKey,QString> metadata)
|
||||
{
|
||||
QMapIterator<Mobipocket::Document::MetaKey,QString> it(metadata);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
switch (it.key()) {
|
||||
case Mobipocket::Document::Title: addMetaData(Okular::DocumentInfo::Title, it.value()); break;
|
||||
case Mobipocket::Document::Author: addMetaData(Okular::DocumentInfo::Author, it.value()); break;
|
||||
case Mobipocket::Document::Description: addMetaData(Okular::DocumentInfo::Description, it.value()); break;
|
||||
case Mobipocket::Document::Subject: addMetaData(Okular::DocumentInfo::Subject, it.value()); break;
|
||||
case Mobipocket::Document::Copyright: addMetaData(Okular::DocumentInfo::Copyright, it.value()); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QTextDocument* Converter::convert( const QString &fileName )
|
||||
{
|
||||
MobiDocument* newDocument=new MobiDocument(fileName);
|
||||
if (!newDocument->mobi()->isValid()) {
|
||||
emit error(i18n("Error while opening the Mobipocket document."), -1);
|
||||
delete newDocument;
|
||||
return NULL;
|
||||
}
|
||||
if (newDocument->mobi()->hasDRM()) {
|
||||
emit error(i18n("This book is protected by DRM and can be displayed only on designated device"), -1);
|
||||
delete newDocument;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
handleMetadata(newDocument->mobi()->metadata());
|
||||
newDocument->setPageSize(QSizeF(600, 800));
|
||||
|
||||
QTextFrameFormat frameFormat;
|
||||
frameFormat.setMargin( 20 );
|
||||
QTextFrame *rootFrame = newDocument->rootFrame();
|
||||
rootFrame->setFrameFormat( frameFormat );
|
||||
QMap<QString,QPair<int,int> > links;
|
||||
QMap<QString,QTextBlock> targets;
|
||||
|
||||
// go over whole document and add all <a> tags to links or targets map
|
||||
for (QTextBlock it = newDocument->begin(); it != newDocument->end(); it = it.next())
|
||||
for (QTextBlock::iterator fit=it.begin(); !fit.atEnd(); ++fit) {
|
||||
QTextFragment frag=fit.fragment();
|
||||
QTextCharFormat format=frag.charFormat();
|
||||
if (!format.isAnchor()) continue;
|
||||
//link
|
||||
if (!format.anchorHref().isEmpty()) links[format.anchorHref()]=
|
||||
QPair<int,int>(frag.position(), frag.position()+frag.length());
|
||||
if (!format.anchorNames().isEmpty()) {
|
||||
// link targets
|
||||
Q_FOREACH(const QString& name, format.anchorNames())
|
||||
targets['#'+name]=it;
|
||||
}
|
||||
}
|
||||
|
||||
// create link actions
|
||||
QMapIterator<QString,QPair<int,int> > it(links);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
QUrl u(it.key());
|
||||
// external or internal link
|
||||
if (!u.isRelative()) emit addAction(new Okular::BrowseAction(it.key()), it.value().first, it.value().second);
|
||||
else {
|
||||
// is there valid target?
|
||||
if (!targets.contains( it.key() ) || !targets[it.key()].isValid()) continue;
|
||||
emit addAction(new Okular::GotoAction(QString(), calculateViewport( newDocument, targets[it.key()] )),
|
||||
it.value().first, it.value().second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return newDocument;
|
||||
}
|
32
generators/mobipocket/converter.h
Normal file
32
generators/mobipocket/converter.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Jakub Stachowski <qbast@go2.pl> *
|
||||
* *
|
||||
* 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 MOBI_CONVERTER_H
|
||||
#define MOBI_CONVERTER_H
|
||||
|
||||
#include <okular/core/textdocumentgenerator.h>
|
||||
#include <okular/core/document.h>
|
||||
|
||||
#include "mobidocument.h"
|
||||
#include "mobipocket.h"
|
||||
|
||||
|
||||
namespace Mobi {
|
||||
class Converter : public Okular::TextDocumentConverter
|
||||
{
|
||||
public:
|
||||
Converter();
|
||||
~Converter();
|
||||
|
||||
virtual QTextDocument *convert( const QString &fileName );
|
||||
private:
|
||||
void handleMetadata(const QMap<Mobipocket::Document::MetaKey, QString> metadata);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
37
generators/mobipocket/generator_mobi.cpp
Normal file
37
generators/mobipocket/generator_mobi.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Ely Levy <elylevy@cs.huji.ac.il> *
|
||||
* *
|
||||
* 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 "generator_mobi.h"
|
||||
|
||||
#include "converter.h"
|
||||
|
||||
#include <kaboutdata.h>
|
||||
|
||||
static KAboutData createAboutData()
|
||||
{
|
||||
KAboutData aboutData(
|
||||
"okular_mobi",
|
||||
"okular_mobi",
|
||||
ki18n("Mobipocket Backend"),
|
||||
"0.1",
|
||||
ki18n("A mobipocket backend"),
|
||||
KAboutData::License_GPL,
|
||||
ki18n("© 2008-2009 Jakub Stachowski")
|
||||
);
|
||||
aboutData.addAuthor(ki18n("Jakub Stachowski"), KLocalizedString(),
|
||||
"qbast@go2.pl");
|
||||
|
||||
return aboutData;
|
||||
}
|
||||
|
||||
OKULAR_EXPORT_PLUGIN( MobiGenerator, createAboutData() )
|
||||
|
||||
MobiGenerator::MobiGenerator( QObject *parent, const QVariantList &args )
|
||||
: Okular::TextDocumentGenerator( new Mobi::Converter, parent, args )
|
||||
{
|
||||
}
|
20
generators/mobipocket/generator_mobi.h
Normal file
20
generators/mobipocket/generator_mobi.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Ely Levy <elylevy@cs.huji.ac.il> *
|
||||
* *
|
||||
* 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 OKULAR_GENERATOR_MOBI_H
|
||||
#define OKULAR_GENERATOR_MOBI_H
|
||||
#include <okular/core/textdocumentgenerator.h>
|
||||
|
||||
class MobiGenerator : public Okular::TextDocumentGenerator
|
||||
{
|
||||
public:
|
||||
MobiGenerator( QObject *parent, const QVariantList &args );
|
||||
~MobiGenerator() {}
|
||||
};
|
||||
|
||||
#endif
|
42
generators/mobipocket/libokularGenerator_mobi.desktop
Normal file
42
generators/mobipocket/libokularGenerator_mobi.desktop
Normal file
|
@ -0,0 +1,42 @@
|
|||
[Desktop Entry]
|
||||
Type=Service
|
||||
Name=Mobipocket document
|
||||
Name[el]=Έγγραφο Mobipocket
|
||||
Name[es]=Documento Mobipocket
|
||||
Name[et]=Mobipocketi dokument
|
||||
Name[fr]=Document mobipocket
|
||||
Name[ga]=Cáipéis Mobipocket
|
||||
Name[ja]=Mobipocket 文書
|
||||
Name[nds]=Mobipocket-Dokment
|
||||
Name[nl]=Mobipocket-document
|
||||
Name[pt]=Documento Mobipocket
|
||||
Name[pt_BR]=Documento Mobipocket
|
||||
Name[sv]=Mobipocket-dokument
|
||||
Name[tr]=Mobipocket belgesi
|
||||
Name[uk]=Документ Mobipocket
|
||||
Name[x-test]=xxMobipocket documentxx
|
||||
Name[zh_CN]=Mobipocket 文档
|
||||
Name[zh_TW]=Mobipocket 文件
|
||||
Comment=Mobipocket backend for Okular
|
||||
Comment[el]=Σύστημα υποστήριξης Mobipocket για το Okular
|
||||
Comment[es]=Motor de Mobipocket para Okular
|
||||
Comment[et]=Okulari Mobipocketi taustaprogramm
|
||||
Comment[fr]=Moteur Mobipocket pour Okular
|
||||
Comment[ga]=Inneall Mobipocket le haghaidh Okular
|
||||
Comment[ja]=Okular の Mobipocket 用バックエンド
|
||||
Comment[nds]=Mobipocket-Hülppropgramm för Okular
|
||||
Comment[nl]=Mobipocket-backend voor Okular
|
||||
Comment[pt]=Interface do Mobipocket para o Okular
|
||||
Comment[pt_BR]=Infraestrutura Mobipocket para o Okular
|
||||
Comment[sv]=Mobipocket-gränssnitt för Okular
|
||||
Comment[tr]=Okular için Mobipocket arka ucu
|
||||
Comment[uk]=Сервер Mobipocket для Okular
|
||||
Comment[x-test]=xxMobipocket backend for Okularxx
|
||||
Comment[zh_CN]=Okular Mobipocket 后端
|
||||
Comment[zh_TW]=Okular 的 Mobipocket 後端介面
|
||||
X-KDE-ServiceTypes=okular/Generator
|
||||
MimeType=application/x-mobipocket-ebook;
|
||||
X-KDE-Library=okularGenerator_mobi
|
||||
X-KDE-Priority=1
|
||||
X-KDE-okularAPIVersion=1
|
||||
X-KDE-okularHasInternalSettings=false
|
92
generators/mobipocket/mobidocument.cpp
Normal file
92
generators/mobipocket/mobidocument.cpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Jakub Stachowski <qbast@go2.pl> *
|
||||
* *
|
||||
* 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 "mobidocument.h"
|
||||
#include "mobipocket.h"
|
||||
#include "qfilestream.h"
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QRegExp>
|
||||
#include <kdebug.h>
|
||||
|
||||
using namespace Mobi;
|
||||
|
||||
MobiDocument::MobiDocument(const QString &fileName) : QTextDocument()
|
||||
{
|
||||
file = new Mobipocket::QFileStream(fileName);
|
||||
doc = new Mobipocket::Document(file);
|
||||
if (doc->isValid()) setHtml(fixMobiMarkup(doc->text()));
|
||||
}
|
||||
|
||||
MobiDocument::~MobiDocument()
|
||||
{
|
||||
delete doc;
|
||||
delete file;
|
||||
}
|
||||
|
||||
QVariant MobiDocument::loadResource(int type, const QUrl &name)
|
||||
{
|
||||
if (type!=QTextDocument::ImageResource || name.scheme()!=QString("pdbrec")) return QVariant();
|
||||
bool ok;
|
||||
quint16 recnum=name.path().mid(1).toUShort(&ok);
|
||||
if (!ok || recnum>=doc->imageCount()) return QVariant();
|
||||
|
||||
QVariant resource;
|
||||
resource.setValue(doc->getImage(recnum-1));
|
||||
addResource(type, name, resource);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
// starting from 'pos', find position in the string that is not inside a tag
|
||||
int outsideTag(const QString& data, int pos)
|
||||
{
|
||||
for (int i=pos-1;i>=0;i--) {
|
||||
if (data[i]=='>') return pos;
|
||||
if (data[i]=='<') return i;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
QString MobiDocument::fixMobiMarkup(const QString& data)
|
||||
{
|
||||
QString ret=data;
|
||||
QMap<int,QString> anchorPositions;
|
||||
static QRegExp anchors("<a(?: href=\"[^\"]*\"){0,1}[\\s]+filepos=['\"]{0,1}([\\d]+)[\"']{0,1}", Qt::CaseInsensitive);
|
||||
int pos=0;
|
||||
|
||||
// find all link destinations
|
||||
while ( (pos=anchors.indexIn( data, pos ))!=-1) {
|
||||
int filepos=anchors.cap( 1 ).toUInt( );
|
||||
if (filepos) anchorPositions[filepos]=anchors.cap(1);
|
||||
pos+=anchors.matchedLength();
|
||||
}
|
||||
|
||||
// put HTML anchors in all link destinations
|
||||
int offset=0;
|
||||
QMapIterator<int,QString> it(anchorPositions);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
// link pointing outside the document, ignore
|
||||
if ( (it.key()+offset) >= ret.size()) continue;
|
||||
int fixedpos=outsideTag(ret, it.key()+offset);
|
||||
ret.insert(fixedpos,QString("<a name=\"")+it.value()+QString("\"> </a>"));
|
||||
// inserting anchor shifts all offsets after the anchor
|
||||
offset+=21+it.value().size();
|
||||
}
|
||||
|
||||
// replace links referencing filepos with normal internal links
|
||||
ret.replace(anchors,"<a href=\"#\\1\"");
|
||||
// Mobipocket uses strange variang of IMG tags: <img recindex="3232"> where recindex is number of
|
||||
// record containing image
|
||||
static QRegExp imgs("<img.*recindex=\"([\\d]*)\".*>", Qt::CaseInsensitive);
|
||||
|
||||
imgs.setMinimal(true);
|
||||
ret.replace(imgs,"<img src=\"pdbrec:/\\1\">");
|
||||
ret.replace("<mbp:pagebreak/>","<p style=\"page-break-after:always\"></p>");
|
||||
return ret;
|
||||
}
|
42
generators/mobipocket/mobidocument.h
Normal file
42
generators/mobipocket/mobidocument.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Jakub Stachowski <qbast@go2.pl> *
|
||||
* *
|
||||
* 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 MOBI_DOCUMENT_H
|
||||
#define MOBI_DOCUMENT_H
|
||||
|
||||
#include <QTextDocument>
|
||||
#include <QUrl>
|
||||
#include <QVariant>
|
||||
|
||||
class QFile;
|
||||
namespace Mobipocket {
|
||||
class Document;
|
||||
class QFileStream;
|
||||
}
|
||||
|
||||
namespace Mobi {
|
||||
|
||||
class MobiDocument : public QTextDocument {
|
||||
|
||||
public:
|
||||
MobiDocument(const QString &fileName);
|
||||
~MobiDocument();
|
||||
|
||||
Mobipocket::Document* mobi() const { return doc; }
|
||||
|
||||
protected:
|
||||
virtual QVariant loadResource(int type, const QUrl &name);
|
||||
|
||||
private:
|
||||
QString fixMobiMarkup(const QString& data);
|
||||
Mobipocket::Document *doc;
|
||||
Mobipocket::QFileStream* file;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
28
generators/mobipocket/okularApplication_mobi.desktop
Normal file
28
generators/mobipocket/okularApplication_mobi.desktop
Normal file
|
@ -0,0 +1,28 @@
|
|||
[Desktop Entry]
|
||||
MimeType=application/x-mobipocket-ebook;
|
||||
Terminal=false
|
||||
Name=Okular
|
||||
Name[x-test]=xxOkularxx
|
||||
GenericName=Document Viewer
|
||||
GenericName[el]=Προβολέας εγγράφων
|
||||
GenericName[es]=Visor de documentos
|
||||
GenericName[et]=Dokumentide näitaja
|
||||
GenericName[fr]=Visonneuse de document
|
||||
GenericName[ga]=Amharcán Cáipéisí
|
||||
GenericName[ja]=文書ビューア
|
||||
GenericName[nds]=Dokmentkieker
|
||||
GenericName[nl]=Documentviewer
|
||||
GenericName[pt]=Visualizador de Documentos
|
||||
GenericName[pt_BR]=Visualizador de documentos
|
||||
GenericName[sv]=Dokumentvisning
|
||||
GenericName[tr]=Belge Gösterici
|
||||
GenericName[uk]=Переглядач документів
|
||||
GenericName[x-test]=xxDocument Viewerxx
|
||||
GenericName[zh_CN]=文档查看器
|
||||
GenericName[zh_TW]=文件檢視器
|
||||
Exec=okular %U %i -caption "%c"
|
||||
Icon=okular
|
||||
Type=Application
|
||||
InitialPreference=1
|
||||
Categories=Qt;KDE;Graphics;Viewer;
|
||||
NoDisplay=true
|
8
generators/mobipocket/okularMobi.desktop
Normal file
8
generators/mobipocket/okularMobi.desktop
Normal file
|
@ -0,0 +1,8 @@
|
|||
[Desktop Entry]
|
||||
Icon=okular
|
||||
Name=Okular
|
||||
Name[x-test]=xxOkularxx
|
||||
X-KDE-ServiceTypes=KParts/ReadOnlyPart
|
||||
X-KDE-Library=okularpart
|
||||
Type=Service
|
||||
MimeType=application/x-mobipocket-ebook;
|
Loading…
Reference in a new issue