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
This commit is contained in:
John Layt 2007-11-26 21:43:54 +00:00
parent 2153ec5edd
commit 1b1ed9451b
16 changed files with 1242 additions and 245 deletions

View file

@ -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

View file

@ -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;

View file

@ -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.
*/

662
core/fileprinter.cpp Normal file
View file

@ -0,0 +1,662 @@
/***************************************************************************
* 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. *
***************************************************************************/
#include "fileprinter.h"
#include <QtGui/QPrinter>
#include <QPrintEngine>
#include <QStringList>
#include <QFile>
#include <QSize>
#include <QtCore/QFile>
#include <QtGui/QLabel>
#include <QtGui/QShowEvent>
#include <KProcess>
#include <KShell>
#include <klocalsocket.h>
#include <kstandarddirs.h>
#include <kmimetypetrader.h>
#include <kparts/part.h>
#include <kpluginfactory.h>
#include <kpluginloader.h>
#include <kservice.h>
#include <ktempdir.h>
#include <kdebug.h>
using namespace Okular;
int FilePrinter::printFile( QPrinter &printer, QString file, FileDeletePolicy fileDeletePolicy,
PageSelectPolicy pageSelectPolicy, const QString &pageRange )
{
FilePrinter fp;
return fp.doPrintFiles( printer, QStringList( file ), fileDeletePolicy, pageSelectPolicy, pageRange );
}
int FilePrinter::printFiles( QPrinter &printer, const QStringList &fileList, FileDeletePolicy fileDeletePolicy )
{
FilePrinter fp;
return fp.doPrintFiles( printer, fileList, fileDeletePolicy, FilePrinter::ApplicationSelectsPages, QString() );
}
int FilePrinter::doPrintFiles( QPrinter &printer, QStringList fileList, FileDeletePolicy fileDeletePolicy,
PageSelectPolicy pageSelectPolicy, const QString &pageRange )
{
QString exe("lpr");
if ( KStandardDirs::findExe(exe).isEmpty() ) {
exe = "lp";
}
if ( KStandardDirs::findExe(exe).isEmpty() ) {
return -9;
}
if ( fileList.size() < 1 ) {
return -8;
}
for (QStringList::ConstIterator it = fileList.begin(); it != fileList.end(); ++it) {
if (!QFile::exists(*it)) {
return -7;
}
}
if ( printer.printerState() == QPrinter::Aborted || printer.printerState() == QPrinter::Error ) {
return -6;
}
// Print to File if a filename set, assumes there must be only 1 file
if ( !printer.outputFileName().isEmpty() ) {
if ( QFile::exists( printer.outputFileName() ) ) {
QFile::remove( printer.outputFileName() );
}
int res = QFile::copy( fileList[0], printer.outputFileName() );
if ( fileDeletePolicy == FilePrinter::SystemDeletesFiles ) {
QFile::remove( fileList[0] );
}
if ( res ) return 0;
}
bool useCupsOptions = cupsAvailable();
QStringList argList = printArguments( printer, fileDeletePolicy, pageSelectPolicy, useCupsOptions, pageRange, exe )
<< fileList;
kDebug() << "Executing " << exe << " with arguments" << argList;
int ret = KProcess::execute( exe, argList );
// If we used the Cups options and the command failed, try again without them in case Cups lpr/lp not installed.
// I'm not convinced this will work, I don't think KProcess returns the result of the command, but rather
// that it was able to be executed?
if ( useCupsOptions && ret < 0 ) {
argList = printArguments( printer, fileDeletePolicy, pageSelectPolicy, useCupsOptions, pageRange, exe )
<< fileList;
kDebug() << "Retrying " << exe << " without cups arguments" << argList;
ret = KProcess::execute( exe, argList );
}
return ret;
}
QList<int> FilePrinter::pageList( QPrinter &printer, int lastPage, const QList<int> &selectedPageList )
{
if ( printer.printRange() == QPrinter::Selection) {
return selectedPageList;
}
int startPage, endPage;
QList<int> list;
if ( printer.printRange() == QPrinter::PageRange ) {
startPage = printer.fromPage();
endPage = printer.toPage();
} else { //AllPages
startPage = 1;
endPage = lastPage;
}
for (int i = startPage; i <= endPage; i++ ) {
list << i;
}
return list;
}
QString FilePrinter::pageRange( QPrinter &printer, int lastPage, const QList<int> &selectedPageList )
{
if ( printer.printRange() == QPrinter::Selection) {
return pageListToPageRange( selectedPageList );
}
if ( printer.printRange() == QPrinter::PageRange ) {
return QString("%1-%2").arg(printer.fromPage()).arg(printer.toPage());
}
return QString("1-%2").arg( lastPage );
}
QString FilePrinter::pageListToPageRange( const QList<int> &pageList )
{
QString pageRange;
int count = pageList.count();
int i = 0;
int seqStart = i;
int seqEnd;
while ( i != count ) {
if ( i + 1 == count || pageList[i] + 1 != pageList[i+1] ) {
seqEnd = i;
if ( !pageRange.isEmpty() ) {
pageRange.append(",");
}
if ( seqStart == seqEnd ) {
pageRange.append(pageList[i]);
} else {
pageRange.append("%1-%2").arg(seqStart).arg(seqEnd);
}
seqStart = i + 1;
}
i++;
}
return pageRange;
}
bool FilePrinter::cupsAvailable()
{
FilePrinter fp;
return ( fp.detectCupsConfig() /*&& fp.detectCupsService()*/ );
}
bool FilePrinter::detectCupsService()
{
// copied from KdeprintChecker::checkService()
// Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be>
// original license LGPL
KLocalSocket sock;
sock.connectToPath("/ipp");
kDebug() << "socket wait = " << sock.waitForConnected();
kDebug() << "socket error = " << sock.error();
kDebug() << "socket isOpen() = " << sock.isOpen();
return sock.isOpen();
}
bool FilePrinter::detectCupsConfig()
{
if ( QFile::exists("/etc/cups/cupsd.conf") ) return true;
if ( QFile::exists("/usr/etc/cups/cupsd.conf") ) return true;
if ( QFile::exists("/usr/local/etc/cups/cupsd.conf") ) return true;
if ( QFile::exists("/opt/etc/cups/cupsd.conf") ) return true;
if ( QFile::exists("/opt/local/etc/cups/cupsd.conf") ) return true;
return false;
}
QSize FilePrinter::psPaperSize( QPrinter &printer )
{
QSize size;
switch ( printer.pageSize() ) {
case QPrinter::A0: size = QSize( 2384, 3370 ); break;
case QPrinter::A1: size = QSize( 1684, 2384 ); break;
case QPrinter::A2: size = QSize( 1191, 1684 ); break;
case QPrinter::A3: size = QSize( 842, 1191 ); break;
case QPrinter::A4: size = QSize( 595, 842 ); break;
case QPrinter::A5: size = QSize( 420, 595 ); break;
case QPrinter::A6: size = QSize( 298, 420 ); break;
case QPrinter::A7: size = QSize( 210, 298 ); break;
case QPrinter::A8: size = QSize( 147, 210 ); break;
case QPrinter::A9: size = QSize( 105, 147 ); break;
case QPrinter::B0: size = QSize( 2835, 4008 ); break;
case QPrinter::B1: size = QSize( 2004, 2835 ); break;
case QPrinter::B2: size = QSize( 1417, 2004 ); break;
case QPrinter::B3: size = QSize( 1001, 1417 ); break;
case QPrinter::B4: size = QSize( 709, 1001 ); break;
case QPrinter::B5: size = QSize( 499, 709 ); break;
case QPrinter::B6: size = QSize( 354, 499 ); break;
case QPrinter::B7: size = QSize( 249, 354 ); break;
case QPrinter::B8: size = QSize( 176, 249 ); break;
case QPrinter::B9: size = QSize( 125, 176 ); break;
case QPrinter::B10: size = QSize( 88, 125 ); break;
case QPrinter::C5E: size = QSize( 459, 649 ); break;
case QPrinter::Comm10E: size = QSize( 297, 684 ); break;
case QPrinter::DLE: size = QSize( 312, 624 ); break;
case QPrinter::Executive: size = QSize( 522, 756 ); break;
case QPrinter::Folio: size = QSize( 595, 935 ); break;
case QPrinter::Ledger: size = QSize( 1224, 792 ); break;
case QPrinter::Legal: size = QSize( 612, 1008 ); break;
case QPrinter::Letter: size = QSize( 612, 792 ); break;
case QPrinter::Tabloid: size = QSize( 792, 1224 ); break;
case QPrinter::Custom: return QSize( (int) printer.widthMM() * ( 25.4 / 72 ),
(int) printer.heightMM() * ( 25.4 / 72 ) );
default: return QSize();
}
if ( printer.orientation() == QPrinter::Landscape ) {
size.transpose();
}
return size;
}
QStringList FilePrinter::printArguments( QPrinter &printer, FileDeletePolicy fileDeletePolicy,
PageSelectPolicy pageSelectPolicy, bool useCupsOptions,
const QString &pageRange, const QString &version )
{
QStringList argList;
if ( ! destination( printer, version ).isEmpty() ) {
argList << destination( printer, version );
}
if ( ! copies( printer, version ).isEmpty() ) {
argList << copies( printer, version );
}
if ( ! jobname( printer, version ).isEmpty() ) {
argList << jobname( printer, version );
}
if ( ! pages( printer, pageSelectPolicy, pageRange, useCupsOptions, version ).isEmpty() ) {
argList << pages( printer, pageSelectPolicy, pageRange, useCupsOptions, version );
}
if ( useCupsOptions && ! cupsOptions( printer ).isEmpty() ) {
argList << cupsOptions( printer );
}
if ( ! deleteFile( printer, fileDeletePolicy, version ).isEmpty() ) {
argList << deleteFile( printer, fileDeletePolicy, version );
}
if ( version == "lp" ) {
argList << "--";
}
return argList;
}
QStringList FilePrinter::destination( QPrinter &printer, const QString &version )
{
if ( version == "lp" ) {
return QStringList("-d") << printer.printerName();
}
if ( version == "lpr" ) {
return QStringList("-P") << printer.printerName();
}
return QStringList();
}
QStringList FilePrinter::copies( QPrinter &printer, const QString &version )
{
// Can't use QPrinter::numCopies(), as if CUPS will always return 1, not sure if this behaves same way as well?
int cp = printer.printEngine()->property( QPrintEngine::PPK_NumberOfCopies ).toInt();
if ( version == "lp" ) {
return QStringList("-n") << QString("%1").arg( cp );
}
if ( version == "lpr" ) {
return QStringList() << QString("-#%1").arg( cp );
}
return QStringList();
}
QStringList FilePrinter::jobname( QPrinter &printer, const QString &version )
{
if ( ! printer.docName().isEmpty() ) {
if ( version == "lp" ) {
return QStringList("-t") << printer.docName();
}
if ( version == "lpr" ) {
return QStringList("-J") << printer.docName();
}
}
return QStringList();
}
QStringList FilePrinter::deleteFile( QPrinter &printer, FileDeletePolicy fileDeletePolicy, const QString &version )
{
if ( fileDeletePolicy == FilePrinter::SystemDeletesFiles && version == "lpr" ) {
return QStringList("-r");
}
return QStringList();
}
QStringList FilePrinter::pages( QPrinter &printer, PageSelectPolicy pageSelectPolicy, const QString &pageRange,
bool useCupsOptions, const QString &version )
{
if ( pageSelectPolicy == FilePrinter::SystemSelectsPages ) {
if ( printer.printRange() == QPrinter::Selection && ! pageRange.isEmpty() ) {
if ( version == "lp" ) {
return QStringList("-P") << pageRange ;
}
if ( version == "lpr" && useCupsOptions ) {
return QStringList("-o") << QString("page-ranges=%1").arg( pageRange );
}
}
if ( printer.printRange() == QPrinter::PageRange ) {
if ( version == "lp" ) {
return QStringList("-P") << QString("%1-%2").arg( printer.fromPage() )
.arg( printer.toPage() );
}
if ( version == "lpr" && useCupsOptions ) {
return QStringList("-o") << QString("page-ranges=%1-%2").arg( printer.fromPage() )
.arg( printer.toPage() );
}
}
}
return QStringList(); // AllPages
}
QStringList FilePrinter::cupsOptions( QPrinter &printer )
{
QStringList optionList;
if ( ! optionMedia( printer ).isEmpty() ) {
optionList << optionMedia( printer );
}
if ( ! optionOrientation( printer ).isEmpty() ) {
optionList << optionOrientation( printer );
}
if ( ! optionDoubleSidedPrinting( printer ).isEmpty() ) {
optionList << optionDoubleSidedPrinting( printer );
}
if ( ! optionPageOrder( printer ).isEmpty() ) {
optionList << optionPageOrder( printer );
}
if ( ! optionCollateCopies( printer ).isEmpty() ) {
optionList << optionCollateCopies( printer );
}
return optionList;
}
QStringList FilePrinter::optionMedia( QPrinter &printer )
{
if ( ! mediaPageSize( printer ).isEmpty() &&
! mediaPaperSource( printer ).isEmpty() ) {
return QStringList("-o") <<
QString("media=%1,%2").arg( mediaPageSize( printer ) )
.arg( mediaPaperSource( printer ) );
}
if ( ! mediaPageSize( printer ).isEmpty() ) {
return QStringList("-o") <<
QString("media=%1").arg( mediaPageSize( printer ) );
}
if ( ! mediaPaperSource( printer ).isEmpty() ) {
return QStringList("-o") <<
QString("media=%1").arg( mediaPaperSource( printer ) );
}
return QStringList();
}
QString FilePrinter::mediaPageSize( QPrinter &printer )
{
switch ( printer.pageSize() ) {
case QPrinter::A0: return "A0";
case QPrinter::A1: return "A1";
case QPrinter::A2: return "A2";
case QPrinter::A3: return "A3";
case QPrinter::A4: return "A4";
case QPrinter::A5: return "A5";
case QPrinter::A6: return "A6";
case QPrinter::A7: return "A7";
case QPrinter::A8: return "A8";
case QPrinter::A9: return "A9";
case QPrinter::B0: return "B0";
case QPrinter::B1: return "B1";
case QPrinter::B10: return "B10";
case QPrinter::B2: return "B2";
case QPrinter::B3: return "B3";
case QPrinter::B4: return "B4";
case QPrinter::B5: return "B5";
case QPrinter::B6: return "B6";
case QPrinter::B7: return "B7";
case QPrinter::B8: return "B8";
case QPrinter::B9: return "B9";
case QPrinter::C5E: return "C5"; //Correct Translation?
case QPrinter::Comm10E: return "Comm10"; //Correct Translation?
case QPrinter::DLE: return "DL"; //Correct Translation?
case QPrinter::Executive: return "Executive";
case QPrinter::Folio: return "Folio";
case QPrinter::Ledger: return "Ledger";
case QPrinter::Legal: return "Legal";
case QPrinter::Letter: return "Letter";
case QPrinter::Tabloid: return "Tabloid";
case QPrinter::Custom: return QString("Custom.%1x%2mm")
.arg( printer.heightMM() )
.arg( printer.widthMM() );
default: return QString();
}
}
// What about Upper and MultiPurpose? And others in PPD???
QString FilePrinter::mediaPaperSource( QPrinter &printer )
{
switch ( printer.paperSource() ) {
case QPrinter::Auto: return QString();
case QPrinter::Cassette: return "Cassette";
case QPrinter::Envelope: return "Envelope";
case QPrinter::EnvelopeManual: return "EnvelopeManual";
case QPrinter::FormSource: return "FormSource";
case QPrinter::LargeCapacity: return "LargeCapacity";
case QPrinter::LargeFormat: return "LargeFormat";
case QPrinter::Lower: return "Lower";
case QPrinter::MaxPageSource: return "MaxPageSource";
case QPrinter::Middle: return "Middle";
case QPrinter::Manual: return "Manual";
case QPrinter::OnlyOne: return "OnlyOne";
case QPrinter::Tractor: return "Tractor";
case QPrinter::SmallFormat: return "SmallFormat";
default: return QString();
}
}
QStringList FilePrinter::optionOrientation( QPrinter &printer )
{
switch ( printer.orientation() ) {
case QPrinter::Portrait: return QStringList("-o") << "portrait";
case QPrinter::Landscape: return QStringList("-o") << "landscape";
default: return QStringList();
}
}
QStringList FilePrinter::optionDoubleSidedPrinting( QPrinter &printer )
{
if ( printer.doubleSidedPrinting() ) {
if ( printer.orientation() == QPrinter::Landscape ) {
return QStringList("-o") << "sides=two-sided-short-edge";
} else {
return QStringList("-o") << "sides=two-sided-long-edge";
}
}
return QStringList("-o") << "sides=one-sided";
}
QStringList FilePrinter::optionPageOrder( QPrinter &printer )
{
if ( printer.pageOrder() == QPrinter::LastPageFirst ) {
return QStringList("-o") << "outputorder=reverse";
}
return QStringList("-o") << "outputorder=normal";
}
QStringList FilePrinter::optionCollateCopies( QPrinter &printer )
{
if ( printer.collateCopies() ) {
return QStringList("-o") << "Collate=True";
}
return QStringList("-o") << "Collate=False";
}
// This code copied from KPrintPreview by Alex Merry, adapted to do PS files instead of PDF
class Okular::FilePrinterPreviewPrivate
{
public:
FilePrinterPreviewPrivate( FilePrinterPreview *host, const QString & _filename )
: q(host)
, mainWidget(new QWidget(host))
, previewPart(0)
, failMessage(0)
{
filename = _filename;
}
void getPart();
bool doPreview();
void fail();
FilePrinterPreview *q;
QWidget *mainWidget;
QString filename;
KParts::ReadOnlyPart *previewPart;
QWidget *failMessage;
};
void FilePrinterPreviewPrivate::getPart()
{
if (previewPart) {
kDebug(500) << "already got a part";
return;
}
kDebug(500) << "querying trader for application/ps service";
KPluginFactory *factory(0);
KService::List offers =
KMimeTypeTrader::self()->query("application/postscript", "KParts/ReadOnlyPart");
KService::List::ConstIterator it = offers.begin();
while (!factory && it != offers.end()) {
KPluginLoader loader(**it);
factory = loader.factory();
if (!factory) {
kDebug(500) << "Loading failed:" << loader.errorString();
}
++it;
}
if (factory) {
kDebug(500) << "Trying to create a part";
previewPart = factory->create<KParts::ReadOnlyPart>(q, (QVariantList() << "Print/Preview"));
if (!previewPart) {
kDebug(500) << "Part creation failed";
}
}
}
bool FilePrinterPreviewPrivate::doPreview()
{
if (!QFile::exists(filename)) {
kWarning() << "Nothing was produced to be previewed";
return false;
}
getPart();
if (!previewPart) {
//TODO: error dialog
kWarning() << "Could not find a PS viewer for the preview dialog";
fail();
return false;
} else {
q->setMainWidget(previewPart->widget());
return previewPart->openUrl(filename);
}
}
void FilePrinterPreviewPrivate::fail()
{
if (!failMessage) {
failMessage = new QLabel(i18n("Could not load print preview part"), q);
}
q->setMainWidget(failMessage);
}
FilePrinterPreview::FilePrinterPreview( const QString &filename, QWidget *parent )
: KDialog( parent )
, d( new FilePrinterPreviewPrivate( this, filename ) )
{
kDebug(500) << "kdeprint: creating preview dialog";
// Set up the dialog
setCaption(i18n("Print Preview"));
setButtons(KDialog::Close);
}
FilePrinterPreview::~FilePrinterPreview()
{
delete d;
}
void FilePrinterPreview::showEvent(QShowEvent *event)
{
if (!event->spontaneous()) {
// being shown for the first time
if (!d->doPreview()) {
event->accept();
return;
}
}
KDialog::showEvent(event);
}
#include "fileprinter.moc"

198
core/fileprinter.h Normal file
View file

@ -0,0 +1,198 @@
/***************************************************************************
* 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

View file

@ -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
};
/**

View file

@ -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();

View file

@ -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

View file

@ -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

View file

@ -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();
int pageWidth = printer.width() - right;
int pageHeight = printer.height() - bottom;
QImage image( m_img );
if ( (image.width() > pageWidth) || (image.height() > pageHeight) )
image = image.scaled( pageWidth, pageHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation );
if ( ( image.width() > printer.width() ) || ( image.height() > printer.height() ) )
image = image.scaled( printer.width(), printer.height(),
Qt::KeepAspectRatio, Qt::SmoothTransformation );
p.drawImage( 0, 0, image );

View file

@ -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);
dummy.setOrientation((QPrinter::Orientation)printer.orientation());
dummy.setFullPage(true);
dummy.setPageSize((QPrinter::PageSize)qtPageSize);
width = dummy.width();
height = dummy.height();
}
// Get the real page size to pass to the ps generator
QPrinter dummy( QPrinter::PrinterResolution );
dummy.setFullPage( true );
dummy.setOrientation( printer.orientation() );
int width = dummy.width();
int height = dummy.height();
// Create the tempfile to send to FilePrinter, which will manage the deletion
KTemporaryFile tf;
tf.setSuffix( ".ps" );
if ( !tf.open() )
return false;
QString tempfilename = tf.fileName();
#if !POPPLER_HAVE_PSCONVERTER_SETOUTPUTDEVICE
// Generate the list of pages to be printed as selected in the print dialog
QList<int> pageList = Okular::FilePrinter::pageList( printer, pdfdoc->numPages(),
document()->bookmarkedPageList() );
// TODO rotation
#ifdef HAVE_POPPLER_0_6
#if POPPLER_HAVE_PSCONVERTER_SETOUTPUTDEVICE
tf.setAutoRemove(false);
#else
tf.close();
#endif
QList<int> pageList;
if (!printer.previewOnly()) pageList = printer.pageList();
else for(int i = 1; i <= pdfdoc->numPages(); i++) pageList.push_back(i);
// TODO rotation
#ifdef HAVE_POPPLER_0_6
double xScale = ((double)width - (double)marginLeft - (double)marginRight) / (double)width;
double yScale = ((double)height - (double)marginBottom - (double)marginTop) / (double)height;
bool strictMargins = false;
if ( abs((int)(xScale * 100) - (int)(yScale * 100)) > 5 ) {
int result = KMessageBox::questionYesNo(document()->widget(),
i18n("The margins you specified are changing the page aspect ratio. Do you want to print with the aspect ratio changed or do you want the margins to be adapted so that aspect ratio is preserved?"),
i18n("Aspect ratio change"),
KGuiItem( i18n("Print with specified margins") ),
KGuiItem( i18n("Print adapting margins to keep aspect ratio") ),
"kpdfStrictlyObeyMargins");
if (result == KMessageBox::Yes) strictMargins = true;
}
QString pstitle = metaData(QLatin1String("Title"), QVariant()).toString();
if ( pstitle.trimmed().isEmpty() )
{
pstitle = document()->currentDocument().fileName();
}
bool forceRasterize = printer.option("kde-okular-poppler-forceRaster").toInt();
bool forceRasterize = pdfOptionsPage->printForceRaster();
Poppler::PSConverter *psConverter = pdfdoc->psConverter();
#if POPPLER_HAVE_PSCONVERTER_SETOUTPUTDEVICE
psConverter->setOutputDevice(&tf);
#else
psConverter->setOutputFileName(tempfilename);
#endif
psConverter->setPageList(pageList);
psConverter->setPaperWidth(width);
psConverter->setPaperHeight(height);
psConverter->setRightMargin(marginRight);
psConverter->setBottomMargin(marginBottom);
psConverter->setLeftMargin(marginLeft);
psConverter->setTopMargin(marginTop);
psConverter->setStrictMargins(strictMargins);
psConverter->setRightMargin(0);
psConverter->setBottomMargin(0);
psConverter->setLeftMargin(0);
psConverter->setTopMargin(0);
psConverter->setStrictMargins(false);
psConverter->setForceRasterize(forceRasterize);
psConverter->setTitle(pstitle);
userMutex()->lock();
if (psConverter->convert())
{
userMutex()->unlock();
delete psConverter;
return printer.printFiles(QStringList(tempfilename), true);
int ret = Okular::FilePrinter::printFile( printer, tempfilename,
Okular::FilePrinter::SystemDeletesFiles,
Okular::FilePrinter::ApplicationSelectsPages,
document()->bookmarkedPageRange() );
if ( ret >= 0 ) return true;
}
else
{
delete psConverter;
#else
userMutex()->lock();
if (pdfdoc->print(tempfilename, pageList, 72, 72, 0, width, height))
{
userMutex()->unlock();
return printer.printFiles(QStringList(tempfilename), true);
}
else
{
#endif
userMutex()->unlock();
return false;
}
*/
return false;
#else // Not HAVE_POPPLER_0_6
userMutex()->lock();
if ( pdfdoc->print( tempfilename, pageList, 72, 72, 0, width, height ) )
{
userMutex()->unlock();
tf.setAutoRemove( false );
int ret = Okular::FilePrinter::printFile( printer, tempfilename,
Okular::FilePrinter::SystemDeletesFiles,
Okular::FilePrinter::ApplicationSelectsPages,
document()->bookmarkedPageRange() );
if ( ret >= 0 ) return true;
}
else
{
userMutex()->unlock();
return false;
}
#endif // HAVE_POPPLER_0_6
tf.close();
return false;
}
QVariant PDFGenerator::metaData( const QString & key, const QVariant & option ) const
@ -1515,11 +1504,7 @@ void PDFGenerator::loadPdfSync( const QString & filePath, QVector<Okular::Page*>
QWidget* PDFGenerator::printConfigurationWidget() const
{
#ifdef HAVE_POPPLER_0_6
return new PDFOptionsPage();
#else
return 0;
#endif
return pdfOptionsPage;
}

View file

@ -26,6 +26,7 @@ namespace Okular {
class ObjectRect;
}
class PDFOptionsPage;
class PDFPixmapGeneratorThread;
/**
@ -131,6 +132,8 @@ class PDFGenerator : public Okular::Generator, public Okular::ConfigInterface, p
mutable QList<Okular::EmbeddedFile*> docEmbeddedFiles;
QVector<bool> rectsGenerated;
PDFOptionsPage * pdfOptionsPage;
};

View file

@ -19,9 +19,11 @@
#include <kconfigdialog.h>
#include <kdebug.h>
#include <kmimetype.h>
#include <ktemporaryfile.h>
#include <okular/core/document.h>
#include <okular/core/page.h>
#include <okular/core/fileprinter.h>
#include "ui_gssettingswidget.h"
#include "gssettings.h"
@ -37,6 +39,9 @@ GSGenerator::GSGenerator() :
m_docInfo(0),
m_request(0)
{
setFeature( PrintPostscript );
setFeature( PrintToFile );
// ### TODO fill after the KDE 4.0 unfreeze
KAboutData *about = new KAboutData(
"okular_ghostview",
@ -75,22 +80,54 @@ void GSGenerator::addPages( KConfigDialog *dlg )
bool GSGenerator::print( QPrinter& printer )
{
/* This printing method unsupported in QPrinter, looking for alternative.
bool result = false;
// Create tempfile to write to
KTemporaryFile tf;
tf.setSuffix( ".ps" );
if ( tf.open() )
if ( !tf.open() )
return false;
// Get list of pages to print
QList<int> pageList = Okular::FilePrinter::pageList( printer,
spectre_document_get_n_pages( m_internalDocument ),
document()->bookmarkedPageList() );
// Default to Postscript export, but if printing to PDF use that instead
SpectreExporterFormat exportFormat = SPECTRE_EXPORTER_FORMAT_PS;
if ( printer.outputFileName().right(3) == "pdf" )
{
bool result = false;
if ( internalDoc->savePages( tf.fileName(), printer.pageList() ) )
{
result = printer.printFiles( QStringList( tf.fileName() ), true );
}
tf.close();
return result;
exportFormat = SPECTRE_EXPORTER_FORMAT_PDF;
tf.setSuffix(".pdf");
}
*/
return false;
SpectreExporter *exporter = spectre_exporter_new( m_internalDocument, exportFormat );
SpectreStatus exportStatus = spectre_exporter_begin( exporter, tf.fileName().toAscii() );
int i = 0;
while ( i < pageList.count() && exportStatus == SPECTRE_STATUS_SUCCESS )
{
exportStatus = spectre_exporter_do_page( exporter, i );
i++;
}
SpectreStatus endStatus = spectre_exporter_end( exporter );
spectre_exporter_free( exporter );
if ( exportStatus == SPECTRE_STATUS_SUCCESS && endStatus == SPECTRE_STATUS_SUCCESS )
{
tf.setAutoRemove( false );
int ret = Okular::FilePrinter::printFile( printer, tf.fileName(),
Okular::FilePrinter::SystemDeletesFiles,
Okular::FilePrinter::ApplicationSelectsPages,
document()->bookmarkedPageRange() );
if ( ret >= 0 ) result = true;
}
tf.close();
return result;
}
bool GSGenerator::loadDocument( const QString & fileName, QVector< Okular::Page * > & pagesVector )

View file

@ -22,6 +22,7 @@
#include <okular/core/document.h>
#include <okular/core/page.h>
#include <okular/core/fileprinter.h>
#include <tiff.h>
#include <tiffio.h>
@ -50,6 +51,8 @@ TIFFGenerator::TIFFGenerator()
d( new Private ), m_docInfo( 0 )
{
setFeature( Threaded );
setFeature( PrintNative );
setFeature( PrintToFile );
KAboutData *about = new KAboutData(
"okular_tiff",
@ -220,9 +223,12 @@ bool TIFFGenerator::print( QPrinter& printer )
QPainter p( &printer );
for ( tdir_t i = 0; i < dirs; ++i )
QList<int> pageList = Okular::FilePrinter::pageList( printer, document()->pages(),
document()->bookmarkedPageList() );
for ( tdir_t i = 0; i < pageList.count(); ++i )
{
if ( !TIFFSetDirectory( d->tiff, i ) )
if ( !TIFFSetDirectory( d->tiff, pageList[i] - 1 ) )
continue;
if ( TIFFGetField( d->tiff, TIFFTAG_IMAGEWIDTH, &width ) != 1 ||

180
part.cpp
View file

@ -79,6 +79,7 @@
#include "core/document.h"
#include "core/generator.h"
#include "core/page.h"
#include "core/fileprinter.h"
K_PLUGIN_FACTORY( okularPartFactory, registerPlugin< Part >(); )
K_EXPORT_PLUGIN( okularPartFactory( okularAboutData( "okular", I18N_NOOP( "okular" ) ) ) )
@ -742,7 +743,7 @@ bool Part::openFile()
m_find->setEnabled( ok && canSearch );
m_findNext->setEnabled( ok && canSearch );
m_saveAs->setEnabled( ok );
m_printPreview->setEnabled( ok );
m_printPreview->setEnabled( ok && m_document->printingSupport() != Okular::Document::NoPrinting );
m_showProperties->setEnabled( ok );
bool hasEmbeddedFiles = ok && m_document->embeddedFiles() && m_document->embeddedFiles()->count() > 0;
m_showEmbeddedFiles->setEnabled( hasEmbeddedFiles );
@ -815,7 +816,7 @@ bool Part::openUrl(const KUrl &url)
setWindowTitleFromDocument();
}
emit enablePrintAction(openOk);
emit enablePrintAction(openOk && m_document->printingSupport() != Okular::Document::NoPrinting);
return openOk;
}
@ -940,7 +941,7 @@ void Part::slotDoFileDirty()
m_sidebar->setCurrentIndex( m_sidebar->currentIndex() );
}
if (m_wasPresentationOpen) slotShowPresentation();
emit enablePrintAction(true);
emit enablePrintAction(true && m_document->printingSupport() != Okular::Document::NoPrinting);
}
else
{
@ -1295,38 +1296,33 @@ void Part::slotPrintPreview()
{
if (m_document->pages() == 0) return;
double width, height;
int landscape, portrait;
QPrinter printer;
const Okular::Page *page;
// printer.setMinMax(1, m_document->pages());
// printer.setPreviewOnly( true );
// if some pages are landscape and others are not the most common win as kprinter does
// not accept a per page setting
landscape = 0;
portrait = 0;
for (uint i = 0; i < m_document->pages(); i++)
// Native printing supports KPrintPreview, Postscript needs to use FilePrinterPreview
if ( m_document->printingSupport() == Okular::Document::NativePrinting )
{
page = m_document->page(i);
width = page->width();
height = page->height();
if (page->orientation() == 90 || page->orientation() == 270) qSwap(width, height);
if (width > height) landscape++;
else portrait++;
KPrintPreview previewdlg( &printer, widget() );
setupPrint( printer );
doPrint( printer );
previewdlg.exec();
}
if (landscape > portrait)
else
{
// printer.setOption("orientation-requested", "4");
printer.setOrientation( QPrinter::Landscape );
// Generate a temp filename for Print to File, then release the file so generator can write to it
KTemporaryFile tf;
tf.setAutoRemove( true );
tf.setSuffix( ".ps" );
tf.open();
printer.setOutputFileName( tf.fileName() );
tf.close();
setupPrint( printer );
doPrint( printer );
if ( QFile::exists( printer.outputFileName() ) )
{
Okular::FilePrinterPreview previewdlg( printer.outputFileName(), widget() );
previewdlg.exec();
}
}
KPrintPreview previewdlg( &printer, widget() );
doPrint(printer);
previewdlg.exec();
}
@ -1495,21 +1491,61 @@ void Part::slotPrint()
{
if (m_document->pages() == 0) return;
QPrinter printer;
QPrintDialog *printDialog = 0;
QWidget *printConfigWidget = 0;
// Must do certain QPrinter setup before creating QPrintDialog
setupPrint( printer );
// Create the Print Dialog with extra config widgets if required
if ( m_document->canConfigurePrinter() )
{
printConfigWidget = m_document->printConfigurationWidget();
}
if ( printConfigWidget )
{
printDialog = KdePrint::createPrintDialog( &printer, QList<QWidget*>() << printConfigWidget, widget() );
}
else
{
printDialog = KdePrint::createPrintDialog( &printer, widget() );
}
if ( printDialog )
{
// Set the available Print Range
printDialog->setMinMax( 1, m_document->pages() );
printDialog->setFromTo( 1, m_document->pages() );
// If the user has bookmarked pages for printing, then enable Selection
if ( !m_document->bookmarkedPageRange().isEmpty() )
{
printDialog->addEnabledOption( QAbstractPrintDialog::PrintSelection );
}
// If the Document type doesn't support print to both PS & PDF then disable the Print Dialog option
if ( printDialog->isOptionEnabled( QAbstractPrintDialog::PrintToFile ) &&
!m_document->supportsPrintToFile() )
{
printDialog->setEnabledOptions( printDialog->enabledOptions() ^ QAbstractPrintDialog::PrintToFile );
}
if ( printDialog->exec() )
doPrint( printer );
}
}
void Part::setupPrint( QPrinter &printer )
{
double width, height;
int landscape, portrait;
QPrinter printer;
const Okular::Page *page;
/* Disable as QPrinter does not support most of this page management stuff.
Besides no point sorting this out until we solve the main printFiles problem.
However leave basic printing in place as some formats still support it.
printer.setPageSelection(KPrinter::ApplicationSide);
printer.setMinMax(1, m_document->pages());
printer.setCurrentPage(m_document->currentPage()+1);
*/
// if some pages are landscape and others are not the most common win as kprinter does
// if some pages are landscape and others are not the most common win as QPrinter does
// not accept a per page setting
landscape = 0;
portrait = 0;
@ -1524,50 +1560,6 @@ void Part::slotPrint()
}
if (landscape > portrait) printer.setOrientation(QPrinter::Landscape);
/*
// range detecting
QString range;
uint pages = m_document->pages();
int startId = -1;
int endId = -1;
for ( uint i = 0; i < pages; ++i )
{
if ( m_document->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 );
}
printer.setOption( "kde-range", range );
*/
// title
QString title = m_document->metaData( "DocumentTitle" ).toString();
if ( title.isEmpty() )
@ -1578,26 +1570,6 @@ void Part::slotPrint()
{
printer.setDocName( title );
}
QPrintDialog *printDialog;
QWidget * w;
if ( m_document->canConfigurePrinter() )
{
w = m_document->printConfigurationWidget();
}
if ( w )
{
printDialog = KdePrint::createPrintDialog( &printer, QList<QWidget*>() << w, widget() );
}
else
{
printDialog = KdePrint::createPrintDialog( &printer, widget() );
}
if ( printDialog->exec() )
doPrint( printer );
}

3
part.h
View file

@ -164,7 +164,8 @@ class Part : public KParts::ReadOnlyPart, public Okular::DocumentObserver, publi
void psTransformEnded(int, QProcess::ExitStatus);
private:
void doPrint( QPrinter& printer );
void setupPrint( QPrinter &printer );
void doPrint( QPrinter &printer );
bool handleCompressed( QString &destpath, const QString &path, const QString &compressedMimetype );
void rebuildBookmarkMenu( bool unplugActions = true );
void updateAboutBackendAction();