2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-05-30 08:50:51 +00:00

Add QPDFJob::registerProgressReporter

This commit is contained in:
Jay Berkenbilt 2022-06-18 20:44:44 -04:00
parent 3a7ee7e938
commit 87412eb05b
7 changed files with 72 additions and 13 deletions

5
TODO
View File

@ -14,7 +14,10 @@ Next:
Pending changes: Pending changes:
* Allow users to supply a custom progress reporter for QPDFJob * Allow users to supply a custom progress reporter for QPDFJob. If one
is provided, use it instead of creating one. Then expose to the C
API. Consider also exposing a way to set a new logger and to get the
logger from QPDF and QPDFJob in the C API.
* Check about runpath in the linux-bin distribution. I think the * Check about runpath in the linux-bin distribution. I think the
appimage build specifically is setting the runpath, which is appimage build specifically is setting the runpath, which is
actually desirable in this case. Make sure to understand and actually desirable in this case. Make sure to understand and

View File

@ -134,6 +134,14 @@ class QPDFJob
"configure logger from getLogger() or call setLogger()")]] QPDF_DLL void "configure logger from getLogger() or call setLogger()")]] QPDF_DLL void
setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
// You can register a custom progress reporter to be called by
// QPDFWriter (see QPDFWriter::registerProgressReporter). This is
// only called if you also request progress reporting through
// normal configuration methods (e.g., pass --progress, call
// config()->progress, etc.)
QPDF_DLL
void registerProgressReporter(std::function<void(int)>);
// Check to make sure no contradictory options have been // Check to make sure no contradictory options have been
// specified. This is called automatically after initializing from // specified. This is called automatically after initializing from
// argv or json and is also called by run, but you can call it // argv or json and is also called by run, but you can call it
@ -579,6 +587,7 @@ class QPDFJob
bool decrypt; bool decrypt;
int split_pages; int split_pages;
bool progress; bool progress;
std::function<void(int)> progress_handler;
bool suppress_warnings; bool suppress_warnings;
bool warnings_exit_zero; bool warnings_exit_zero;
bool copy_encryption; bool copy_encryption;

View File

@ -323,6 +323,7 @@ QPDFJob::Members::Members() :
decrypt(false), decrypt(false),
split_pages(0), split_pages(0),
progress(false), progress(false),
progress_handler(nullptr),
suppress_warnings(false), suppress_warnings(false),
warnings_exit_zero(false), warnings_exit_zero(false),
copy_encryption(false), copy_encryption(false),
@ -463,6 +464,11 @@ QPDFJob::setOutputStreams(std::ostream* out, std::ostream* err)
this->m->log->setOutputStreams(out, err); this->m->log->setOutputStreams(out, err);
} }
void
QPDFJob::registerProgressReporter(std::function<void(int)> handler) {
this->m->progress_handler = handler;
}
void void
QPDFJob::doIfVerbose( QPDFJob::doIfVerbose(
std::function<void(Pipeline&, std::string const& prefix)> fn) std::function<void(Pipeline&, std::string const& prefix)> fn)
@ -3146,16 +3152,23 @@ QPDFJob::setWriterOptions(QPDF& pdf, QPDFWriter& w)
w.forcePDFVersion(version, extension_level); w.forcePDFVersion(version, extension_level);
} }
if (m->progress) { if (m->progress) {
char const* outfilename = this->m->outfilename if (this->m->progress_handler) {
? this->m->outfilename.get() w.registerProgressReporter(
: "standard output"; std::shared_ptr<QPDFWriter::ProgressReporter>(
w.registerProgressReporter( new QPDFWriter::FunctionProgressReporter(
std::shared_ptr<QPDFWriter::ProgressReporter>( this->m->progress_handler)));
// line-break } else {
new ProgressReporter( char const* outfilename = this->m->outfilename
*this->m->log->getInfo(), ? this->m->outfilename.get()
this->m->message_prefix, : "standard output";
outfilename))); w.registerProgressReporter(
std::shared_ptr<QPDFWriter::ProgressReporter>(
// line-break
new ProgressReporter(
*this->m->log->getInfo(),
this->m->message_prefix,
outfilename)));
}
} }
} }

View File

@ -4,10 +4,15 @@ use warnings;
my $seen = 0; my $seen = 0;
while (<>) while (<>)
{ {
if (m/write progress: (?:10)?0\%/) if (m/write progress: 0\%/)
{ {
print; print;
} }
elsif (m/write progress: 100\%/)
{
print;
$seen = 0;
}
elsif (m/write progress: /) elsif (m/write progress: /)
{ {
if (! $seen) if (! $seen)

View File

@ -1,4 +1,11 @@
normal normal
qpdf: a.pdf: write progress: 0%
....other write progress....
qpdf: a.pdf: write progress: 100%
custom progress reporter
custom write progress: 0%
....other write progress....
custom write progress: 100%
error caught by check error caught by check
finished config finished config
usage: an input file name is required usage: an input file name is required

View File

@ -87,7 +87,8 @@ $td->runtest("QPDFJob json partial",
{$td->FILE => "job-partial-json.out", $td->EXIT_STATUS => 0}, {$td->FILE => "job-partial-json.out", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES); $td->NORMALIZE_NEWLINES);
$td->runtest("QPDFJob API", $td->runtest("QPDFJob API",
{$td->COMMAND => "test_driver 84 -"}, {$td->COMMAND => "test_driver 84 -",
$td->FILTER => "perl filter-progress.pl"},
{$td->FILE => "job-api.out", $td->EXIT_STATUS => 0}, {$td->FILE => "job-api.out", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES); $td->NORMALIZE_NEWLINES);
$td->runtest("check output", $td->runtest("check output",

View File

@ -2937,6 +2937,27 @@ test_84(QPDF& pdf, char const* arg2)
->qdf() ->qdf()
->deterministicId() ->deterministicId()
->objectStreams("preserve") ->objectStreams("preserve")
->progress()
->checkConfiguration();
j.run();
assert(j.getExitCode() == 0);
assert(!j.hasWarnings());
assert(j.getEncryptionStatus() == 0);
}
std::cout << "custom progress reporter" << std::endl;
{
QPDFJob j;
j.registerProgressReporter([](int p) {
std::cout << "custom write progress: " << p << "%" << std::endl;
});
j.config()
->inputFile("minimal.pdf")
->outputFile("a.pdf")
->qdf()
->deterministicId()
->objectStreams("preserve")
->progress()
->checkConfiguration(); ->checkConfiguration();
j.run(); j.run();
assert(j.getExitCode() == 0); assert(j.getExitCode() == 0);