diff --git a/core/document.cpp b/core/document.cpp index 4cedddb36..91dd0b50e 100644 --- a/core/document.cpp +++ b/core/document.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * Copyright (C) 2004-2005 by Enrico Ros * - * Copyright (C) 2004-2007 by Albert Astals Cid * + * Copyright (C) 2004-2008 by Albert Astals Cid * * * * 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 * @@ -3011,6 +3011,18 @@ void Document::unregisterView( View *view ) d->m_views.remove( view ); } +QByteArray Document::fontData(const FontInfo &font) const +{ + QByteArray result; + + if (d->m_generator) + { + QMetaObject::invokeMethod(d->m_generator, "requestFontData", Qt::DirectConnection, Q_ARG(Okular::FontInfo, font), Q_ARG(QByteArray *, &result)); + } + + return result; +} + void DocumentPrivate::requestDone( PixmapRequest * req ) { if ( !req ) diff --git a/core/document.h b/core/document.h index 83df57f1c..763d2c126 100644 --- a/core/document.h +++ b/core/document.h @@ -1,6 +1,6 @@ /*************************************************************************** * Copyright (C) 2004-2005 by Enrico Ros * - * Copyright (C) 2004-2007 by Albert Astals Cid * + * Copyright (C) 2004-2008 by Albert Astals Cid * * * * 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 * @@ -551,6 +551,13 @@ class OKULAR_EXPORT Document : public QObject */ void unregisterView( View *view ); + /** + * Gets the font data for the given font + * + * @since 0.8 (KDE 4.2) + */ + QByteArray fontData(const FontInfo &font) const; + public Q_SLOTS: /** * This slot is called whenever the user changes the @p rotation of diff --git a/core/fontinfo.cpp b/core/fontinfo.cpp index 82c398f53..59ea79f79 100644 --- a/core/fontinfo.cpp +++ b/core/fontinfo.cpp @@ -10,6 +10,8 @@ // local includes #include "fontinfo.h" +#include + using namespace Okular; class Okular::FontInfoPrivate @@ -17,7 +19,8 @@ class Okular::FontInfoPrivate { public: FontInfoPrivate() - : type( FontInfo::Unknown ), embedType( FontInfo::NotEmbedded ) + : type( FontInfo::Unknown ), embedType( FontInfo::NotEmbedded ), + canBeExtracted( false ) { } @@ -26,13 +29,17 @@ class Okular::FontInfoPrivate return name == rhs.name && type == rhs.type && embedType == rhs.embedType && - file == rhs.file; + file == rhs.file && + canBeExtracted == rhs.canBeExtracted && + nativeId == rhs.nativeId; } QString name; FontInfo::FontType type; FontInfo::EmbedType embedType; + bool canBeExtracted; QString file; + QVariant nativeId; }; @@ -90,6 +97,26 @@ void FontInfo::setFile( const QString& file ) d->file = file; } +bool FontInfo::canBeExtracted() const +{ + return d->canBeExtracted; +} + +void FontInfo::setCanBeExtracted(bool extractable) +{ + d->canBeExtracted = extractable; +} + +void FontInfo::setNativeId( const QVariant &id ) +{ + d->nativeId = id; +} + +QVariant FontInfo::nativeId() const +{ + return d->nativeId; +} + bool FontInfo::operator==( const FontInfo &fi ) const { return *d == *fi.d; diff --git a/core/fontinfo.h b/core/fontinfo.h index 0bdd2a1b2..338ac4a95 100644 --- a/core/fontinfo.h +++ b/core/fontinfo.h @@ -105,6 +105,36 @@ class OKULAR_EXPORT FontInfo QString file() const; void setFile( const QString& file ); + /** + * In case of embedded fonts, returns if the font can be extracted into a QByteArray + * + * @since 0.8 (KDE 4.2) + */ + bool canBeExtracted() const; + + /** + * Sets if a font can be extracted or not. False by default + */ + void setCanBeExtracted( bool extractable ); + + /** + * Sets the "native" @p id of the font info. + * + * This is for use of the Generator, that can optionally store an + * handle (a pointer, an identifier, etc) of the "native" font + * object, if any. + * + * @since 0.8 (KDE 4.2) + */ + void setNativeId( const QVariant &id ); + + /** + * Returns the "native" id of the font info. + * + * @since 0.8 (KDE 4.2) + */ + QVariant nativeId() const; + FontInfo& operator=( const FontInfo &fi ); /** diff --git a/core/generator.cpp b/core/generator.cpp index 2415c64bf..3ea840112 100644 --- a/core/generator.cpp +++ b/core/generator.cpp @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (C) 2005 by Piotr Szymanski * + * Copyright (C) 2008 by Albert Astals Cid * * * * 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 * @@ -406,6 +407,10 @@ void Generator::updatePageBoundingBox( int page, const NormalizedRect & bounding d->m_document->setPageBoundingBox( page, boundingBox ); } +void Generator::requestFontData(const Okular::FontInfo & /*font*/, QByteArray * /*data*/) +{ + +} PixmapRequest::PixmapRequest( int id, int pageNumber, int width, int height, int priority, bool asynchronous ) : d( new PixmapRequestPrivate ) diff --git a/core/generator.h b/core/generator.h index 33ddef9cb..9e314ceae 100644 --- a/core/generator.h +++ b/core/generator.h @@ -1,6 +1,7 @@ /*************************************************************************** * Copyright (C) 2004-5 by Enrico Ros * * Copyright (C) 2005 by Piotr Szymanski * + * Copyright (C) 2008 by Albert Astals Cid * * * * 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 * @@ -30,6 +31,7 @@ K_PLUGIN_FACTORY( classname ## Factory, registerPlugin< classname >(); ) \ K_EXPORT_PLUGIN( classname ## Factory( aboutdata ) ) +class QByteArray; class QMutex; class QPrinter; class QPrintDialog; @@ -43,6 +45,7 @@ class DocumentInfo; class DocumentSynopsis; class EmbeddedFile; class ExportFormatPrivate; +class FontInfo; class GeneratorPrivate; class Page; class PixmapRequest; @@ -448,6 +451,14 @@ class OKULAR_EXPORT Generator : public QObject */ void updatePageBoundingBox( int page, const NormalizedRect & boundingBox ); + protected Q_SLOTS: + /** + * Gets the font data for the given font + * + * @since 0.8 (KDE 4.1) + */ + void requestFontData(const Okular::FontInfo &font, QByteArray *data); + protected: /// @cond PRIVATE Generator( GeneratorPrivate &dd, QObject *parent, const QVariantList &args ); diff --git a/generators/poppler/generator_pdf.cpp b/generators/poppler/generator_pdf.cpp index 81479ecb1..bd49c1be4 100644 --- a/generators/poppler/generator_pdf.cpp +++ b/generators/poppler/generator_pdf.cpp @@ -45,6 +45,10 @@ #include "formfields.h" #include "popplerembeddedfile.h" +#ifdef HAVE_POPPLER_0_9 +Q_DECLARE_METATYPE(Poppler::FontInfo) +#endif + static const int PDFDebug = 4710; class PDFOptionsPage : public QWidget @@ -630,6 +634,13 @@ Okular::FontInfo::List PDFGenerator::fontsForPage( int page ) of.setType( convertPopplerFontInfoTypeToOkularFontInfoType( font.type() ) ); of.setEmbedType( embedTypeForPopplerFontInfo( font) ); of.setFile( font.file() ); +#ifdef HAVE_POPPLER_0_9 + of.setCanBeExtracted( of.embedType() != Okular::FontInfo::NotEmbedded ); + + QVariant nativeId; + nativeId.setValue( font ); + of.setNativeId( nativeId ); +#endif list.append( of ); } @@ -805,6 +816,14 @@ Okular::TextPage* PDFGenerator::textPage( Okular::Page *page ) return tp; } +void PDFGenerator::requestFontData(const Okular::FontInfo &font, QByteArray *data) +{ +#ifdef HAVE_POPPLER_0_9 + Poppler::FontInfo fi = font.nativeId().value(); + *data = pdfdoc->fontData(fi); +#endif +} + bool PDFGenerator::print( QPrinter& printer ) { // Get the real page size to pass to the ps generator diff --git a/generators/poppler/generator_pdf.h b/generators/poppler/generator_pdf.h index 8d5dea773..2dc0fd415 100644 --- a/generators/poppler/generator_pdf.h +++ b/generators/poppler/generator_pdf.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2004 by Albert Astals Cid * + * Copyright (C) 2004-2008 by Albert Astals Cid * * Copyright (C) 2004 by Enrico Ros * * * * This program is free software; you can redistribute it and/or modify * @@ -99,6 +99,9 @@ class PDFGenerator : public Okular::Generator, public Okular::ConfigInterface, p bool doCloseDocument(); Okular::TextPage* textPage( Okular::Page *page ); + protected slots: + void requestFontData(const Okular::FontInfo &font, QByteArray *data); + private slots: // (async related) receive data from the generator thread void threadFinished(); @@ -177,3 +180,5 @@ class PDFPixmapGeneratorThread : public QThread }; #endif + +/* kate: replace-tabs on; indent-width 4; */ diff --git a/ui/propertiesdialog.cpp b/ui/propertiesdialog.cpp index 0b1875d77..bf191f261 100644 --- a/ui/propertiesdialog.cpp +++ b/ui/propertiesdialog.cpp @@ -10,15 +10,19 @@ #include "propertiesdialog.h" // qt/kde includes +#include #include #include #include +#include #include #include #include #include +#include #include #include +#include #include #include @@ -26,6 +30,9 @@ #include "core/document.h" #include "core/fontinfo.h" +static const int IsExtractableRole = Qt::UserRole; +static const int FontInfoRole = Qt::UserRole + 1; + PropertiesDialog::PropertiesDialog(QWidget *parent, Okular::Document *doc) : KPageDialog( parent ), m_document( doc ), m_fontPage( 0 ), m_fontModel( 0 ), m_fontInfo( 0 ), m_fontProgressBar( 0 ), @@ -101,6 +108,8 @@ PropertiesDialog::PropertiesDialog(QWidget *parent, Okular::Document *doc) page2Layout->setSpacing(spacingHint()); // add a tree view QTreeView *view = new QTreeView(page2); + view->setContextMenuPolicy(Qt::CustomContextMenu); + connect(view, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(showFontsMenu(const QPoint &))); page2Layout->addWidget(view); view->setRootIsDecorated(false); view->setAlternatingRowColors(true); @@ -173,6 +182,40 @@ void PropertiesDialog::reallyStartFontReading() m_document->startFontReading(); } +void PropertiesDialog::showFontsMenu(const QPoint &pos) +{ + QTreeView *view = static_cast(sender()); + QModelIndex index = view->indexAt(pos); + if (index.data(IsExtractableRole).toBool()) + { + QMenu *menu = new QMenu(this); + menu->addAction( i18nc("@action:inmenu", "&Extract Font") ); + QAction *result = menu->exec(view->viewport()->mapToGlobal(pos)); + if (result) + { + Okular::FontInfo fi = index.data(FontInfoRole).value(); + const QString caption = i18n( "Where do you want to save %1?", fi.name() ); + const QString path = KFileDialog::getSaveFileName( fi.name(), QString(), this, caption ); + if ( path.isEmpty() ) + return; + + QFile f( path ); + if ( !f.exists() || KMessageBox::warningContinueCancel( this, i18n( "A file named \"%1\" already exists. Are you sure you want to overwrite it?", path ), QString(), KGuiItem( i18nc( "@action:button", "&Overwrite" ) ) ) == KMessageBox::Continue ) + { + if ( f.open( QIODevice::WriteOnly ) ) + { + f.write( m_document->fontData(fi) ); + f.close(); + } + else + { + KMessageBox::error( this, i18n( "Could not open \"%1\" for writing. File was not saved.", path ) ); + } + } + } + } +} + FontsListModel::FontsListModel( QObject * parent ) : QAbstractTableModel( parent ) { @@ -311,6 +354,16 @@ QVariant FontsListModel::data( const QModelIndex &index, int role ) const return tooltip; break; } + case IsExtractableRole: + { + return m_fonts.at( index.row() ).canBeExtracted(); + } + case FontInfoRole: + { + QVariant v; + v.setValue( m_fonts.at( index.row() ) ); + return v; + } } return QVariant(); @@ -343,3 +396,5 @@ int FontsListModel::rowCount( const QModelIndex &parent ) const } #include "propertiesdialog.moc" + +/* kate: replace-tabs on; indent-width 4; */ diff --git a/ui/propertiesdialog.h b/ui/propertiesdialog.h index e1be9bf53..59ff2180f 100644 --- a/ui/propertiesdialog.h +++ b/ui/propertiesdialog.h @@ -30,7 +30,7 @@ class PropertiesDialog : public KPageDialog Q_OBJECT public: - PropertiesDialog( QWidget *parent, Okular::Document *doc ); + PropertiesDialog( QWidget *parent, Okular::Document *doc ); virtual ~PropertiesDialog(); private slots: @@ -38,6 +38,7 @@ class PropertiesDialog : public KPageDialog void slotFontReadingProgress( int page ); void slotFontReadingEnded(); void reallyStartFontReading(); + void showFontsMenu(const QPoint &pos); private: Okular::Document * m_document; @@ -71,3 +72,5 @@ class FontsListModel }; #endif + +/* kate: replace-tabs on; indent-width 4; */