svn path=/trunk/KDE/kdegraphics/kdvi/; revision=461082
This commit is contained in:
Stefan Kebekus 2005-09-16 12:18:31 +00:00
parent 46bb5ad692
commit 3d2b6db73e
3 changed files with 131 additions and 4 deletions

View file

@ -52,6 +52,7 @@
#include <kdebug.h>
#include <klocale.h>
#include <ktempfile.h>
#include <qdir.h>
#include <qfileinfo.h>
#include <stdlib.h>
@ -75,6 +76,7 @@ dvifile::dvifile(const dvifile *old, fontPool *fp)
numberOfExternalPSFiles = 0;
numberOfExternalNONPSFiles = 0;
sourceSpecialMarker = old->sourceSpecialMarker;
have_complainedAboutMissingPDF2PS = false;
dviData = old->dviData.copy();
@ -278,7 +280,8 @@ dvifile::dvifile(QString fname, fontPool *pool)
numberOfExternalNONPSFiles = 0;
font_pool = pool;
sourceSpecialMarker = true;
have_complainedAboutMissingPDF2PS = false;
QFile file(fname);
filename = file.name();
file.open( QIODevice::ReadOnly );
@ -315,6 +318,13 @@ dvifile::~dvifile()
kdDebug(4300) << "destroy dvi-file" << endl;
#endif
// Delete converted PDF files
QMapIterator<QString, QString> i(convertedFiles);
while (i.hasNext()) {
i.next();
QFile::remove(i.value());
}
if (suggestedPageSize != 0)
delete suggestedPageSize;
if (font_pool != 0)
@ -351,6 +361,65 @@ void dvifile::renumber()
}
QString dvifile::convertPDFtoPS(const QString &PDFFilename, QString *converrorms)
{
// Check if the PDFFile is known
QMap<QString, QString>::Iterator it = convertedFiles.find(PDFFilename);
if (it != convertedFiles.end()) {
// PDF-File is known. Good.
return it.data();
}
// Get the name of a temporary file
KTempFile tmpfile(QString::null, ".ps");
QString convertedFileName = tmpfile.name();
tmpfile.close();
tmpfile.unlink();
// Use pdf2ps to do the conversion
KProcIO proc;
proc << "pdf2ps" << PDFFilename << convertedFileName;
if (proc.start(KProcess::Block, true) == false) {
convertedFiles[PDFFilename] = QString::null; // Indicates that conversion failed, won't try again.
if ((converrorms != 0) && (have_complainedAboutMissingPDF2PS == false)) {
*converrorms = i18n("<qt><p>The external program <strong>pdf2ps</strong> could not be started. As a result, "
"the PDF-file %1 could not be converted to PostScript. Some graphic elements in your "
"document will therefore not be displayed.</p>"
"<p><b>Possible reason:</b> The program <strong>pdf2ps</strong> is perhaps not installed "
"on your system, or it cannot be found in the current search path.</p>"
"<p><b>What you can do:</b> The program <strong>pdf2ps</strong> program is normally "
"contained in distributions of the ghostscript PostScript interpreter system. If "
"ghostscipt is not installed on your system, you could install it now. "
"If you are sure that ghostscript is installed, please try to use <strong>pdf2ps</strong> "
"from the command line to check if it really works.</p><p><b>PATH:</b> %2</p></qt>").arg(PDFFilename).arg(getenv("PATH"));
have_complainedAboutMissingPDF2PS = true;
}
return QString::null;
}
if ( !QFile::exists(convertedFileName) || !proc.normalExit() || (proc.exitStatus() != 0) ) {
convertedFiles[PDFFilename] = QString::null; // Indicates that conversion failed, won't try again.
if (converrorms != 0) {
QString outp, outl;
while(proc.readln(outl) != -1)
outp += outl;
*converrorms = i18n("<qt><p>The PDF-file %1 could not be converted to PostScript. Some graphic elements in your "
"document will therefore not be displayed.</p>"
"<p><b>Possible reason:</b> The file %1 might be broken, or might not be a PDF-file at all. "
"This is the output of the <strong>pdf2ps</strong> program that KDVI used:</p>"
"<p><strong>%2</strong></p></qt>").arg(PDFFilename).arg(outp);
}
return QString::null;
}
// Save name of converted file to buffer, so PDF file won't be
// converted again, and files can be deleted when *this is
// deconstructed.
convertedFiles[PDFFilename] = convertedFileName;
return convertedFileName;
}
bool dvifile::saveAs(const QString &filename)
{
if (dvi_Data() == 0)

View file

@ -5,7 +5,7 @@
// Class that represents a DVI file. Part of KDVI - A DVI previewing
// plugin for kviewshell.
//
// (C) 2004 Stefan Kebekus. Distributed under the GPL.
// (C) 2004-2005 Stefan Kebekus. Distributed under the GPL.
//
#ifndef _DVIFILE_H
@ -18,6 +18,7 @@
#include <qstring.h>
//Added by qt3to4:
#include <Q3MemArray>
#include <qmap.h>
#include "bigEndianByteReader.h"
@ -99,6 +100,26 @@ class dvifile : public bigEndianByteReader
renumbers the pages. */
void renumber();
/** PDF to PS file conversion
This utility method takes the name of a PDF-file, and attempts to
convert it to a PS file. The dvifile internally keeps a list of
converted files, to do two thigs:
- convert files only once.
- delete all converted files on destruction
@warning The internal buffer can lead to difficulties if filenames
of PDF-files are not unique: if the content of a PDF file is
changed and this method is called a second time with the same file
name, the method will then NOT convert the file, but simply return
the name from the buffer
@returns The name of the PS file, or QString::null on failure.
*/
QString convertPDFtoPS(const QString &PDFFilename, QString *converrorms=0);
private:
/** process_preamble reads the information in the preamble and
stores it into global variables for later use. */
@ -118,6 +139,19 @@ class dvifile : public bigEndianByteReader
double cmPerDVIunit;
Q3MemArray<Q_UINT8> dviData;
/** Map of filenames for converted PDF files
This map contains names of PDF files that were converted to
PostScript. The key is the name of the PDF file, the data the name
of the associated PS file, or QString::null, if the file could not
be converted. The PS files are deleted when the DVI-file is
destructed. */
QMap<QString, QString> convertedFiles;
/** Flag, used so that KDVI complains only once about a missing
"PDF2PS" utility. Set to "false" in the constructor. */
bool have_complainedAboutMissingPDF2PS;
};
#endif //ifndef _DVIFILE_H

View file

@ -15,6 +15,7 @@
#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kmimetype.h>
#include <kprocess.h>
#include <kprocio.h>
@ -84,7 +85,11 @@ void dviRenderer::prescan_embedPS(char *cp, Q_UINT8 *beginningOfSpecialCommand)
// Now locate the Gfx file on the hard disk...
EPSfilename = ghostscript_interface::locateEPSfile(EPSfilename, dviFile);
// If the EPSfilename really points to a PDF file, convert that file now.
if (ending == "pdf")
EPSfilename = dviFile->convertPDFtoPS(EPSfilename);
if (!QFile::exists(EPSfilename)) {
// Find the number of the page
Q_UINT32 currentOffset = beginningOfSpecialCommand - dviFile->dvi_Data();
@ -92,7 +97,10 @@ void dviRenderer::prescan_embedPS(char *cp, Q_UINT8 *beginningOfSpecialCommand)
for(page=0; page < dviFile->total_pages; page++)
if ((dviFile->page_offset[page] <= currentOffset) && (currentOffset <= dviFile->page_offset[page+1]))
break;
errorMsg += i18n("Page %1: The PostScript file <strong>%2</strong> could not be found.<br>").arg(page+1).arg(originalFName);
if (ending == "pdf")
errorMsg += i18n("Page %1: The PDF file <strong>%2</strong> could not be converted to PostScript.<br>").arg(page+1).arg(originalFName);
else
errorMsg += i18n("Page %1: The PostScript file <strong>%2</strong> could not be found.<br>").arg(page+1).arg(originalFName);
embedPS_progress->progressBar()->advance(1);
qApp->processEvents();
return;
@ -408,6 +416,22 @@ void dviRenderer::prescan_ParsePSFileSpecial(QString cp)
// Now locate the Gfx file on the hard disk...
EPSfilename = ghostscript_interface::locateEPSfile(EPSfilename, dviFile);
// If the EPSfilename really points to a PDF file, convert that file now.
if (ending == "pdf") {
QString convErrorMsg;
QString oEPSfilename = EPSfilename;
emit setStatusBarText( i18n("Converting PDF-file %1...").arg(EPSfilename) );
EPSfilename = dviFile->convertPDFtoPS(EPSfilename, &convErrorMsg);
emit setStatusBarText( QString::null );
if (convErrorMsg.isEmpty() != true) {
KMessageBox::detailedError(parentWidget,
i18n("<qt><strong>File conversion error!</strong> KDVI was not able to convert the external "
"PDF-file <strong>%1</strong> into PostScript. Expect missing graphics or graphic errors.</qt>").arg(oEPSfilename),
convErrorMsg, i18n("PDF/PS conversion error"));
return;
}
}
// Now parse the arguments.
int llx = 0;