mirror of https://github.com/JakubMelka/PDF4QT.git
Text codec used when redirecting output
This commit is contained in:
parent
7bded071ea
commit
03f7f01c7d
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "pdfoutputformatter.h"
|
#include "pdfoutputformatter.h"
|
||||||
|
|
||||||
|
#include <QTextCodec>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QXmlStreamWriter>
|
#include <QXmlStreamWriter>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
@ -91,7 +92,7 @@ private:
|
||||||
class PDFXmlOutputFormatterImpl : public PDFOutputFormatterImpl
|
class PDFXmlOutputFormatterImpl : public PDFOutputFormatterImpl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PDFXmlOutputFormatterImpl();
|
PDFXmlOutputFormatterImpl(QString codec);
|
||||||
|
|
||||||
virtual void beginElement(PDFOutputFormatter::Element type, QString name, QString description, Qt::Alignment alignment, int reference) override;
|
virtual void beginElement(PDFOutputFormatter::Element type, QString name, QString description, Qt::Alignment alignment, int reference) override;
|
||||||
virtual void endElement() override;
|
virtual void endElement() override;
|
||||||
|
@ -109,7 +110,7 @@ private:
|
||||||
class PDFHtmlOutputFormatterImpl : public PDFOutputFormatterImpl
|
class PDFHtmlOutputFormatterImpl : public PDFOutputFormatterImpl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PDFHtmlOutputFormatterImpl();
|
PDFHtmlOutputFormatterImpl(QString codecName);
|
||||||
|
|
||||||
virtual void beginElement(PDFOutputFormatter::Element type, QString name, QString description, Qt::Alignment alignment, int reference) override;
|
virtual void beginElement(PDFOutputFormatter::Element type, QString name, QString description, Qt::Alignment alignment, int reference) override;
|
||||||
virtual void endElement() override;
|
virtual void endElement() override;
|
||||||
|
@ -308,14 +309,17 @@ const PDFTextOutputFormatterImpl::TableCell& PDFTextOutputFormatterImpl::getTabl
|
||||||
return dummy;
|
return dummy;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFHtmlOutputFormatterImpl::PDFHtmlOutputFormatterImpl() :
|
PDFHtmlOutputFormatterImpl::PDFHtmlOutputFormatterImpl(QString codecName) :
|
||||||
m_string(),
|
m_string(),
|
||||||
m_streamWriter(&m_string),
|
m_streamWriter(&m_string),
|
||||||
m_depth(0),
|
m_depth(0),
|
||||||
m_headerDepth(1),
|
m_headerDepth(1),
|
||||||
m_elementStack()
|
m_elementStack()
|
||||||
{
|
{
|
||||||
|
if (QTextCodec* codec = QTextCodec::codecForName(codecName.toLatin1()))
|
||||||
|
{
|
||||||
|
m_streamWriter.setCodec(codec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFHtmlOutputFormatterImpl::beginElement(PDFOutputFormatter::Element type, QString name, QString description, Qt::Alignment alignment, int reference)
|
void PDFHtmlOutputFormatterImpl::beginElement(PDFOutputFormatter::Element type, QString name, QString description, Qt::Alignment alignment, int reference)
|
||||||
|
@ -483,7 +487,7 @@ void PDFHtmlOutputFormatterImpl::endl()
|
||||||
m_streamWriter.writeEndElement();
|
m_streamWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFXmlOutputFormatterImpl::PDFXmlOutputFormatterImpl() :
|
PDFXmlOutputFormatterImpl::PDFXmlOutputFormatterImpl(QString codecName) :
|
||||||
m_string(),
|
m_string(),
|
||||||
m_streamWriter(&m_string),
|
m_streamWriter(&m_string),
|
||||||
m_depth(0)
|
m_depth(0)
|
||||||
|
@ -491,6 +495,11 @@ PDFXmlOutputFormatterImpl::PDFXmlOutputFormatterImpl() :
|
||||||
m_streamWriter.setAutoFormatting(true);
|
m_streamWriter.setAutoFormatting(true);
|
||||||
m_streamWriter.setAutoFormattingIndent(2);
|
m_streamWriter.setAutoFormattingIndent(2);
|
||||||
|
|
||||||
|
if (QTextCodec* codec = QTextCodec::codecForName(codecName.toLatin1()))
|
||||||
|
{
|
||||||
|
m_streamWriter.setCodec(codec);
|
||||||
|
}
|
||||||
|
|
||||||
m_namespace = "https://github.com/JakubMelka/PdfForQt";
|
m_namespace = "https://github.com/JakubMelka/PdfForQt";
|
||||||
m_prefix = "pdftool";
|
m_prefix = "pdftool";
|
||||||
}
|
}
|
||||||
|
@ -575,7 +584,7 @@ QString PDFXmlOutputFormatterImpl::getString() const
|
||||||
return m_string;
|
return m_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFOutputFormatter::PDFOutputFormatter(Style style) :
|
PDFOutputFormatter::PDFOutputFormatter(Style style, QString codecName) :
|
||||||
m_impl(nullptr)
|
m_impl(nullptr)
|
||||||
{
|
{
|
||||||
switch (style)
|
switch (style)
|
||||||
|
@ -585,11 +594,11 @@ PDFOutputFormatter::PDFOutputFormatter(Style style) :
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Style::Xml:
|
case Style::Xml:
|
||||||
m_impl = new PDFXmlOutputFormatterImpl();
|
m_impl = new PDFXmlOutputFormatterImpl(codecName);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Style::Html:
|
case Style::Html:
|
||||||
m_impl = new PDFHtmlOutputFormatterImpl();
|
m_impl = new PDFHtmlOutputFormatterImpl(codecName);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,19 +630,39 @@ QString PDFOutputFormatter::getString() const
|
||||||
return m_impl->getString();
|
return m_impl->getString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFConsole::writeText(QString text)
|
void PDFConsole::writeText(QString text, QString codecName)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), text.utf16(), text.size(), nullptr, nullptr);
|
HANDLE outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
if (!WriteConsoleW(outputHandle, text.utf16(), text.size(), nullptr, nullptr))
|
||||||
|
{
|
||||||
|
// Write console failed. This can happen only, if outputHandle is not handle
|
||||||
|
// to console screen buffer, but, for example a file or a pipe.
|
||||||
|
if (QTextCodec* codec = QTextCodec::codecForName(codecName.toLatin1()))
|
||||||
|
{
|
||||||
|
QByteArray encodedData = codec->fromUnicode(text);
|
||||||
|
WriteFile(outputHandle, encodedData.constData(), encodedData.size(), nullptr, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
QTextStream(stdout) << text;
|
QTextStream(stdout) << text;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFConsole::writeError(QString text)
|
void PDFConsole::writeError(QString text, QString codecName)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), text.utf16(), text.size(), nullptr, nullptr);
|
HANDLE outputHandle = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
if (!WriteConsoleW(outputHandle, text.utf16(), text.size(), nullptr, nullptr))
|
||||||
|
{
|
||||||
|
// Write console failed. This can happen only, if outputHandle is not handle
|
||||||
|
// to console screen buffer, but, for example a file or a pipe.
|
||||||
|
if (QTextCodec* codec = QTextCodec::codecForName(codecName.toLatin1()))
|
||||||
|
{
|
||||||
|
QByteArray encodedData = codec->fromUnicode(text);
|
||||||
|
WriteFile(outputHandle, encodedData.constData(), encodedData.size(), nullptr, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
QTextStream(stdout) << text;
|
QTextStream(stdout) << text;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
Html
|
Html
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit PDFOutputFormatter(Style style);
|
explicit PDFOutputFormatter(Style style, QString codecName);
|
||||||
~PDFOutputFormatter();
|
~PDFOutputFormatter();
|
||||||
|
|
||||||
enum class Element
|
enum class Element
|
||||||
|
@ -97,10 +97,10 @@ class PDFConsole
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// Writes text to the console
|
/// Writes text to the console
|
||||||
static void writeText(QString text);
|
static void writeText(QString text, QString codecName);
|
||||||
|
|
||||||
/// Writes error to the console
|
/// Writes error to the console
|
||||||
static void writeError(QString text);
|
static void writeError(QString text, QString codecName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit PDFConsole() = delete;
|
explicit PDFConsole() = delete;
|
||||||
|
|
|
@ -58,7 +58,7 @@ QString PDFToolHelpApplication::getStandardString(StandardString standardString)
|
||||||
|
|
||||||
int PDFToolHelpApplication::execute(const PDFToolOptions& options)
|
int PDFToolHelpApplication::execute(const PDFToolOptions& options)
|
||||||
{
|
{
|
||||||
PDFOutputFormatter formatter(options.outputStyle);
|
PDFOutputFormatter formatter(options.outputStyle, options.outputCodec);
|
||||||
formatter.beginDocument("help", PDFToolTranslationContext::tr("PDFTool help"));
|
formatter.beginDocument("help", PDFToolTranslationContext::tr("PDFTool help"));
|
||||||
formatter.endl();
|
formatter.endl();
|
||||||
|
|
||||||
|
@ -107,9 +107,27 @@ int PDFToolHelpApplication::execute(const PDFToolOptions& options)
|
||||||
|
|
||||||
formatter.endTable();
|
formatter.endTable();
|
||||||
|
|
||||||
|
formatter.endl();
|
||||||
|
formatter.beginHeader("text-output", PDFToolTranslationContext::tr("Text Encoding"));
|
||||||
|
|
||||||
|
formatter.writeText("header", PDFToolTranslationContext::tr("When you redirect console to a file, then specific codec is used to transform output text to target encoding. UTF-8 encoding is used by default. For XML output, you should use only UTF-8 codec. Available codecs:"));
|
||||||
|
formatter.endl();
|
||||||
|
|
||||||
|
QList<QByteArray> codecs = QTextCodec::availableCodecs();
|
||||||
|
QStringList codecNames;
|
||||||
|
for (const QByteArray& codecName : codecs)
|
||||||
|
{
|
||||||
|
codecNames << QString::fromLatin1(codecName);
|
||||||
|
}
|
||||||
|
formatter.writeText("codecs", codecNames.join(", "));
|
||||||
|
formatter.endl();
|
||||||
|
formatter.writeText("default-codec", PDFToolTranslationContext::tr("Suggested codec: UTF-8 or %1").arg(QString::fromLatin1(QTextCodec::codecForLocale()->name())));
|
||||||
|
|
||||||
|
formatter.endHeader();
|
||||||
|
|
||||||
formatter.endDocument();
|
formatter.endDocument();
|
||||||
|
|
||||||
PDFConsole::writeText(formatter.getString());
|
PDFConsole::writeText(formatter.getString(), options.outputCodec);
|
||||||
return ExitSuccess;
|
return ExitSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +148,7 @@ void PDFToolAbstractApplication::initializeCommandLineParser(QCommandLineParser*
|
||||||
if (optionFlags.testFlag(ConsoleFormat))
|
if (optionFlags.testFlag(ConsoleFormat))
|
||||||
{
|
{
|
||||||
parser->addOption(QCommandLineOption("console-format", "Console output text format (valid values: text|xml|html).", "console-format", "text"));
|
parser->addOption(QCommandLineOption("console-format", "Console output text format (valid values: text|xml|html).", "console-format", "text"));
|
||||||
|
parser->addOption(QCommandLineOption("text-codec", QString("Text codec used when writing text output to redirected standard output. UTF-8 is default."), "text-codec", "UTF-8"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optionFlags.testFlag(OpenDocument))
|
if (optionFlags.testFlag(OpenDocument))
|
||||||
|
@ -184,11 +203,13 @@ PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser
|
||||||
{
|
{
|
||||||
if (!consoleFormat.isEmpty())
|
if (!consoleFormat.isEmpty())
|
||||||
{
|
{
|
||||||
PDFConsole::writeError(PDFToolTranslationContext::tr("Unknown console format '%1'. Defaulting to text console format.").arg(consoleFormat));
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Unknown console format '%1'. Defaulting to text console format.").arg(consoleFormat), options.outputCodec);
|
||||||
}
|
}
|
||||||
|
|
||||||
options.outputStyle = PDFOutputFormatter::Style::Text;
|
options.outputStyle = PDFOutputFormatter::Style::Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options.outputCodec = parser->value("text-codec");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optionFlags.testFlag(OpenDocument))
|
if (optionFlags.testFlag(OpenDocument))
|
||||||
|
@ -225,7 +246,7 @@ PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser
|
||||||
}
|
}
|
||||||
else if (!dateFormat.isEmpty())
|
else if (!dateFormat.isEmpty())
|
||||||
{
|
{
|
||||||
PDFConsole::writeError(PDFToolTranslationContext::tr("Unknown console date/time format '%1'. Defaulting to short date/time format.").arg(dateFormat));
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Unknown console date/time format '%1'. Defaulting to short date/time format.").arg(dateFormat), options.outputCodec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,13 +280,13 @@ bool PDFToolAbstractApplication::readDocument(const PDFToolOptions& options, pdf
|
||||||
|
|
||||||
case pdf::PDFDocumentReader::Result::Cancelled:
|
case pdf::PDFDocumentReader::Result::Cancelled:
|
||||||
{
|
{
|
||||||
PDFConsole::writeError(PDFToolTranslationContext::tr("Invalid password provided."));
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Invalid password provided."), options.outputCodec);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
case pdf::PDFDocumentReader::Result::Failed:
|
case pdf::PDFDocumentReader::Result::Failed:
|
||||||
{
|
{
|
||||||
PDFConsole::writeError(PDFToolTranslationContext::tr("Error occured during document reading. %1").arg(reader.getErrorMessage()));
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Error occured during document reading. %1").arg(reader.getErrorMessage()), options.outputCodec);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +299,7 @@ bool PDFToolAbstractApplication::readDocument(const PDFToolOptions& options, pdf
|
||||||
|
|
||||||
for (const QString& warning : reader.getWarnings())
|
for (const QString& warning : reader.getWarnings())
|
||||||
{
|
{
|
||||||
PDFConsole::writeError(PDFToolTranslationContext::tr("Warning: %1").arg(warning));
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Warning: %1").arg(warning), options.outputCodec);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -42,6 +42,7 @@ struct PDFToolOptions
|
||||||
{
|
{
|
||||||
// For option 'ConsoleFormat'
|
// For option 'ConsoleFormat'
|
||||||
PDFOutputFormatter::Style outputStyle = PDFOutputFormatter::Style::Text;
|
PDFOutputFormatter::Style outputStyle = PDFOutputFormatter::Style::Text;
|
||||||
|
QString outputCodec;
|
||||||
|
|
||||||
// For option 'OpenDocument'
|
// For option 'OpenDocument'
|
||||||
QString document;
|
QString document;
|
||||||
|
|
|
@ -52,7 +52,7 @@ int PDFToolVerifySignaturesApplication::execute(const PDFToolOptions& options)
|
||||||
// No document specified?
|
// No document specified?
|
||||||
if (options.document.isEmpty())
|
if (options.document.isEmpty())
|
||||||
{
|
{
|
||||||
PDFConsole::writeError(PDFToolTranslationContext::tr("No document specified."));
|
PDFConsole::writeError(PDFToolTranslationContext::tr("No document specified."), options.outputCodec);
|
||||||
return ErrorNoDocumentSpecified;
|
return ErrorNoDocumentSpecified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ int PDFToolVerifySignaturesApplication::execute(const PDFToolOptions& options)
|
||||||
|
|
||||||
case pdf::PDFDocumentReader::Result::Failed:
|
case pdf::PDFDocumentReader::Result::Failed:
|
||||||
{
|
{
|
||||||
PDFConsole::writeError(PDFToolTranslationContext::tr("Error occured during document reading. %1").arg(reader.getErrorMessage()));
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Error occured during document reading. %1").arg(reader.getErrorMessage()), options.outputCodec);
|
||||||
return ErrorDocumentReading;
|
return ErrorDocumentReading;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ int PDFToolVerifySignaturesApplication::execute(const PDFToolOptions& options)
|
||||||
|
|
||||||
for (const QString& warning : reader.getWarnings())
|
for (const QString& warning : reader.getWarnings())
|
||||||
{
|
{
|
||||||
PDFConsole::writeError(PDFToolTranslationContext::tr("Warning: %1").arg(warning));
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Warning: %1").arg(warning), options.outputCodec);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify signatures
|
// Verify signatures
|
||||||
|
@ -107,7 +107,7 @@ int PDFToolVerifySignaturesApplication::execute(const PDFToolOptions& options)
|
||||||
pdf::PDFForm form = pdf::PDFForm::parse(&document, document.getCatalog()->getFormObject());
|
pdf::PDFForm form = pdf::PDFForm::parse(&document, document.getCatalog()->getFormObject());
|
||||||
std::vector<pdf::PDFSignatureVerificationResult> signatures = pdf::PDFSignatureHandler::verifySignatures(form, reader.getSource(), parameters);
|
std::vector<pdf::PDFSignatureVerificationResult> signatures = pdf::PDFSignatureHandler::verifySignatures(form, reader.getSource(), parameters);
|
||||||
|
|
||||||
PDFOutputFormatter formatter(options.outputStyle);
|
PDFOutputFormatter formatter(options.outputStyle, options.outputCodec);
|
||||||
formatter.beginDocument("signatures", PDFToolTranslationContext::tr("Digital signatures/timestamps verification of %1").arg(options.document));
|
formatter.beginDocument("signatures", PDFToolTranslationContext::tr("Digital signatures/timestamps verification of %1").arg(options.document));
|
||||||
formatter.endl();
|
formatter.endl();
|
||||||
|
|
||||||
|
@ -386,7 +386,7 @@ int PDFToolVerifySignaturesApplication::execute(const PDFToolOptions& options)
|
||||||
|
|
||||||
formatter.endDocument();
|
formatter.endDocument();
|
||||||
|
|
||||||
PDFConsole::writeText(formatter.getString());
|
PDFConsole::writeText(formatter.getString(), options.outputCodec);
|
||||||
return ExitSuccess;
|
return ExitSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -210,6 +210,11 @@ int PDFToolXmlApplication::execute(const PDFToolOptions& options)
|
||||||
writer.setAutoFormattingIndent(2);
|
writer.setAutoFormattingIndent(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (QTextCodec* codec = QTextCodec::codecForName(options.outputCodec.toLatin1()))
|
||||||
|
{
|
||||||
|
writer.setCodec(codec);
|
||||||
|
}
|
||||||
|
|
||||||
QString comment = QString("Processed by %1 %2").arg(QCoreApplication::applicationName(), QCoreApplication::applicationVersion());
|
QString comment = QString("Processed by %1 %2").arg(QCoreApplication::applicationName(), QCoreApplication::applicationVersion());
|
||||||
writer.writeStartDocument();
|
writer.writeStartDocument();
|
||||||
writer.writeComment(comment);
|
writer.writeComment(comment);
|
||||||
|
@ -240,7 +245,7 @@ int PDFToolXmlApplication::execute(const PDFToolOptions& options)
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
writer.writeEndDocument();
|
writer.writeEndDocument();
|
||||||
|
|
||||||
PDFConsole::writeText(xmlString);
|
PDFConsole::writeText(xmlString, options.outputCodec);
|
||||||
return ExitSuccess;
|
return ExitSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue