Commit 1b1ed945 authored by John Layt's avatar John Layt

Enable Okular printing features:

* Add FilePrinter class to enable printing via postscript files
* DJVU, PDF, and PS backends print FilePrinter
* All backends enable printing of bookmarked pages
* Print and Print Preview actions enabled/disabled depending on backends
  printing ability

Note that FilePrinter only works on *NIX platforms with Cups, lpr, or lp.



svn path=/trunk/KDE/kdegraphics/okular/; revision=741990
parent 2153ec5e
......@@ -43,6 +43,7 @@ set(okularcore_SRCS
core/textdocumentgenerator.cpp
core/textpage.cpp
core/utils.cpp
core/fileprinter.cpp
)
install( FILES
......@@ -64,6 +65,7 @@ install( FILES
core/textdocumentgenerator.h
core/textpage.h
core/utils.h
core/fileprinter.h
DESTINATION ${INCLUDE_INSTALL_DIR}/okular/core )
install( FILES
......
......@@ -28,6 +28,7 @@
#include <QtGui/QApplication>
#include <QtGui/QLabel>
#include <QtGui/QPrinter>
#include <QtGui/QPrintDialog>
#include <kaboutdata.h>
#include <kauthorized.h>
......@@ -2186,6 +2187,68 @@ BookmarkManager * Document::bookmarkManager() const
return d->m_bookmarkManager;
}
QList<int> Document::bookmarkedPageList() const
{
QList<int> list;
uint docPages = pages();
//pages are 0-indexed internally, but 1-indexed externally
for ( uint i = 0; i < docPages; i++ )
{
if ( bookmarkManager()->isBookmarked( i ) )
{
list << i + 1;
}
}
return list;
}
QString Document::bookmarkedPageRange() const
{
// Code formerly in Part::slotPrint()
// range detecting
QString range;
uint docPages = pages();
int startId = -1;
int endId = -1;
for ( uint i = 0; i < docPages; ++i )
{
if ( bookmarkManager()->isBookmarked( i ) )
{
if ( startId < 0 )
startId = i;
if ( endId < 0 )
endId = startId;
else
++endId;
}
else if ( startId >= 0 && endId >= 0 )
{
if ( !range.isEmpty() )
range += ',';
if ( endId - startId > 0 )
range += QString( "%1-%2" ).arg( startId + 1 ).arg( endId + 1 );
else
range += QString::number( startId + 1 );
startId = -1;
endId = -1;
}
}
if ( startId >= 0 && endId >= 0 )
{
if ( !range.isEmpty() )
range += ',';
if ( endId - startId > 0 )
range += QString( "%1-%2" ).arg( startId + 1 ).arg( endId + 1 );
else
range += QString::number( startId + 1 );
}
return range;
}
void Document::processAction( const Action * action )
{
if ( !action )
......@@ -2396,6 +2459,33 @@ void Document::processSourceReference( const SourceReference * ref )
QProcess::startDetached( p );
}
Document::PrintingType Document::printingSupport() const
{
if ( d->m_generator )
{
if ( d->m_generator->hasFeature( Generator::PrintNative ) )
{
return NativePrinting;
}
#ifndef Q_OS_WIN
if ( d->m_generator->hasFeature( Generator::PrintPostscript ) )
{
return PostscriptPrinting;
}
#endif
}
return NoPrinting;
}
bool Document::supportsPrintToFile() const
{
return d->m_generator ? d->m_generator->hasFeature( Generator::PrintToFile ) : false;
}
bool Document::print( QPrinter &printer )
{
return d->m_generator ? d->m_generator->print( printer ) : false;
......
......@@ -24,6 +24,7 @@
#include <kmimetype.h>
class QPrinter;
class QPrintDialog;
class KComponentData;
class KBookmark;
class KConfigDialog;
......@@ -415,6 +416,16 @@ class OKULAR_EXPORT Document : public QObject
*/
void processAction( const Action *action );
/**
* Returns a list of the bookmarked.pages
*/
QList<int> bookmarkedPageList() const;
/**
* Returns the range of the bookmarked.pages
*/
QString bookmarkedPageRange() const;
/**
* Processes/Executes the given source @p reference.
*/
......@@ -425,6 +436,27 @@ class OKULAR_EXPORT Document : public QObject
*/
bool canConfigurePrinter() const;
/**
* What type of printing a document supports
*/
enum PrintingType
{
NoPrinting, ///< Printing Not Supported
NativePrinting, ///< Native Cross-Platform Printing
PostscriptPrinting ///< Postscript file printing
};
/**
* Returns what sort of printing the document supports:
* Native, Postscript, None
*/
PrintingType printingSupport() const;
/**
* Returns whether the document supports printing to both PDF and PS files.
*/
bool supportsPrintToFile() const;
/**
* Prints the document to the given @p printer.
*/
......
This diff is collapsed.
/***************************************************************************
* Copyright (C) 2007 by John Layt <john@layt.net> *
* *
* FilePrinterPreview based on KPrintPreview (originally LGPL) *
* Copyright (c) 2007 Alex Merry <huntedhacker@tiscali.co.uk> *
* *
* 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. *
***************************************************************************/
// This Class is a temporary addition to Okular for the duration of KDE 4.0.
// In KDE 4.1 this class will either be moved to kdelibs if still required,
// or replaced with a Qt 4.4 based solution.
#ifndef FILEPRINTER_H
#define FILEPRINTER_H
#include <QList>
#include <QString>
#include <kdialog.h>
#include <okular/core/okular_export.h>
class QPrinter;
class QSize;
namespace Okular {
class OKULAR_EXPORT FilePrinter
{
public:
/** Whether file(s) get deleted by the application or by the print system.
*
* You may need to chose system deletion if your temp file clean-up
* deletes the file before the print system is finished with it.
*/
enum FileDeletePolicy { ApplicationDeletesFiles, SystemDeletesFiles };
/** Whether pages to be printed are selected by the application or the print system.
*
* If application side, then the generated file will only contain those pages
* selected by the user, so FilePrinter will print all the pages in the file.
*
* If system side, then the file will contain all the pages in the document, and
* the print system will print the users selected print range from out of the file.
*
* Note system side only works in CUPS, not LPR.
*/
enum PageSelectPolicy { ApplicationSelectsPages, SystemSelectsPages };
/** Print a file using the settings in QPrinter
*
* Only supports CUPS and LPR on *NIX. Page Range only supported in CUPS.
* Most settings unsupported by LPR, some settings unsupported by CUPS.
*
* @param printer the print settings to use
* @param file the file to print
* @param fileDeletePolicy if the application or system deletes the file
* @param pageSelectPolicy if the application or system selects the pages to print
* @param pageRange page range to print if SystemSlectsPages and user chooses Selection in Print Dialog
*
* @returns Returns exit code:
* -9 if lpr not found
* -8 if empty file name
* -7 if unable to find file
* -6 if invalid printer state
* -2 if the KProcess could not be started
* -1 if the KProcess crashed
* otherwise the KProcess exit code
*/
static int printFile( QPrinter &printer, const QString file,
FileDeletePolicy fileDeletePolicy = FilePrinter::ApplicationDeletesFiles,
PageSelectPolicy pageSelectPolicy = FilePrinter::ApplicationSelectsPages,
const QString &pageRange = QString() );
/** Print a list of files using the settings in QPrinter
*
* Only supports CUPS and LPR on *NIX.
* Most settings unsupported by LPR, some settings unsupported by CUPS.
*
* @param printer the print settings to use
* @param fileList the files to print
* @param fileDeletePolicy if the application or system deletes the file
*
* @returns Returns exit code:
* -9 if lpr not found
* -8 if empty file list
* -7 if unable to find a file
* -6 if invalid printer state
* -2 if the KProcess could not be started
* -1 if the KProcess crashed
* otherwise the KProcess exit code
*/
static int printFiles( QPrinter &printer, const QStringList &fileList,
FileDeletePolicy fileDeletePolicy = FilePrinter::ApplicationDeletesFiles );
/** Return the list of pages selected by the user in the Print Dialog
*
* @param printer the print settings to use
* @param lastPage the last page number, needed if AllPages option is selected
* @param selectedPageList list of pages to use if Selection option is selected
* @returns Returns list of pages to print
*/
static QList<int> pageList( QPrinter &printer, int lastPage, const QList<int> &selectedPageList );
/** Return the range of pages selected by the user in the Print Dialog
*
* @param printer the print settings to use
* @param lastPage the last page number, needed if AllPages option is selected
* @param selectedPageList list of pages to use if Selection option is selected
* @returns Returns range of pages to print
*/
static QString pageRange( QPrinter &printer, int lastPage, const QList<int> &selectedPageList );
/** convert a Page List into a Page Range
*
* @param pageList list of pages to convert
* @returns Returns equivalent page range
*/
static QString pageListToPageRange( const QList<int> &pageList );
/** Return if CUPS Print System is available on this system
*
* @returns Returns true if CUPS available
*/
static bool cupsAvailable();
/** Returns the postscript standard page size
*
* @returns Returns paper size in ps points
*/
static QSize psPaperSize( QPrinter &printer );
protected:
bool detectCupsService();
bool detectCupsConfig();
int doPrintFiles( QPrinter &printer, const QStringList fileList,
FileDeletePolicy fileDeletePolicy, PageSelectPolicy pageSelectPolicy,
const QString &pageRange );
QStringList printArguments( QPrinter &printer,
FileDeletePolicy fileDeletePolicy, PageSelectPolicy pageSelectPolicy,
bool useCupsOptions, const QString &pageRange, const QString &version );
QStringList destination( QPrinter &printer, const QString &version );
QStringList copies( QPrinter &printer, const QString &version );
QStringList jobname( QPrinter &printer, const QString &version );
QStringList deleteFile( QPrinter &printer, FileDeletePolicy fileDeletePolicy,
const QString &version );
QStringList pages( QPrinter &printer, PageSelectPolicy pageSelectPolicy,
const QString &pageRange, bool useCupsOptions, const QString &version );
QStringList cupsOptions( QPrinter &printer );
QStringList optionMedia( QPrinter &printer );
QString mediaPageSize( QPrinter &printer );
QString mediaPaperSource( QPrinter &printer );
QStringList optionOrientation( QPrinter &printer );
QStringList optionDoubleSidedPrinting( QPrinter &printer );
QStringList optionPageOrder( QPrinter &printer );
QStringList optionCollateCopies( QPrinter &printer );
};
// This code copied from KPrintPreview by Alex Merry, adapted to do PS files instead of PDF
class FilePrinterPreviewPrivate;
class OKULAR_EXPORT FilePrinterPreview : public KDialog
{
Q_OBJECT
public:
/**
* Create a Print Preview dialog for a given file.
*
* @param printer file to print preview
* @param parent pointer to the parent widget for the dialog
*/
explicit FilePrinterPreview( const QString &filename, QWidget *parent = 0 );
virtual ~FilePrinterPreview();
protected:
void showEvent( QShowEvent *event );
private:
FilePrinterPreviewPrivate * const d;
};
}
#endif // FILEPRINTER_H
......@@ -33,6 +33,7 @@
class QMutex;
class QPrinter;
class QPrintDialog;
class KAboutData;
class KComponentData;
class KIcon;
......@@ -196,7 +197,10 @@ class OKULAR_EXPORT Generator : public QObject
TextExtraction, ///< Whether the Generator can extract text from the document in the form of TextPage's
ReadRawData, ///< Whether the Generator can read a document directly from its raw data.
FontInfo, ///< Whether the Generator can provide information about the fonts used in the document
PageSizes ///< Whether the Generator can change the size of the document pages.
PageSizes, ///< Whether the Generator can change the size of the document pages.
PrintNative, ///< Whether the Generator supports native cross-platform printing (QPainter-based).
PrintPostscript, ///< Whether the Generator supports postscript-based file printing.
PrintToFile ///< Whether the Generator supports export to PDF & PS through the Print Dialog
};
/**
......
......@@ -12,7 +12,9 @@
#include <QtGui/QPainter>
#include <QtGui/QPrinter>
#include <okular/core/document.h>
#include <okular/core/page.h>
#include <okular/core/fileprinter.h>
OKULAR_EXPORT_PLUGIN(ComicBookGenerator)
......@@ -20,6 +22,8 @@ ComicBookGenerator::ComicBookGenerator()
: Generator()
{
setFeature( Threaded );
setFeature( PrintNative );
setFeature( PrintToFile );
}
ComicBookGenerator::~ComicBookGenerator()
......@@ -70,19 +74,17 @@ bool ComicBookGenerator::print( QPrinter& printer )
{
QPainter p( &printer );
for ( int i = 0; i < mDocument.pages(); ++i ) {
QImage image = mDocument.pageImage( i );
uint left, top, right, bottom;
left = printer.paperRect().left() - printer.pageRect().left();
top = printer.paperRect().top() - printer.pageRect().top();
right = printer.paperRect().right() - printer.pageRect().right();
bottom = printer.paperRect().bottom() - printer.pageRect().bottom();
QList<int> pageList = Okular::FilePrinter::pageList( printer, document()->pages(),
document()->bookmarkedPageList() );
int pageWidth = printer.width() - right;
int pageHeight = printer.height() - bottom;
for ( int i = 0; i < pageList.count(); ++i ) {
if ( (image.width() > pageWidth) || (image.height() > pageHeight) )
image = image.scaled( pageWidth, pageHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
QImage image = mDocument.pageImage( pageList[i] - 1 );
if ( ( image.width() > printer.width() ) || ( image.height() > printer.height() ) )
image = image.scaled( printer.width(), printer.height(),
Qt::KeepAspectRatio, Qt::SmoothTransformation );
if ( i != 0 )
printer.newPage();
......
......@@ -16,6 +16,7 @@
#include <okular/core/page.h>
#include <okular/core/textpage.h>
#include <okular/core/utils.h>
#include <okular/core/fileprinter.h>
#include <qdom.h>
#include <qmutex.h>
......@@ -66,6 +67,7 @@ DjVuGenerator::DjVuGenerator()
{
setFeature( TextExtraction );
setFeature( Threaded );
setFeature( PrintPostscript );
m_djvu = new KDjVu();
......@@ -185,30 +187,31 @@ const Okular::DocumentSynopsis * DjVuGenerator::generateDocumentSynopsis()
bool DjVuGenerator::print( QPrinter& printer )
{
/* This printing method unsupported in QPrinter, looking for alternative.
QList<int> pageList;
if ( !printer.previewOnly() )
pageList = printer.pageList();
else
{
int pages = m_djvu->pages().count();
for( int i = 1; i <= pages; ++i )
pageList.push_back(i);
}
bool result = false;
// Create tempfile to write to
KTemporaryFile tf;
tf.setSuffix( ".ps" );
if ( !tf.open() )
return false;
QMutexLocker locker( userMutex() );
QList<int> pageList = Okular::FilePrinter::pageList( printer, m_djvu->pages().count(),
document()->bookmarkedPageList() );
if ( m_djvu->exportAsPostScript( &tf, pageList ) )
{
return printer.printFiles( QStringList( tf.fileName() ), false );
tf.setAutoRemove( false );
int ret = Okular::FilePrinter::printFile( printer, tf.fileName(),
Okular::FilePrinter::SystemDeletesFiles,
Okular::FilePrinter::ApplicationSelectsPages,
document()->bookmarkedPageRange() );
result = ( ret >=0 );
}
*/
return false;
tf.close();
return result;
}
QVariant DjVuGenerator::metaData( const QString &key, const QVariant &option ) const
......
......@@ -478,9 +478,13 @@ void DVIExportToPS::finished_impl(int exit_code)
{
if (printer_ && !output_name_.isEmpty()) {
const QFileInfo output(output_name_);
if (output.exists() && output.isReadable())
//Unsupported in Qt
//printer_->printFiles(QStringList(output_name_), true);
if (output.exists() && output.isReadable()) {
// I'm not 100% sure on this, think we still need to select pages in export to ps above
FilePrinter::printFile( printer_, output_name_,
FilePrinter::ApplicationDeletesFiles,
FilePrinter::ApplicationSelectsPages,
QString() );
}
}
#ifndef DVIEXPORT_USE_QPROCESS
......
......@@ -31,6 +31,8 @@ KIMGIOGenerator::KIMGIOGenerator()
{
setFeature( ReadRawData );
setFeature( Threaded );
setFeature( PrintNative );
setFeature( PrintToFile );
KAboutData *about = new KAboutData(
"okular_kimgio",
......@@ -122,18 +124,12 @@ bool KIMGIOGenerator::print( QPrinter& printer )
{
QPainter p( &printer );
uint left, top, right, bottom;
left = printer.paperRect().left() - printer.pageRect().left();
top = printer.paperRect().top() - printer.pageRect().top();
right = printer.paperRect().right() - printer.pageRect().right();
bottom = printer.paperRect().bottom() - printer.pageRect().bottom();
QImage image( m_img );
int pageWidth = printer.width() - right;
int pageHeight = printer.height() - bottom;
if ( ( image.width() > printer.width() ) || ( image.height() > printer.height() ) )
QImage image( m_img );
if ( (image.width() > pageWidth) || (image.height() > pageHeight) )
image = image.scaled( pageWidth, pageHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation );
image = image.scaled( printer.width(), printer.height(),
Qt::KeepAspectRatio, Qt::SmoothTransformation );
p.drawImage( 0, 0, image );
......
......@@ -37,6 +37,7 @@
#include <okular/core/sound.h>
#include <okular/core/sourcereference.h>
#include <okular/core/textpage.h>
#include <okular/core/fileprinter.h>
#include <config-okular-poppler.h>
......@@ -106,15 +107,14 @@ class PDFOptionsPage : public QWidget
layout->addStretch(1);
}
void getOptions( QMap<QString,QString>& opts, bool incldef = false )
bool printForceRaster()
{
Q_UNUSED(incldef);
opts[ "kde-okular-poppler-forceRaster" ] = QString::number( m_forceRaster->isChecked() );
return m_forceRaster->isChecked();
}
void setOptions( const QMap<QString,QString>& opts )
void setPrintForceRaster( bool forceRaster )
{
m_forceRaster->setChecked( opts[ "kde-okular-poppler-forceRaster" ].toInt() );
m_forceRaster->setChecked( forceRaster );
}
private:
......@@ -292,7 +292,7 @@ OKULAR_EXPORT_PLUGIN(PDFGenerator)
PDFGenerator::PDFGenerator()
: Generator(), pdfdoc( 0 ), ready( true ),
pixmapRequest( 0 ), docInfoDirty( true ), docSynopsisDirty( true ),
docEmbeddedFilesDirty( true )
docEmbeddedFilesDirty( true ), pdfOptionsPage( 0 )
{
// ### TODO fill after the KDE 4.0 unfreeze
KAboutData *about = new KAboutData(
......@@ -307,8 +307,10 @@ PDFGenerator::PDFGenerator()
setAboutData( about );
setFeature( TextExtraction );
setFeature( FontInfo );
setFeature( PrintPostscript );
#ifdef HAVE_POPPLER_0_6
setFeature( ReadRawData );
pdfOptionsPage = new PDFOptionsPage();
#endif
// update the configuration
reparseConfig();
......@@ -325,6 +327,8 @@ PDFGenerator::~PDFGenerator()
generatorThread->wait();
delete generatorThread;
}
delete pdfOptionsPage;
}
//BEGIN Generator inherited functions
......@@ -842,119 +846,104 @@ Okular::TextPage* PDFGenerator::textPage( Okular::Page *page )
bool PDFGenerator::print( QPrinter& printer )
{
/* This printing method unsupported in QPrinter, looking for alternative.
int width, height;
// PageSize is a CUPS artificially created setting
QString ps = printer.option( "PageSize" );
QRegExp sizere( "w(\\d+)h(\\d+)" );
int marginTop, marginLeft, marginRight, marginBottom;
marginTop = (int)printer.option("kde-margin-top").toDouble();
marginLeft = (int)printer.option("kde-margin-left").toDouble();
marginRight = (int)printer.option("kde-margin-right").toDouble();
marginBottom = (int)printer.option("kde-margin-bottom").toDouble();
if ( sizere.exactMatch( ps ) )
{
// size not supported by Qt, CUPS gives us the size as wWIDTHhHEIGHT, at least on the printers i tested
width = sizere.cap( 1 ).toInt();
height = sizere.cap( 2 ).toInt();
}
else
{
// size is supported by Qt, we get either the pageSize name or nothing because the CUPS driver
// does not do any translation, then use KPrinter::pageSize to get the page size
KPrinter::PageSize qtPageSize;
if (!ps.isEmpty())
{
bool ok;
qtPageSize = pageNameToPageSize(ps, &ok);
// If we could not decode page size from the cups text try KPrinter::pageSize as last resort :-D
if (!ok) qtPageSize = printer.pageSize();
}
else qtPageSize = printer.pageSize();
QPrinter dummy(QPrinter::PrinterResolution);